1 | #!/usr/bin/env perl
|
---|
2 |
|
---|
3 | # Generates Makefiles for different systems and packages
|
---|
4 | # Uses a hashmap to do config variables (see readvar for how variables are
|
---|
5 | # read in and an example of how they are resolved / used)
|
---|
6 |
|
---|
7 | use strict;
|
---|
8 | use warnings;
|
---|
9 | use utf8;
|
---|
10 | use File::Basename;
|
---|
11 | use File::Path 'make_path';
|
---|
12 | use File::Copy 'cp';
|
---|
13 | use Storable 'dclone';
|
---|
14 | use Digest::MD5;
|
---|
15 |
|
---|
16 |
|
---|
17 | my $USAGE = "Usage: " . basename($0) . " <distros> <packages>
|
---|
18 | distros: A comma separated list of the distros defined in distros/
|
---|
19 | Or 'all' (for all distros)
|
---|
20 | packages: A comma separated list of the packages defined in packages/
|
---|
21 | Or 'all' (for all packages)
|
---|
22 | ";
|
---|
23 |
|
---|
24 | $#ARGV == 1 or die $USAGE;
|
---|
25 |
|
---|
26 | sub globbify {
|
---|
27 | my ($dir, $files) = @_;
|
---|
28 | $files =~ /^all$/i and return glob "$dir/*";
|
---|
29 | my @list = glob "$dir/{$files}";
|
---|
30 | for (@list) {
|
---|
31 | -f or die "Could not find '", $_, "'";
|
---|
32 | }
|
---|
33 | return @list;
|
---|
34 | }
|
---|
35 |
|
---|
36 | sub empty {
|
---|
37 | shift =~ /^\s*$/ and return 1;
|
---|
38 | }
|
---|
39 |
|
---|
40 | sub comment {
|
---|
41 | shift =~ /^\s*#/ and return 1;
|
---|
42 | }
|
---|
43 |
|
---|
44 | sub trim {
|
---|
45 | for (@_) {
|
---|
46 | s/^\s+|\s+$//g;
|
---|
47 | }
|
---|
48 | return @_;
|
---|
49 | }
|
---|
50 |
|
---|
51 | sub add {
|
---|
52 | my ($src, $dst, $subst) = @_;
|
---|
53 | $dst =~ s/@([\w]+)@/$subst->{$1}/g;
|
---|
54 |
|
---|
55 | if (-d $src) {
|
---|
56 | mkdir $dst;
|
---|
57 | opendir my $DIRFH, $src or die "Could not open '$src': $!";
|
---|
58 | while (readdir $DIRFH) {
|
---|
59 | next if ($_ eq '.' or $_ eq '..');
|
---|
60 | add ("$src/$_", "$dst/$_", $subst);
|
---|
61 | }
|
---|
62 | closedir $DIRFH;
|
---|
63 | } else {
|
---|
64 | print ' - ', $dst, "\n";
|
---|
65 | if (-B $src or $src =~ /\.patch$/i) {
|
---|
66 | # copy binary file
|
---|
67 | cp $src, $dst or die "Failed to copy '$src': $!";
|
---|
68 | } else {
|
---|
69 | # copy normal file
|
---|
70 | open IN, '<', $src
|
---|
71 | or die "Failed to open '$src' for reading: $!";
|
---|
72 | open OUT, '>', $dst
|
---|
73 | or die "Failed to open '$dst' for writing: $!";
|
---|
74 | while (<IN>) {
|
---|
75 | s/@([\w]+)@/$subst->{$1}/g;
|
---|
76 | print OUT;
|
---|
77 | }
|
---|
78 | my $perms = (stat IN)[2] & 07777;
|
---|
79 | close IN;
|
---|
80 | close OUT;
|
---|
81 | chmod ($perms | 0600, $dst);
|
---|
82 | }
|
---|
83 | }
|
---|
84 | }
|
---|
85 |
|
---|
86 | my %escape = (
|
---|
87 | "n" => "\n",
|
---|
88 | "\\" => "\\",
|
---|
89 | " " => " "
|
---|
90 | );
|
---|
91 |
|
---|
92 | sub readvar {
|
---|
93 | my ($vars, $line) = @_;
|
---|
94 | my ($var, $val) = trim (split ":", $line, 2);
|
---|
95 | defined $var and defined $val or die "Invalid variable assignment: '$line'";
|
---|
96 | local $/ = '';
|
---|
97 | $val =~ s/@([\w]+)@/$vars->{$1}/g;
|
---|
98 | $val =~ s/\\([ \\n]|$)/$escape{$1}/g;
|
---|
99 | $vars->{$var} = $val;
|
---|
100 | }
|
---|
101 |
|
---|
102 | sub addsource {
|
---|
103 | my ($vars, $source) = @_;
|
---|
104 | my $md5 = Digest::MD5->new;
|
---|
105 | open my $MD5FH, '<', $source;
|
---|
106 | binmode $MD5FH;
|
---|
107 | $md5->addfile ($MD5FH);
|
---|
108 | my $field_separator = $vars->{'FIELD_SEPARATOR'};
|
---|
109 | $vars->{'SOURCES'} .= $field_separator . basename($source);
|
---|
110 | $vars->{'SOURCE_SUMS'} .= $field_separator . $md5->hexdigest;
|
---|
111 | close $MD5FH;
|
---|
112 | }
|
---|
113 |
|
---|
114 | my @distros = globbify "distros", shift;
|
---|
115 | my @packages = globbify "packages", shift;
|
---|
116 |
|
---|
117 | for my $dconf (@distros) {
|
---|
118 | my $distro = basename $dconf;
|
---|
119 | print "$distro\n";
|
---|
120 |
|
---|
121 | open DISTRO, '<', $dconf;
|
---|
122 | my %distro_vars;
|
---|
123 | while (my $var = <DISTRO>) {
|
---|
124 | chomp $var;
|
---|
125 | (comment $var or empty $var) and next;
|
---|
126 | readvar \%distro_vars, $var;
|
---|
127 | }
|
---|
128 | close DISTRO;
|
---|
129 |
|
---|
130 | for my $pconf (@packages) {
|
---|
131 | my $package = basename $pconf;
|
---|
132 | print " - $package\n";
|
---|
133 | my $package_path = "build/$distro/$package";
|
---|
134 | make_path $package_path;
|
---|
135 |
|
---|
136 | open PACKAGE, '<', $pconf;
|
---|
137 | my %package_vars = %{dclone \%distro_vars};
|
---|
138 | while (my $var = <PACKAGE>) {
|
---|
139 | chomp $var;
|
---|
140 | empty $var and last;
|
---|
141 | comment $var and next;
|
---|
142 | readvar \%package_vars, $var;
|
---|
143 | }
|
---|
144 | for (keys %package_vars) {
|
---|
145 | defined $package_vars{$_} or $package_vars{$_} = ' ';
|
---|
146 | # print "$_ = $package_vars{$_}\n";
|
---|
147 | }
|
---|
148 |
|
---|
149 | while (my $file = <PACKAGE>) {
|
---|
150 | chomp $file;
|
---|
151 | empty $file and last;
|
---|
152 | comment $file and next;
|
---|
153 | add ("files/$file", "$package_path/$file", \%package_vars);
|
---|
154 | addsource (\%package_vars, "$package_path/$file");
|
---|
155 | }
|
---|
156 |
|
---|
157 | # write the makefile
|
---|
158 | my $outfile = "$package_path/Makefile";
|
---|
159 | print " - $outfile\n";
|
---|
160 | open MAKEFILE, '>', $outfile
|
---|
161 | or die "Failed to open '$outfile' for writing: $!";
|
---|
162 | while (my $segment = <PACKAGE>) {
|
---|
163 | chomp $segment;
|
---|
164 | empty $segment and last;
|
---|
165 | comment $segment and next;
|
---|
166 | open IN, '<', "segments/$segment"
|
---|
167 | or die "Failed to open 'segments/$segment' for reading: $!";
|
---|
168 | while (<IN>) {
|
---|
169 | s/@([\w]+)@/$package_vars{$1}/g;
|
---|
170 | print MAKEFILE;
|
---|
171 | }
|
---|
172 | close IN;
|
---|
173 | print MAKEFILE "\n";
|
---|
174 | }
|
---|
175 | close PACKAGE;
|
---|
176 | # add a target for packaging
|
---|
177 | if (open IN, '<', "segments/$distro_vars{'MANAGER'}") {
|
---|
178 | while (<IN>) {
|
---|
179 | s/@([\w]+)@/$package_vars{$1}/g;
|
---|
180 | print MAKEFILE;
|
---|
181 | }
|
---|
182 | close IN;
|
---|
183 | }
|
---|
184 | close MAKEFILE;
|
---|
185 | addsource \%package_vars, $outfile;
|
---|
186 |
|
---|
187 | # write the package manager files
|
---|
188 | add ("managers/$distro_vars{'MANAGER'}", $package_path, \%package_vars);
|
---|
189 | }
|
---|
190 | }
|
---|