| #!/usr/bin/perl |
| |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| use strict; |
| use warnings; |
| |
| use Getopt::Long; |
| use File::Spec::Functions qw( rel2abs catdir catfile updir ); |
| use FindBin qw( $Bin ); |
| use File::stat qw( stat ); |
| |
| # Process command line arguments. |
| my ( @probes, @user_files, @charm_files ); |
| my $outfile; |
| GetOptions( |
| 'probes:s' => \@probes, |
| 'files=s' => \@user_files, |
| 'out=s' => \$outfile, |
| ); |
| my $usage = <<END_USAGE; |
| Usage: |
| |
| meld.pl --files=FILES [--probes=PROBES] --out=OUTFILE |
| |
| * probes -- A comma separated list of Charmonizer Probe names, e.g. |
| "Integers", "Integers,Floats,LargeFiles". Defaults to all probes if not |
| supplied. |
| * files -- A comma separated list of files to be appended verbatim. At |
| least one file must be present and it must define main(). |
| * out -- The output file. |
| |
| END_USAGE |
| die $usage unless @user_files; |
| die $usage unless $outfile; |
| $outfile = rel2abs($outfile); |
| @user_files = split( /,/, join( ',', @user_files ) ); |
| @probes = split( /,/, join( ',', @probes ) ); |
| |
| # Slurp all user files. |
| my %user_file_content; |
| for my $file (@user_files) { |
| $user_file_content{$file} = slurp($file); |
| } |
| |
| # Make sure we are in the charmonizer dir. |
| chdir( catdir( $Bin, updir() ) ); |
| |
| # Default to including all Probes. |
| if ( !@probes ) { |
| my $probe_dir = catdir(qw( src Charmonizer Probe )); |
| opendir( my $dh, $probe_dir ) or die "Can't opendir '$probe_dir': $!"; |
| @probes = map { $_ =~ s/\.c$//; $_ } grep {/\.c$/} readdir $dh; |
| } |
| |
| my @core = qw( |
| Library |
| CFlags |
| CLI |
| Compiler |
| ConfWriter |
| ConfWriterC |
| ConfWriterPerl |
| ConfWriterPython |
| ConfWriterRuby |
| HeaderChecker |
| Make |
| OperatingSystem |
| Util |
| ); |
| |
| # Add Core headers. |
| for ( 'Defines', @core ) { |
| push @charm_files, catfile( qw( src Charmonizer Core ), "$_.h" ); |
| } |
| push @charm_files, catfile(qw( src Charmonizer Probe.h )); |
| |
| # Add specified Probe headers in lexically sorted order. |
| for ( sort @probes ) { |
| push @charm_files, catfile( qw( src Charmonizer Probe ), "$_.h" ); |
| } |
| |
| # Add Core implementation files. |
| for (@core) { |
| push @charm_files, catfile( qw( src Charmonizer Core ), "$_.c" ); |
| } |
| push @charm_files, catfile(qw( src Charmonizer Probe.c )); |
| |
| # Add Probe implementation files in lexically sorted order. |
| for ( sort @probes ) { |
| push @charm_files, catfile( qw( src Charmonizer Probe ), "$_.c" ); |
| } |
| |
| # Don't write out unless there has been an update. |
| if ( -e $outfile ) { |
| my $outfile_mtime = stat($outfile)->mtime; |
| my $needs_update; |
| for my $dependency ( @charm_files, @user_files ) { |
| die "Can't find '$dependency'" unless -e $dependency; |
| if ( stat($dependency)->mtime > $outfile_mtime ) { |
| $needs_update = 1; |
| last; |
| } |
| } |
| if ($needs_update) { |
| unlink $outfile; |
| } |
| else { |
| exit; |
| } |
| } |
| |
| # Start the composite. |
| open( my $out_fh, '>', $outfile ) |
| or die "Can't open '$outfile': $!"; |
| binmode $out_fh; |
| print $out_fh meld_start(); |
| |
| # Process core files. |
| for my $file (@charm_files) { |
| print $out_fh pare_charm_file($file); |
| } |
| |
| # Process user specified files. |
| for my $file (@user_files) { |
| my $content = $user_file_content{$file}; |
| |
| # Comment out pound-includes for files being inlined. |
| $content =~ s|^(#include "Charmonizer[^\n]+)\n|/* $1 */\n|msg; |
| |
| print $out_fh line_directive(1, $file); |
| print $out_fh $content; |
| } |
| |
| close $out_fh or die "Can't close '$outfile': $!"; |
| exit; |
| |
| sub pare_charm_file { |
| my $path = shift; |
| my $content = slurp($path); |
| my $num_newlines = $content =~ tr/\n/\n/; |
| |
| # Strip license header. |
| $content =~ s#/\* Licensed to the Apache.+?\*/\n+##s |
| or die "Couldn't find ASF license header in '$path'"; |
| |
| # Remove opening C++ guards (if this is a header). |
| $content =~ s/^#ifdef __cplusplus.*?#endif\n+//ms; |
| |
| # Add a #line directive. |
| my $new_num_newlines = $content =~ tr/\n/\n/; |
| my $starting_line = 1 + $num_newlines - $new_num_newlines; |
| $content = line_directive($starting_line, $path) . $content; |
| |
| # Remove closing C++ guards (if this is a header). |
| $content =~ s/^#ifdef __cplusplus.*?#endif\n+//ms; |
| |
| # Comment out pound-includes for files being inlined. |
| $content =~ s|^(#include "Charmonizer[^\n]+)\n|/* $1 */\n|msg; |
| |
| return <<END_STUFF; |
| /***************************************************************************/ |
| |
| $content |
| END_STUFF |
| } |
| |
| sub slurp { |
| my $path = shift; |
| open( my $fh, '<', $path ) or die "Can't open '$path': $!"; |
| return do { local $/; <$fh> }; |
| } |
| |
| sub line_directive { |
| my ( $lineno, $file ) = @_; |
| $file =~ s'\\'/'g; |
| return qq|#line $lineno "$file"\n|; |
| } |
| |
| sub meld_start { |
| return <<END_STUFF; |
| /* This is an auto-generated file -- do not edit directly. */ |
| |
| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| END_STUFF |
| } |
| |