source: admin_finroc_server/lib/FINROC/dependencies.pm @ 16:3bdc5aa74130

tip
Last change on this file since 16:3bdc5aa74130 was 16:3bdc5aa74130, checked in by Tobias Föhst <tobias.foehst@…>, 5 years ago

Fixed dependency detection in .finroc and .xml files

File size: 10.1 KB
Line 
1# You received this file as part of Finroc
2# A framework for intelligent robot control
3#
4# Copyright (C) Finroc GbR (finroc.org)
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20#----------------------------------------------------------------------
21# \file    dependencies.pm
22#
23# \author  Tobias Foehst
24#
25# \date    2010-06-30
26#
27#----------------------------------------------------------------------
28package FINROC::dependencies;
29
30use strict;
31
32use XML::Simple;
33use File::Basename;
34use Data::Dumper;
35
36use FINROC::messages;
37
38use FINROC::dependencies::cpp;
39use FINROC::dependencies::java;
40
41sub DependencyFromInclude($)
42{
43    my ($include) = @_;
44
45    my @include = split "/", $include;
46
47    return sprintf "rrlib_%s", $include[1] if $include[0] eq "rrlib";
48    return sprintf "finroc_core" if $include[0] eq "core";
49    return sprintf "finroc_%s_%s", $include[0], $include[1] if grep { $include[0] eq $_ } ( "plugins", "libraries", "projects" );
50}
51
52sub DependencyFromSimVis3DResourceFile($)
53{
54    my ($path) = @_;
55
56    my @path = split "/", $path;
57
58    return sprintf "rrlib_simvis3d_resources_abstract_objects" if $path[0] eq "abstract_objects";
59    return sprintf "rrlib_simvis3d_resources_%s_%s", $path[0], $path[1] if grep { $path[0] eq $_ } ( "environments", "robots" );
60    return sprintf "rrlib_simvis3d_resources_%s_%s_%s", $path[0], $path[1], $path[2] if scalar grep { $path[0] eq $_ } ( "decoration", "humans", "sensors" );
61}
62
63sub ResolveSourceFiles($$$)
64{
65    my ($directory, $source_file_patterns, $exclude_patterns) = @_;
66
67    my @files;
68    return @files unless defined $source_file_patterns;
69
70    foreach my $include_pattern (split " ", $source_file_patterns)
71    {
72        if ($include_pattern =~ /\*\*/)
73        {
74            $include_pattern =~ s/\//\\\//g;
75            $include_pattern =~ s/\./\\./g;
76            $include_pattern =~ s/\*\*/.*/g;
77            $include_pattern =~ s/([^\.])\*/$1\[^\/\]*/g;
78            $include_pattern = qr/^$directory\/$include_pattern$/;
79            foreach my $file (map { chomp; $_ } `find \"$directory\" -type f`)
80            {
81                push @files, $file if $file =~ $include_pattern;
82            }
83        }
84        else
85        {
86            push @files, map { chomp; $_ } `ls \"$directory\"/$include_pattern`;
87        }
88    }
89
90    return @files unless defined $exclude_patterns;
91
92    my %excluded_files;
93    foreach my $exclude_pattern (split " ", $exclude_patterns)
94    {
95        if ($exclude_pattern =~ /\*\*/)
96        {
97            $exclude_pattern =~ s/\//\\\//g;
98            $exclude_pattern =~ s/\./\\./g;
99            $exclude_pattern =~ s/\*\*/.*/g;
100            $exclude_pattern =~ s/([^\.])\*/$1\[^\/\]*/g;
101            $exclude_pattern = qr/^$directory\/$exclude_pattern$/;
102            foreach my $file (map { chomp; $_ } `find \"$directory\" -type f`)
103            {
104                $excluded_files{$file} = 1 if $file =~ $exclude_pattern;
105            }
106        }
107        else
108        {
109            map { chomp; $excluded_files{$_} = 1 } `ls \"$directory\"/$exclude_pattern`;
110        }
111    }
112
113    return grep { !exists $excluded_files{$_} } @files;
114}
115
116sub ProcessSourceFiles($$$$)
117{
118    my ($language, $files, $mandatory, $optional) = @_;
119
120    eval sprintf "FINROC::dependencies::%s::ProcessSourceFiles(\$files, \$mandatory, \$optional)", $language;
121    ERRORMSG "$@\n" if $@;
122}
123
124sub ProcessTargets($$$$$)
125{
126    my ($targets, $directory, $language, $mandatory, $optional) = @_;
127
128    foreach (@{$targets})
129    {
130        $$_{sources} = { content => $$_{sources} } unless ref $$_{sources};
131        my @source_files = ResolveSourceFiles $directory, $$_{sources}{content}, $$_{sources}{exclude};
132
133        my $mandatory_list = $mandatory;
134        $mandatory_list = $optional if exists $$_{optional} and $$_{optional} eq "true";
135        $mandatory_list = $optional if grep { /\/examples\// } @source_files;
136        ProcessSourceFiles $language, [ @source_files ], $mandatory_list, $optional;
137    }
138}
139
140sub ProcessFinrocFiles($$$)
141{
142    my ($files, $mandatory, $optional) = @_;
143
144    foreach (@$files)
145    {
146        my $xml = eval { XMLin($_,
147                               KeepRoot => 1,
148                               ForceArray => [ 'parameter', 'element' ],
149                               ContentKey => '-content',
150                               GroupTags => { parameters => 'parameter' },
151                               NormalizeSpace => 2) };
152
153        if ($@)
154        {
155            WARNMSG sprintf "Skipping malformed xml file '%s'.\n", $_;
156            next;
157        }
158
159        next unless exists $$xml{FinstructableGroup};
160
161        my $dependencies = $mandatory;
162        $dependencies = $optional if /\/examples\//;
163
164        foreach my $dependency (grep { $_ } split /,| /, $$xml{FinstructableGroup}{dependencies})
165        {
166            while ($dependency)
167            {
168                push @$dependencies, $dependency;
169                my $dependency_old = $dependency;
170                $dependency =~ s/_[^_]+$//;
171                last if $dependency eq $dependency_old;
172            }
173        }
174
175        foreach my $element (keys %{$$xml{FinstructableGroup}{element}})
176        {
177            next unless defined $$xml{FinstructableGroup}{element}{$element}{parameters}{'XML file'};
178            my $file = join "", map { $_ =~ s/^sources\/cpp\///; $_ } $$xml{FinstructableGroup}{element}{$element}{parameters}{'XML file'};
179            my $dependency = DependencyFromInclude $file;
180            push @$dependencies, $dependency if $dependency;
181        }
182    }
183}
184
185sub ProcessSimVis3DResourceFiles($$$)
186{
187    my ($files, $mandatory, $optional) = @_;
188
189    foreach my $file (@$files)
190    {
191        my $descr = eval { XMLin($file,
192                                 KeyAttr => [],
193                                 ForceArray => [ "part", "element" ]) };
194
195        if ($@)
196        {
197            WARNMSG sprintf "Skipping malformed xml file '%s'.\n", $_;
198            next;
199        }
200
201        my $dependencies = $mandatory;
202        $dependencies = $optional if $file =~ /\/examples\//;
203
204        foreach (@{$$descr{part}})
205        {
206            push @$dependencies, DependencyFromSimVis3DResourceFile $$_{file};
207        }
208        foreach (@{$$descr{element}})
209        {
210            push @$dependencies, DependencyFromSimVis3DResourceFile $$_{collision_geom} if defined $$_{collision_geom};
211        }
212    }
213}
214
215sub DependenciesFromWorkingCopy($$)
216{
217    my ($working_copy, $repository) = @_;
218
219    my ($repository_type, $repository_name) = $repository =~ /^([^_]+)_(.+)/;
220
221    $repository_name = $repository_type = $repository unless defined $repository_type and defined $repository_name;
222
223    DEBUGMSG sprintf "repository type and name: %s, %s\n", $repository_type, $repository_name;
224
225    my $language = "cpp";
226    $language = $1 if $repository_name =~ /-(.+)$/;
227
228    DEBUGMSG sprintf "language: %s\n", $language;
229
230    my (@mandatory, @optional);
231
232    my @make_files = map { chomp; $_ } `find \"$working_copy\" -iname "make.xml"`;
233    foreach (@make_files)
234    {
235        my $directory = dirname $_;
236
237        my $make = eval { XMLin($_,
238                                KeyAttr => [],
239                                ForceArray => [ "program", "library", "rrlib", "unittest", "testprogram", "finroclibrary", "finrocplugin", "finrocprogram" ],
240                                ForceContent => [ "sources" ],
241                                NormalizeSpace => 2) };
242
243        if ($@)
244        {
245            WARNMSG sprintf "Skipping malformed xml file '%s'.\n", $_;
246            next;
247        }
248
249        ProcessTargets $$make{library}, $directory, $language, \@mandatory, \@optional;
250        ProcessTargets $$make{program}, $directory, $language, \@mandatory, \@optional;
251
252        ProcessTargets $$make{rrlib}, $directory, $language, \@mandatory, \@optional if $repository_type eq "rrlib";
253        if ($repository_type eq "finroc")
254        {
255            ProcessTargets $$make{finroclibrary}, $directory, $language, \@mandatory, \@optional;
256            ProcessTargets $$make{finrocplugin}, $directory, $language, \@mandatory, \@optional if $repository_name =~ /_?plugins_/;
257            ProcessTargets $$make{finrocprogram}, $directory, $language, \@mandatory, \@optional if $repository_name =~ /^(projects|tools)_/;
258        }
259
260        ProcessTargets $$make{testprogram}, $directory, $language, \@optional, \@optional;
261    }
262
263    DEBUGMSG sprintf "collected mandatory dependencies: %s\n", join ", ", @mandatory;
264    DEBUGMSG sprintf "collected optional dependencies: %s\n", join ", ", @optional;
265
266    my @finroc_files = map { chomp; $_ } `find \"$working_copy\" -iname "*.finroc" -a ! -iname "license.finroc"`;
267    ProcessFinrocFiles \@finroc_files, \@mandatory, \@optional;
268    @finroc_files = map { chomp; $_ } `find \"$working_copy\" -iname "*.xml"`;
269    ProcessFinrocFiles \@finroc_files, \@mandatory, \@optional;
270
271    my @simvis3d_resource_files = map { chomp; $_ } `find \"$working_copy\" -iname "*.descr"`;
272    ProcessSimVis3DResourceFiles \@simvis3d_resource_files, \@mandatory, \@optional;
273
274    my %seen = ( $repository => 1 );
275    @mandatory = grep { !$seen{$_}++ } @mandatory;
276    @optional = grep { !$seen{$_}++ } @optional;
277
278    # filter dependencies to other-world-repositories
279    if ($repository_type eq "rrlib")
280    {
281        @mandatory = grep { $_ =~ /^rrlib_/ } @mandatory;
282        @optional = grep { $_ =~ /^rrlib_/ } @optional;
283    }
284    if ($repository_type eq "finroc")
285    {
286        @mandatory = grep { $_ =~ /^(rrlib|finroc)_/ } @mandatory;
287        @optional = grep { $_ =~ /^(rrlib|finroc)_/ } @optional;
288    }
289
290    return (join(" ", sort @mandatory), join(" ", sort @optional));
291}
292
2931;
Note: See TracBrowser for help on using the repository browser.