Add dependency generation for .api files
[panamaz] / src / notzed.nativez / bin / export-api
1 #!/usr/bin/perl
2
3 # meta script to run everything at once.
4
5 # TODO: add an option that dumps out the make dependencies
6
7 use strict;
8 use File::Basename;
9 use File::Spec::Functions qw(abs2rel);
10
11 use FindBin;
12 use lib "$FindBin::Bin/../lib";
13
14 use Data::Dumper;
15 use File::Path qw(make_path);
16 use File::Basename;
17
18 use config;
19
20 my $apidef;
21 my $apibase;
22 my $apih;
23 my $mode = 'generate';
24 my $var = {
25         package => 'api',
26         output => 'bin',
27         workdir => 'bin',
28         verbose => 0,
29         include => [],
30 };
31
32 while (@ARGV) {
33         my $cmd = shift(@ARGV);
34
35         if ($cmd eq '-MT') {
36                 $var->{'make-target'} = shift;
37         } elsif ($cmd eq '-MF') {
38                 $var->{'make-file'} = shift;
39         } else {
40                 if ($cmd =~ m/^(-[^-])(.+)/) {
41                         $cmd = $1;
42                         unshift @ARGV, $2;
43                 }
44
45                 if ($cmd eq "-t") {
46                         $var->{package} = shift;
47                 } elsif ($cmd eq "-d") {
48                         $var->{output} = shift;
49                 } elsif ($cmd eq "-w") {
50                         $var->{workdir} = shift;
51                 } elsif ($cmd eq "-I") {
52                         push @{$var->{include}}, shift;
53                 } elsif ($cmd eq "-v") {
54                         $var->{verbose}++;
55                 } elsif ($cmd eq '-M') {
56                         $mode = 'make-rule';
57                 } else {
58                         $apidef = $cmd;
59                         $apih = "$1.h" if ($apidef =~ m/^(.*).api$/);
60                         $apibase = basename($apidef, '.api');
61                 }
62         }
63 }
64
65 push @{$var->{include}}, "$FindBin::Bin/../lib";
66
67 #print Dumper($var);
68
69 die ("Missing config argument") if !defined($apidef);
70 die ("Unable to find config: $apidef") if !-f $apidef;
71 die ("Unable to find matching header for: $apidef") if !-f $apih;
72
73 my $api = new config($var, $apidef);
74 my @includes = map { ('-I', $_ ) } @{$var->{include}};
75
76 if ($mode eq 'make-rule') {
77         my @list = ();
78
79         $var->{'make-target'} = "$apibase.d" if !defined $var->{'make-target'};
80
81         my @args = (
82                 '-M',
83                 '-MT', $var->{'make-target'},
84                 @includes,
85                 $apih);
86
87         open (my $gcc, '-|', 'gcc', @args) // die("command failed $!");
88         while (<$gcc>) {
89                 chop;
90                 s/ *\\$//;
91                 s/^ +//;
92                 push @list, $_;
93         }
94         close($gcc);
95
96         foreach my $m (qw(export-api export-defines generate-api)) {
97                 push @list, abs2rel("$FindBin::Bin/$m");
98         }
99         foreach my $m (qw(api.pm code.pm config.pm method.pm tokenise.pm)) {
100                 push @list, abs2rel("$FindBin::Bin/../lib/$m");
101         }
102
103         push @list, $apidef;
104         push @list, map { abs2rel($_) } @{$api->{includes}};
105
106         if (defined $var->{'make-file'}) {
107                 open (my $f, ">", $var->{'make-file'}.'~') || die "writing $var->{'make-file'}";
108                 print $f join(" \\\n ", @list)."\n";
109                 close ($f) || die "writing $var->{'make-file'}";
110                 rename($var->{'make-file'}.'~', $var->{'make-file'}) || die "writing $var->{'make-file'}";
111         } else {
112                 print join(" \\\n ", @list)."\n";
113         }
114         exit 0;
115 }
116
117 my @cmd = (
118         'gcc',
119         "-fplugin=$FindBin::Bin/../lib/libexport.so",
120         "-fplugin-arg-libexport-output=$var->{workdir}/$apibase.pm",
121 #       "-fplugin-arg-libexport-verbose=$var->{verbose}",
122         '-O0',
123         '-o', '/dev/null',
124         @includes,
125         $apih
126 );
127
128 print join " ", @cmd, "\n";
129 system(@cmd) == 0 || die("command failed");
130
131 my @defines = ();
132 if (grep { $_->{type} eq 'define' } @{$api->{objects}}) {
133         @cmd = (
134                 "$FindBin::Bin/export-defines",
135                 '--hack-new-format-2',
136                 $var->{verbose} ? '-v' : (),
137                 '-o',
138                 "$var->{workdir}/$apibase-defines.pm",
139                 @includes,
140                 $apidef
141         );
142
143         print join " ", @cmd, "\n";
144         system(@cmd) == 0 || die("command failed");
145         push @defines, '-a', "./$var->{workdir}/$apibase-defines.pm";
146 }
147
148 @cmd = (
149         "$FindBin::Bin/generate-api",
150         $var->{verbose} ? '-v' : (),
151         '-t', $var->{package},
152         '-d', $var->{output},
153         '-a', "./$var->{workdir}/$apibase.pm",
154         @defines,
155         $apidef
156 );
157 print join " ", @cmd, "\n";
158 system(@cmd) == 0 || die("command failed");