makefile-lossless 0.3.7

Lossless Parser for Makefiles
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# Make Syntax - Not Yet Supported

This document lists Make syntax features from various Make implementations that are not yet fully supported by the makefile-lossless parser.

## GNU Make Syntax

The following GNU Make features are not yet fully supported:

## Special Target Directives

The following special targets are recognized but not parsed with special handling:

- `.PHONY` - Marks targets that don't create actual files
- `.SUFFIXES` - Defines implicit rule suffixes
- `.PRECIOUS` - Prevents deletion of intermediate files
- `.INTERMEDIATE` - Marks files as intermediate
- `.SECONDARY` - Prevents deletion of intermediate files with no dependencies
- `.DELETE_ON_ERROR` - Deletes target file on error
- `.IGNORE` - Ignores errors in recipes
- `.LOW_RESOLUTION_TIME` - Assumes low resolution timestamps
- `.SILENT` - Suppresses recipe echoing
- `.EXPORT_ALL_VARIABLES` - Exports all variables
- `.NOTPARALLEL` - Disables parallel execution
- `.ONESHELL` - Executes all recipe lines in single shell
- `.POSIX` - Enables POSIX-compliant mode

## Variable Functions

Many GNU Make functions are not explicitly parsed or handled:

### String Functions
- `$(strip string)` - Remove leading/trailing whitespace
- `$(findstring find,in)` - Find substring
- `$(filter pattern...,text)` - Keep words matching patterns
- `$(filter-out pattern...,text)` - Remove words matching patterns
- `$(sort list)` - Sort and remove duplicates
- `$(word n,text)` - Extract nth word
- `$(wordlist s,e,text)` - Extract word range
- `$(words text)` - Count words
- `$(firstword names...)` - Get first word
- `$(lastword names...)` - Get last word

### File Name Functions
- `$(dir names...)` - Extract directory part
- `$(notdir names...)` - Remove directory part
- `$(suffix names...)` - Extract file suffixes
- `$(basename names...)` - Remove file suffixes
- `$(addsuffix suffix,names...)` - Add suffix to names
- `$(addprefix prefix,names...)` - Add prefix to names
- `$(join list1,list2)` - Join two lists pairwise
- `$(realpath names...)` - Get canonical absolute path
- `$(abspath names...)` - Get absolute path

### Control Flow Functions
- `$(if condition,then-part[,else-part])` - Conditional expansion
- `$(foreach var,list,text)` - Iterate over list
- `$(call variable,param,...)` - Call user-defined function
- `$(eval text)` - Evaluate as makefile syntax
- `$(value variable)` - Get raw variable value
- `$(origin variable)` - Get variable origin
- `$(flavor variable)` - Get variable flavor

## Advanced Conditional Features

While basic conditionals (`ifdef`, `ifndef`, `ifeq`, `ifneq`, `else`, `endif`) are supported, the following are not fully handled:

- `elif` statements (partially supported, treated similar to `else`)
- Complex conditional expressions with functions
- Nested function calls within conditionals

## Pattern Rules and Implicit Rules (Partially Supported)

- Pattern rules with `%` wildcards (e.g., `%.o: %.c`) - **BASIC SUPPORT** (parsed but no special handling)
- Static pattern rules (e.g., `objects: %.o: %.c`)
- Implicit rule chains
- `.SUFFIXES` based implicit rules
- Double-suffix rules (e.g., `.c.o:`)
- Single-suffix rules (e.g., `.c:`)

## Advanced Recipe Features

- Multi-line recipes with backslash continuation
- Recipe modifiers (`@`, `-`, `+`)
- Shell function calls within recipes
- Recipe-specific variable assignments

## Variable Assignment Operators

While basic assignment operators are supported, special handling may be missing for:

- `?=` (conditional assignment)
- `::=` (POSIX simple assignment)
- `:::=` (immediate assignment)
- `!=` (shell assignment)

## Include Directives (Partially Supported)

Basic include directives are supported, but advanced features may be missing:

- `include` directive - **SUPPORTED**
- `-include` directive (ignore errors) - **SUPPORTED**
- `sinclude` directive (synonym for `-include`) - **SUPPORTED**
- Multiple files in single include (e.g., `include file1.mk file2.mk`)
- Wildcard expansion in include paths (e.g., `include *.mk`)
- Variable expansion in include paths - **PARTIALLY SUPPORTED**

## Order-Only Prerequisites

- Syntax: `targets: normal-prerequisites | order-only-prerequisites`

## Double-Colon Rules

- Rules with `::` instead of `:` for independent rules

## Define/Endef Multi-line Variables

```make
define variable
multi-line
value
endef
```

## Automatic Variables (Partially Supported)

Special variables in recipes are recognized as variables but not specially interpreted:

- `$@` - Target name - **PARSED AS VARIABLE** (no special handling)
- `$<` - First prerequisite - **PARSED AS VARIABLE** (no special handling)
- `$^` - All prerequisites - **PARSED AS VARIABLE** (no special handling)
- `$?` - Prerequisites newer than target - **PARSED AS VARIABLE** (no special handling)
- `$*` - Stem of pattern rule - **PARSED AS VARIABLE** (no special handling)
- `$+` - All prerequisites with duplicates - **PARSED AS VARIABLE** (no special handling)
- `$|` - Order-only prerequisites - **PARSED AS VARIABLE** (no special handling)
- `$%` - Archive member - **PARSED AS VARIABLE** (no special handling)
- `$(@D)` - Directory part of target
- `$(@F)` - File part of target
- `$(<D)`, `$(<F)` - Directory/file parts of first prerequisite
- `$(^D)`, `$(^F)` - Directory/file parts of all prerequisites

## Archive Member Targets

- Syntax: `lib.a(member.o)`

## VPATH and vpath Directives

- `VPATH` variable for search paths
- `vpath` directive for pattern-specific search paths

## Target-specific Variable Assignments

```make
target: variable = value
target: variable := value
```

## Export/Unexport Directives

While `export` is partially supported, full handling may be missing for:

- `export variable`
- `unexport variable`
- `export` without arguments (export all)

## Override Directive

- `override variable = value`
- `override variable := value`

## Private Variables

- `private variable = value`

## Undefine Directive

- `undefine variable`

## GNU Make Specific Extensions

- `.RECIPEPREFIX` - Change recipe prefix character
- `.SHELLFLAGS` - Flags for shell invocation
- `MAKECMDGOALS` - Command line targets
- `.FEATURES` - Available GNU Make features
- `.INCLUDE_DIRS` - Include search directories

## BSD Make Syntax

BSD Make (bmake/pmake) specific features not yet supported:

### Variable Modifiers
- `:U` - Use default value if undefined
- `:D` - Use value if defined
- `:L` - Lowercase conversion
- `:U` - Uppercase conversion
- `:M` - Match pattern
- `:N` - Exclude pattern
- `:O` - Order alphabetically
- `:Q` - Quote shell meta-characters
- `:R` - Reverse order
- `:S/old/new/` - Substitution
- `:T` - Tail (basename)
- `:H` - Head (dirname)
- `:E` - Extension
- `:C/regex/replacement/` - Regex substitution
- `:hash` - Hash value
- `:range[=sep]` - Generate numeric range
- `:ts` - Change separator

### Conditional Operators
- `.if`, `.elif`, `.else`, `.endif` - BSD-style conditionals
- `.ifdef`, `.ifndef` - BSD-style defined checks
- `.ifmake` - Check if target is being made
- `.ifnmake` - Check if target is not being made
- Conditional operators: `==`, `!=`, `>`, `>=`, `<`, `<=`, `&&`, `||`, `!`

### Loop Constructs
- `.for` variable `in` list / `.endfor` - BSD-style loops

### Include Directives
- `.include "file"` - BSD-style include
- `.include <file>` - System include
- `.sinclude` - Silent include

### Special Variables
- `.CURDIR` - Current directory
- `.OBJDIR` - Object directory
- `.TARGETS` - Command line targets
- `.ALLSRC` - All sources (like `$^`)
- `.IMPSRC` - Implied source
- `.PREFIX` - Prefix of target
- `.ARCHIVE` - Archive name
- `.MEMBER` - Archive member
- `.OODATE` - Out-of-date prerequisites

### Special Targets
- `.BEGIN` - Run before anything else
- `.END` - Run after everything else
- `.ERROR` - Run on error
- `.INTERRUPT` - Run on interrupt
- `.MAIN` - Default target
- `.MAKEFLAGS` - Flags to pass to sub-makes
- `.MFLAGS` - Another way to pass flags
- `.NOTMAIN` - Not the main target
- `.OPTIONAL` - Optional dependencies
- `.ORDER` - Order dependencies
- `.PATH` - Search path for files
- `.SHELL` - Shell to use

## POSIX Make Syntax

POSIX-compliant features that may not be fully supported:

### Inference Rules
- `.c.o:` - Suffix rules
- Single suffix rules (`.c:`)
- Double suffix rules (`.c.o:`)

### Macro String Substitution
- `$(macro:str1=str2)` - Substitution in expansion

### Internal Macros
- `$$@` - Current target (in prerequisites)
- `$$<` - Current dependency
- `$$*` - Current stem

### Special Targets
- `.DEFAULT` - Default rule
- `.IGNORE` - Ignore errors
- `.PRECIOUS` - Don't delete on interrupt
- `.SILENT` - Don't echo commands
- `.SUFFIXES` - List of suffixes
- `.SCCS_GET` - SCCS retrieval

## Microsoft NMAKE Syntax

NMAKE-specific features not supported:

### Preprocessing Directives
- `!IF` / `!ELSEIF` / `!ELSE` / `!ENDIF` - Conditionals
- `!IFDEF` / `!IFNDEF` - Defined checks
- `!ERROR` - Generate error
- `!MESSAGE` - Display message
- `!INCLUDE` - Include file
- `!CMDSWITCHES` - Set command switches
- `!UNDEF` - Undefine macro

### Special Macros
- `$?` - Dependencies newer than target
- `$**` - All dependencies
- `$$@` - Current target (full path)
- `$(**)` - All dependencies (full paths)
- `$<` - Dependency in inference rule
- `$(?)` - Dependencies newer than target (full paths)

### Filename Macros and Modifiers
- `$(@D)` - Directory of target
- `$(@B)` - Base name of target
- `$(@F)` - File name of target
- `$(@R)` - File name without extension

### Batch Mode Rules
- `{frompath}.fromext{topath}.toext::` - Batch inference rules

### Inline Files
```nmake
target: dependency
    command <<filename
inline file contents
<<
```

### Directives
- `.IGNORE:` - Ignore errors
- `.PRECIOUS:` - Keep files
- `.SILENT:` - Suppress echo
- `.SUFFIXES:` - Define suffixes

## SunOS/Solaris Make

Solaris Make specific features:

### Special Targets
- `.KEEP_STATE` - Automatic dependency checking
- `.PARALLEL` - Parallel execution rules
- `.NO_PARALLEL` - Disable parallel execution
- `.WAIT` - Synchronization point
- `.SCCS_GET` - SCCS retrieval rules

### Conditional Macros
- `:=` - Conditional macro assignment
- `target := macro = value` - Target-specific conditional assignment

### Special Macros
- `$$%` - Member of archive library

## AIX Make

AIX Make specific features:

### Special Targets
- `.NOEXPORT` - Don't export variables
- `.MAKE` - Always execute

### Variable References
- `${variable:modifier}` - AIX-specific modifiers

## Additional GNU Make Features Not Supported

### Secondary Expansion
- `.SECONDEXPANSION` - Enable secondary expansion
- `$$` in prerequisites for second expansion

### Guile Integration
- `$(guile ...)` - Embedded Guile Scheme code

### Load Directive
- `load` - Load dynamic extensions

### Output Synchronization
- `.NOTPARALLEL` - Disable parallel execution
- `--output-sync` - Synchronized output in parallel builds

### Job Server
- `+` command prefix for recursive make
- `$(MAKE)` variable for recursive invocation

### Text Transformation Functions
- `$(info text)` - Print information message
- `$(warning text)` - Print warning message
- `$(error text)` - Print error and stop

### File Functions
- `$(file op filename[,text])` - File operations
- `$(file >filename,text)` - Write to file
- `$(file >>filename,text)` - Append to file
- `$(file <filename)` - Read from file

### Debugging Features
- `$(info ...)`, `$(warning ...)`, `$(error ...)` - Debugging output
- `.SHELLSTATUS` - Exit status of last shell command

## Makefile Parsing Limitations

### Comments
- Comments within variable definitions may not be handled correctly
- Escaped newlines in comments

### Line Continuations
- Complex line continuations with mixed tabs and spaces
- Line continuations in conditional expressions

### Shell Integration
- Complex shell escaping
- Nested shell command substitutions
- Shell-specific syntax within recipes

### Globbing and Wildcards
- Advanced globbing patterns
- Recursive wildcards (`**`)

### Unicode and Encoding
- Non-UTF-8 encodings
- Unicode in target/variable names

## Notes

The parser currently focuses on preserving the structure and content of makefiles for lossless round-tripping. Many of these features are preserved in the output but may not have specialized parsing or manipulation APIs. The parser is designed to be permissive and will attempt to parse makefiles with these features without failing, even if it doesn't fully understand their semantics.

Different Make implementations have incompatible syntax and features. This parser primarily targets GNU Make syntax while attempting to be flexible enough to handle common patterns from other implementations.

### Supported Features Summary

The parser **does** support:
- Basic rules with targets, prerequisites, and recipes
- Variable definitions (`=`, `:=`, `+=`)
- Variable references (`$(VAR)`, `${VAR}`)
- Comments (`#`)
- Basic conditionals (`ifdef`, `ifndef`, `ifeq`, `ifneq`, `else`, `endif`)
- Include directives (`include`, `-include`, `sinclude`)
- Export directives (basic form)
- `.PHONY` targets (parsed as regular rules)
- Pattern rules with `%` (basic parsing)
- Shell function calls (`$(shell ...)`)
- Most GNU Make functions (preserved but not interpreted)