#!/usr/bin/env perl use warnings; use strict; # # Copyright (C) 2017-2019 Hamish Coleman # # Read through a descriptions file on input and auto generate a list of rules # for building the various files on output # # Each rule input line generates two dependancies: # $filename.orig from $depname.orig using macro rule_$rule_extract # $depname from $filename using macro rule_$rule_insert # my @entries; while(<>) { s/^#.*//; # remove comment lines next if (m/^$/); if (!m/^(\S+)\s+(\S+)\s+(.*)/) { # if we dont have three space-separated fields, skip the line next; } my $entry = {}; $entry->{generator_file} = $ARGV; $entry->{generator_line} = $.; $entry->{filename} = $1; $entry->{tags_raw} = $2; $entry->{description} = $3; for my $tv (split(/,/,$entry->{tags_raw})) { my ($tag,$val_raw) = split(/:/,$tv); if (!defined($val_raw)) { warn("Missing tag value"); next; } my @values = split(/;/,$val_raw); push @{$entry->{tags}{$tag}}, @values; } # default tags - if there is a value loaded from the tags_raw, it will # take precedence, but otherwise this ensures we create the array and # have the default value at [0] push @{$entry->{tags}{extract}},1; push @{$entry->{tags}{insert}},1; push @{$entry->{tags}{suffix}},1; push @entries,$entry; } my $rules_found = 0; my @extracts; my @inserts; for my $entry (@entries) { # only generate rules for lines that ask for them next if (!defined($entry->{tags}{rule})); # FIXME - if there is more than one rule, error? # currently need at least one dep defined next if (!defined($entry->{tags}{dep})); $rules_found++; my @deps = @{$entry->{tags}{dep}}; my $dep0 = shift @deps; my @deps_extract; if (defined($entry->{tags}{depe})) { @deps_extract = @{$entry->{tags}{depe}}; } my @deps_insert; if (defined($entry->{tags}{depi})) { @deps_insert = @{$entry->{tags}{depi}}; } my @params; if (defined($entry->{tags}{param})) { @params = @{$entry->{tags}{param}}; } if ($entry->{tags}{extract}[0]) { # generate the forward rule my $suffix = ""; if ($entry->{tags}{suffix}[0]) { $suffix = ".orig"; } my $rule = "rule_".$entry->{tags}{rule}[0]."_extract"; push @extracts, sprintf("# %s:%i\n", $entry->{generator_file}, $entry->{generator_line}, ), sprintf("%s: %s %s %s %s\n\t\$(call %s)\n\n", $entry->{filename}.$suffix, $dep0.$suffix, join(' ',@deps,@deps_extract), $entry->{generator_file}, '$('.$rule.'_DEPS)', join(',',$rule,@params), ); } if ($entry->{tags}{insert}[0]) { # generate the inverse rule my $rule = "rule_".$entry->{tags}{rule}[0]."_insert"; push @inserts, sprintf("# %s:%i\n", $entry->{generator_file}, $entry->{generator_line}, ), sprintf("%s: %s %s %s %s\n\t\$(call %s)\n\n", $dep0, $entry->{filename}, join(' ',@deps,@deps_insert), $entry->{generator_file}, '$('.$rule.'_DEPS)', join(',',$rule,@params), ); } } if (!$rules_found) { # only generate output if we have at least one matching line - so an empty input # will just result in an empty output exit(0); } print("# autogenerated rules file - do not edit\n\n"); print(join('',@extracts)); print("\n\n"); print(join('',@inserts));