#makefile #variables #parse #command #target #comments #rules

bin+lib makefile_parser_rs

Rust library to parse Makefiles, with variables supported

1 unstable release

new 0.1.0 Nov 20, 2024

#12 in #makefile

MIT license

16KB
332 lines

makefile_parser_rs

Description

Built with Rust, makefile_parser_rs is a library main task of which is to parse Makefiles. It supports detecting declared variables and substituting them to commands where they are used.

Parsing details

The parser accepts a valid Makefile and splits it as follows:

  • Comments
  • Variable declarations
  • Rules ** Target ** Dependencies ** Commands

Grammar

makefile	=  { line* }
line		=  { (variable_assignment | comment | rule)? ~ NEWLINE }
comment		=  { whitespace* ~ "#" ~ (ASCII_ALPHANUMERIC | (!NEWLINE ~ ANY))* }

variable	=  { (ASCII_ALPHANUMERIC | "_" | "." | "-" | "+" | "%" | "^" | "&")+ }
value		= @{ ("-" | "--")? ~ (string | variable)? }

variable_assignment = {
	variable
	~
	whitespace*
	~
	("=" | ":=" | "?=")
	~
	whitespace*
	~
	value
}

rule = {
	target ~ ":" ~ (" " ~ dependencies)? ~ NEWLINE ~ commands
}

target			= { (ASCII_ALPHANUMERIC | "_" | ".")+ }
dependencies	= { target ~ (" " ~ target)* }

commands			=  { (command ~ NEWLINE)* ~ command }
command_variable	= @{ "$(" ~ variable ~ ")" }
command_flag		=  { "-" ~ (ASCII_ALPHANUMERIC | "-")+ }
command_arg			=  { !"-" ~ variable+ }

command = {
	whitespace+
	~
	(whitespace+ | command_arg | string | command_variable | command_flag)+
}

string		= @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
whitespace	= _{ " " | "\t" | "\r" }

Usage example

makefile_parser_rs parse Makefile or make run args="parse Makefile"

Example Makefile parse

Given a Makefile:

# This is a simple Makefile

CC = gcc
CFLAGS = -Wall

main: main.cpp my_class.cpp
    clang++ -Wall -o main main.cpp my_class.cpp
    $(CC) $(CFLAGS) -o some_target dependency1 dependency2

another_target: dependency3
    @echo "Building another target"

Running makefile_parser_rs parse example_make, the output is:

Makefile:
|  Variables:
|  |  CC: gcc
|  |  CFLAGS: -Wall
|  Comments:
|  |  # This is a simple Makefile
|  Rule:
|  |  Target: main
|  |  Dependencies:
|  |  |  main.cpp
|  |  |  my_class.cpp
|  |  Commands:
|  |  |  clang++ -Wall -o main main.cpp my_class.cpp
|  |  |  $(CC) $(CFLAGS) -o some_target dependency1 dependency2
|  |  |  gcc -Wall -o some_target dependency1 dependency2

Dependencies

~4MB
~75K SLoC