package textbender::a::b::rhinohide::Rhinohide; # Copyright 2007, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. use strict; use warnings; =pod =head1 DESCRIPTION Basic build of Rhinohide. =head1 EXPORTS =over 4 =cut BEGIN { use Exporter (); our @ISA; @ISA = qw( Exporter ); our @EXPORT_OK; @EXPORT_OK = qw( build_rhinohide ); } our @EXPORT_OK; my $_build_cache_dir; { use textbender::a::b::Build qw( build_cache_root ensure_dir ); $_build_cache_dir = ensure_dir( build_cache_root() . '/textbender/a/b/rhinohide' ); } =pod =item B (target, described in the accompanying F script) =cut sub build_rhinohide() { # cf. textbender::a::b::rhinohideDemo::RhinohideDemo::build_rhinohideDemo() use textbender::a::b::base::Base(); use textbender::a::b::Build qw( %option ); print textbender::a::b::Build::call_stack_indentation() . "rhinohide\n"; build_jar(); $option{'sign'} && textbender::a::b::base::Base::sign_all(); } =pod =item B (target, described in the accompanying F script) =cut sub build_clean() { use File::Path qw( rmtree ); use textbender::a::b::Build qw( build_cache_root out_dir ); print textbender::a::b::Build::call_stack_indentation() . "clean\n"; rmtree( build_cache_root() . "/textbender" ); rmtree( out_dir() ); } =pod =item B (target, described in the accompanying F script) =cut sub build_jar() { use textbender::a::b::Build qw( ensure_dir ); print textbender::a::b::Build::call_stack_indentation() . "jar\n"; compile(); # - - - my $jar_file = ensure_dir(out_dir()) . '/rhinohide.jar'; textbender::a::b::Java::jar( compile_class_outdir(), $jar_file ); return $jar_file; } =pod =item B Compiles out-of-sync source files *.java to *.class. Returns the number of files compiled. =cut my $compile__print_count; sub _compile__print_all_source() # File::Find::find wanted sub { # cf. textbender::a::b::Java::_compile__print_all_source() my $file = $File::Find::name; -d $file and return; # skip directories my $outfile = $file; # textbender/foo/bar.java $outfile =~ s:\.java$:.class: or return; # textbender/foo/bar.class -l $file && $file =~ m'/\.\#[^/]+$' and die "\nemacs lock file (do you need to save this buffer?): $_\n"; $outfile = compile_class_outdir() . '/' . $outfile; # /dir/textbender/foo/bar.class if( -f $outfile ) { File::stat::stat($file)->mtime > File::stat::stat($outfile)->mtime or return; } else # finally, filter by path (last because we still want to compile off-path dependencies (pulled in by javac on the last path) that are now out-of-date { $file =~ m:^textbender/o/rhinohide/: or return; } print ARGFILE $file; print ARGFILE "\n"; ++$compile__print_count; } sub compile() { # cf. textbender::a::b::Java::_compile() use File::Find (); use textbender::a::b::Console qw( print_score $verbosity ); use textbender::a::b::Build qw( build_cache_root ensure_dir ); use textbender::a::b::Java qw( JDK_dir ); my $compile_class_outdir = ensure_dir( compile_class_outdir() ); my $command = JDK_dir() . '/bin/javac' . ' -sourcepath .' . " -d $compile_class_outdir" . ' -deprecation -g' # Though deprecation warnings are emitted only for single-file compiles, # with or without -deprecation, in 1.4, # . ' -source ' . textbender::a::b::Java::major_version() ## latest is the default in 1.5 # . ' -target ' . textbender::a::b::Java::major_version() ## latest is the default in 1.5 # . ' -verbose' . ' -Xlint' # new in 1.5 . ' -Xlint:-serial'; # because its documentation (especially for @serialField and @serialData) is incomprehensible local *ARGFILE; my $argfile; # Source. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $argfile = build_cache_root() . '/textbender/a/b/Java-compile-arg-source'; open ARGFILE, '>', $argfile or die; { $compile__print_count = 0; # thus far File::Find::find ( {follow_fast=>1, no_chdir=>1, wanted=>\&_compile__print_all_source}, 'textbender' ); close ARGFILE; } $compile__print_count or return 0; $command .= ' @' . $argfile; # Classpath. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $argfile = build_cache_root() . '/textbender/a/b/Java-compile-arg-classpath'; open ARGFILE, '>', $argfile or die; { print ARGFILE "-classpath $compile_class_outdir"; # Jars from the development kit. # ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` for my $file( 'jre/lib/plugin.jar' ) # for JSObject (in-browser code) { print ARGFILE ':'; print ARGFILE JDK_dir() . '/' . $file; } # ` ` ` print ARGFILE "\n"; close ARGFILE; } $command .= ' @' . $argfile; # - - - print textbender::a::b::Build::call_stack_indentation() . "(compile $compile__print_count...\n"; if( $verbosity ) { print "\n$command\n"; print_score( undef, '^' ); } system $command and exit; return $compile__print_count; } =pod =item B Returns the directory to which compiled Java (*.class) files are output. =cut sub compile_class_outdir() { use textbender::a::b::Build qw( build_cache_root ); return build_cache_root() . '/textbender/a/b/rhinohide/compile-out'; } =pod =back =cut 1;