2011-01-04 23:04:08 +00:00
#!/usr/bin/perl
2011-02-04 01:32:34 +00:00
#
# Copyright 2011 Google Inc.
#
# Licensed 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.
#
#
# A simple little build system.
#
# See the configuration at the bottom of this file.
2011-01-04 23:04:08 +00:00
use strict ;
use Getopt::Long ;
2011-01-05 16:21:27 +00:00
use FindBin ;
2011-06-22 21:16:50 +00:00
use Cwd ;
2011-01-04 23:04:08 +00:00
my $ opt_list ;
my $ opt_eachclean ;
my $ opt_verbose ;
2011-02-26 21:29:04 +00:00
my $ opt_test ;
2011-03-19 08:20:54 +00:00
my $ opt_deps ;
2011-06-22 21:16:50 +00:00
my $ opt_updatego ;
2011-01-04 23:04:08 +00:00
2011-01-05 16:21:27 +00:00
chdir ( $ FindBin:: Bin ) or die "Couldn't chdir to $FindBin::Bin: $!" ;
2011-01-04 23:04:08 +00:00
GetOptions ( "list" = > \ $ opt_list ,
"eachclean" = > \ $ opt_eachclean ,
2011-05-10 19:17:43 +00:00
"verbose+" = > \ $ opt_verbose ,
2011-02-26 21:29:04 +00:00
"test" = > \ $ opt_test ,
2011-03-19 08:20:54 +00:00
"deps" = > \ $ opt_deps ,
2011-06-22 21:16:50 +00:00
"updatego" = > \ $ opt_updatego ,
2011-01-04 23:04:08 +00:00
) or usage ( ) ;
sub usage {
die << EOM
Usage:
build . pl all # build all
2011-02-04 01:40:53 +00:00
build . pl allfast # build all targets that compile quickly
2011-01-04 23:04:08 +00:00
build . pl clean # clean all
build . pl REGEXP # builds specific target, if it matches any targets
build . pl - - list
build . pl - - eachclean # builds each target with a full clean before it
# (for testing that dependencies are correct)
2011-03-19 08:20:54 +00:00
build . pl - - deps # Show each target's dependencies
2011-01-04 23:04:08 +00:00
Other options:
- - verbose | - v Verbose
2011-02-26 21:29:04 +00:00
- - test | - t Run tests where found
2011-06-22 21:16:50 +00:00
- - updatego Attempt to update GOROOT to maintainer ' s go version
2011-01-04 23:04:08 +00:00
EOM
;
}
my % built ; # target -> bool (was it already built?)
2011-06-17 21:13:01 +00:00
# Note: the target key is usually the directory, but may be overridden. use
# the dir($target) function to find the directory
2011-01-04 23:04:08 +00:00
my % targets ; # dir -> { deps => [ ... ], }
read_targets ( ) ;
if ( $ opt_list ) {
print "Available targets:\n" ;
foreach my $ target ( sort keys % targets ) {
print " * $target\n" ;
}
2011-03-19 08:20:54 +00:00
exit ;
}
if ( $ opt_deps ) {
foreach my $ target ( sort keys % targets ) {
find_go_camli_deps ( $ target ) ;
my $ t = $ targets { $ target } or die ;
print "$target: @{ $t->{deps} }\n" ;
}
exit ;
2011-01-04 23:04:08 +00:00
}
if ( $ opt_eachclean ) {
my $ target = shift ;
die "--eachclean doesn't take a target\n" if $ target ;
foreach my $ target ( sort keys % targets ) {
clean ( ) ;
% built = ( ) ;
build ( $ target ) ;
}
exit ;
}
2011-06-22 21:16:50 +00:00
if ( $ opt_updatego ) {
update_go ( ) ;
}
2011-01-04 23:04:08 +00:00
my $ target = shift or usage ( ) ;
if ( $ target eq "clean" ) {
clean ( ) ;
exit ;
}
2011-02-04 01:40:53 +00:00
if ( $ target eq "allfast" ) {
2011-05-30 19:22:14 +00:00
my @ targets = sort grep { ! $ targets { $ _ } { tags } { not_in_all } } keys % targets ;
@ targets = filter_os_targets ( @ targets ) ;
foreach my $ target ( @ targets ) {
2011-02-04 01:40:53 +00:00
build ( $ target ) ;
}
2011-05-30 00:34:32 +00:00
record_go_version ( ) ;
2011-02-04 01:40:53 +00:00
exit ;
}
2011-01-04 23:04:08 +00:00
if ( $ target eq "all" ) {
2011-05-30 19:22:14 +00:00
my @ targets = filter_os_targets ( sort keys % targets ) ;
foreach my $ target ( @ targets ) {
2011-01-04 23:04:08 +00:00
build ( $ target ) ;
}
2011-05-30 00:34:32 +00:00
record_go_version ( ) ;
2011-01-04 23:04:08 +00:00
exit ;
}
my @ matches = grep { /$target/ } sort keys % targets ;
unless ( @ matches ) {
die "No build targets patching pattern /$target/\n" ;
}
if ( @ matches > 1 ) {
2011-02-03 23:56:02 +00:00
if ( scalar ( grep { $ _ eq $ target } @ matches ) == 1 ) {
@ matches = ( $ target ) ;
} else {
die "Build pattern is ambiguous, matches multiple targets:\n * " . join ( "\n * " , @ matches ) . "\n" ;
}
2011-01-04 23:04:08 +00:00
}
build ( $ matches [ 0 ] ) ;
sub v {
return unless $ opt_verbose ;
my $ msg = shift ;
chomp $ msg ;
print STDERR "# $msg\n" ;
}
2011-05-10 19:17:43 +00:00
sub v2 {
return unless $ opt_verbose >= 2 ;
my $ msg = shift ;
chomp $ msg ;
print STDERR "# $msg\n" ;
}
2011-01-04 23:04:08 +00:00
sub clean {
for my $ root ( "$ENV{GOROOT}/pkg/linux_amd64" ,
2011-03-05 22:14:00 +00:00
"$ENV{GOROOT}/pkg/linux_386" ) {
2011-06-17 21:13:01 +00:00
for my $ pkg ( "camli" , "camlistore.org" ) {
2011-01-04 23:04:08 +00:00
my $ dir = "$root/$pkg" ;
next unless - d $ dir ;
system ( "rm" , "-rfv" , $ dir ) ;
}
}
foreach my $ target ( sort keys % targets ) {
print STDERR "Cleaning $target\n" ;
2011-06-17 21:13:01 +00:00
system ( "make" , "-C" , dir ( $ target ) , "clean" ) ;
2011-01-04 23:04:08 +00:00
}
}
2011-06-22 21:16:50 +00:00
# Updates go to maintainer version.
sub update_go {
# Get revision number:
my $ last = do { open ( my $ fh , ".last_go_version" ) or die ; local $/ ; <$fh> } ;
$ last =~ s!^[68]g version weekly.[0-9]{4}-[0-9]{2}-[0-9]{2} !! ;
chomp $ last ;
2011-06-23 05:20:59 +00:00
unless ( $ last =~ /^(\d+)\+?\s*$/ ) {
2011-06-22 21:16:50 +00:00
print "Failed to obtain maintainer's go revision\n" ;
return ;
}
2011-06-23 05:20:59 +00:00
my $ maintainer_version = $ 1 ;
2011-06-22 21:16:50 +00:00
print "Updating go to revision: $last\n" ;
my $ prev_cwd = getcwd ;
if ( $ ENV { 'GOROOT' } eq '' ) {
print "\$GOROOT not set!\n" ;
return ;
}
chdir $ ENV { 'GOROOT' } or die "Chdir to $ENV{'GOROOT'} failed\n" ;
system ( "hg" , "pull" ) and die "Hg pull failed\n" ;
2011-06-23 05:20:59 +00:00
system ( "hg" , "update" , $ maintainer_version ) and die "Hg update failed\n" ;
2011-06-22 21:16:50 +00:00
print "Building...\n" ;
chdir "$ENV{'GOROOT'}/src" or die "Chdir to $ENV{'GOROOT'}/src failed\n" ;
system ( "./all.bash" ) and die "Go build failed\n" ;
chdir $ prev_cwd or die "Chdir back to $prev_cwd failed\n" ;
}
2011-03-19 20:55:39 +00:00
# Returns a help message on a build failure of a given target.
sub fixit_tip {
my $ target = shift ;
if ( $ target =~ /\bgo\b/ ) {
my $ gover = `gotry runtime 'Version()'` ;
unless ( $ gover =~ /Version.+"(.+)"/ ) {
return "Failed to find 'gotry'. Is Go installed? Or have you put \$GOROOT/bin in your \$PATH?" ;
}
$ gover = $ 1 ;
2011-05-30 00:34:32 +00:00
my $ last = do { open ( my $ fh , ".last_go_version" ) or die ; local $/ ; <$fh> } ;
$ last =~ s!^[68]g version !! ;
chomp $ last ;
chomp $ gover ;
if ( $ last eq $ gover ) {
return "" ;
2011-03-19 20:55:39 +00:00
}
2011-06-17 01:39:17 +00:00
return "You're running Go version: $gover (maintainer's last version used was $last)\nCamlistore generally tracks Go tip closely.\n(run \"hg pull && hg update tip && cd src && ./all.bash\" in \$GOROOT)" ;
2011-05-30 00:34:32 +00:00
2011-03-19 20:55:39 +00:00
}
if ( $ target =~ /\bandroid\b/ ) {
return "Have you installed the Android SDK, installed ant, set \$JAVA_HOME?\n" .
"Unset \$JAVA_HOME if it points to a bogus place? Run update-java-alternatives?\n" .
"See errors above." ;
}
return "" ;
}
2011-03-19 05:33:43 +00:00
my $ did_go_check = 0 ;
2011-06-30 04:07:37 +00:00
my $ gc_bin ;
2011-02-04 01:47:25 +00:00
sub perform_go_check () {
2011-03-19 05:33:43 +00:00
return if $ did_go_check + + ;
2011-06-30 04:07:37 +00:00
unless ( $ ENV { GOROOT } ) {
if ( `which 6g` =~ /\S/ || `which 8g` =~ /\S/ ) {
die "You seem to have Go installed, but you don't have your " .
"\$GOROOT environment variable set.\n" .
"Can't build without it.\n" ;
}
die "You don't seem to have Go installed. See:\n\n http://golang.org/doc/install.html\n\n" ;
2011-02-04 01:47:25 +00:00
}
2011-06-30 04:07:37 +00:00
die "Your \$GOROOT environment variable isn't a directory.\n" unless - d $ ENV { GOROOT } ;
foreach my $ gc ( "6g" , "8g" ) {
$ gc_bin = `which $gc` or next ;
chomp $ gc_bin ;
last ;
2011-02-04 01:47:25 +00:00
}
2011-06-30 04:07:37 +00:00
die "No 6g or 8g found in your \$PATH.\n" unless - x $ gc_bin ;
return 1 ;
2011-02-04 01:47:25 +00:00
}
2011-01-04 23:04:08 +00:00
sub build {
my @ history = @ _ ;
my $ target = $ history [ 0 ] ;
2011-02-04 01:47:25 +00:00
2011-06-03 19:36:08 +00:00
my $ is_go = $ target =~ m !/go/! ;
if ( $ is_go ) {
2011-02-04 01:47:25 +00:00
perform_go_check ( ) ;
}
2011-01-04 23:04:08 +00:00
my $ already_built = $ built { $ target } || 0 ;
2011-05-10 19:17:43 +00:00
v2 ( "Building '$target' (already_built=$already_built; via @history)" ) ;
2011-01-04 23:04:08 +00:00
return if $ already_built ;
$ built { $ target } = 1 ;
2011-03-05 22:14:00 +00:00
if ( $ target =~ /^ext:(.+)/ ) {
die "\$GOROOT not set" unless $ ENV { GOROOT } && - d $ ENV { GOROOT } ;
my $ golib = $ 1 ;
my @ files = glob ( "$ENV{GOROOT}/pkg/*/${golib}.a" ) ;
unless ( @ files ) {
die "You need to run:\n\n\tgoinstall $golib\n" ;
}
return ;
}
2011-03-19 05:33:43 +00:00
my $ t = $ targets { $ target } or die "Bogus or undeclared build target: $target\n" ;
# Add auto-learned dependencies.
find_go_camli_deps ( $ target ) ;
2011-03-20 04:20:35 +00:00
gen_target_makefile ( $ target ) ;
2011-01-04 23:04:08 +00:00
# Dependencies first.
my @ deps = @ { $ t - > { deps } } ;
if ( @ deps ) {
2011-05-10 19:17:43 +00:00
v2 ( "Deps of '$target' are @deps" ) ;
2011-01-04 23:04:08 +00:00
foreach my $ dep ( @ deps ) {
build ( $ dep , @ history ) ;
}
2011-05-10 19:17:43 +00:00
v2 ( "built deps for $target, now can build" ) ;
2011-01-04 23:04:08 +00:00
}
my @ quiet = ( "--silent" ) ;
@ quiet = ( ) if $ opt_verbose ;
2011-06-03 19:36:08 +00:00
my $ build_command = sub {
2011-06-17 21:13:01 +00:00
return system ( "make" , @ quiet , "-C" , dir ( $ target ) , "install" ) == 0 ;
2011-06-03 19:36:08 +00:00
} ;
if ( ! $ build_command - > ( ) ) {
2011-01-04 23:04:08 +00:00
my $ chain = "" ;
if ( @ history > 1 ) {
2011-05-30 00:34:32 +00:00
$ chain = "via chain @history" ;
2011-01-04 23:04:08 +00:00
}
2011-03-19 20:55:39 +00:00
my $ help_msg = fixit_tip ( $ target ) ;
if ( $ help_msg ) {
$ help_msg = "\nPossible tip: $help_msg\n\n" ;
}
my $ deps ;
if ( $ chain ) {
$ deps = " (via deps: $chain)" ;
}
die "\nError building $target$deps\n$help_msg" ;
2011-01-04 23:04:08 +00:00
}
v ( "Built '$target'" ) ;
2011-02-26 21:29:04 +00:00
2011-03-20 04:40:32 +00:00
if ( $ opt_test && ! $ t - > { tags } { skip_tests } ) {
2011-06-17 21:13:01 +00:00
opendir ( my $ dh , dir ( $ target ) ) or die ;
2011-03-19 05:33:43 +00:00
my @ test_files = grep { /_test\.go$/ } readdir ( $ dh ) ;
2011-02-26 21:29:04 +00:00
closedir ( $ dh ) ;
if ( @ test_files ) {
2011-06-17 21:13:01 +00:00
if ( system ( "make" , @ quiet , "-C" , dir ( $ target ) , "test" ) != 0 ) {
2011-02-26 21:29:04 +00:00
die "Tests failed for $target\n" ;
}
}
}
2011-01-04 23:04:08 +00:00
}
2011-03-19 05:33:43 +00:00
sub find_go_camli_deps {
my $ target = shift ;
2011-03-20 04:20:35 +00:00
if ( $ target =~ /\bthird_party\b/ ) {
# Skip third-party stuff.
return ;
}
unless ( $ target =~ m !lib/go/camli! ||
2011-06-17 21:13:01 +00:00
$ target =~ m !^camlistore\.org/! ||
2011-03-20 04:20:35 +00:00
$ target =~ m !(server|clients)/go\b! ) {
2011-03-19 05:33:43 +00:00
return ;
}
2011-06-17 21:13:01 +00:00
my $ t = $ targets { $ target } or die "Bogus or undeclared build target: $target\n" ;
my $ target_dir = dir ( $ target ) ;
2011-06-18 18:58:55 +00:00
v2 ( "Deps of $target in $target_dir" ) ;
2011-06-17 21:13:01 +00:00
opendir ( my $ dh , $ target_dir ) or die "Failed to open directory: $target\n" ;
2011-03-23 01:29:40 +00:00
my @ go_files = grep { ! m !^\.\#! } grep { ! /_testmain\.go$/ } grep { /\.go$/ } readdir ( $ dh ) ;
2011-03-19 05:33:43 +00:00
closedir ( $ dh ) ;
# TODO: just stat the files first and keep a cache file of the
# deps somewhere (the header of the generated Makefile?) but
2011-06-30 04:07:37 +00:00
# maybe it is not worth it. for now we'll parse all the files
2011-03-19 05:33:43 +00:00
# every time to find their deps and also generate the Makefile
# every time.
my @ deps ;
my % seen ; # $dep -> 1
for my $ f ( @ go_files ) {
2011-06-17 21:13:01 +00:00
open ( my $ fh , "$target_dir/$f" ) or die "Failed to open $target_dir/$f: $!" ;
2011-03-19 05:33:43 +00:00
my $ src = do { local $/ ; <$fh> ; } ;
2011-05-22 19:38:29 +00:00
if ( $ src =~ m !^import\b!m ) {
unless ( $ src =~ m !\bimport\s*\((.+?)\)!s ) {
2011-06-17 21:13:01 +00:00
die "Failed to parse imports from $target_dir/$f.\n" .
2011-05-22 19:38:29 +00:00
"No imports(...) block? Um, add a fake one. :)\n" ;
}
my $ imports = $ 1 ;
while ( $ imports =~ m !"(camli\b.+?)"!g ) {
my $ dep = "lib/go/$1" ;
push @ deps , $ dep unless $ seen { $ dep } + + ;
}
2011-06-17 21:13:01 +00:00
while ( $ imports =~ m !"(camlistore\.org/.+?)"!g ) {
my $ dep = $ 1 ;
push @ deps , $ dep unless $ seen { $ dep } + + ;
}
2011-03-19 05:33:43 +00:00
}
}
foreach my $ dep ( @ deps ) {
unless ( grep { $ _ eq $ dep } @ { $ t - > { deps } } ) {
push @ { $ t - > { deps } } , $ dep ;
}
}
2011-03-20 04:20:35 +00:00
}
2011-06-17 21:13:01 +00:00
sub dir {
my $ target = shift ;
my $ t = $ targets { $ target } or die "Bogus or undeclared build target: $target\n" ;
return $ t - > { tags } { dir } || $ target ;
}
2011-03-20 04:20:35 +00:00
sub gen_target_makefile {
my $ target = shift ;
my $ type = "" ;
if ( $ target =~ m !lib/go/camli! ) {
$ type = "pkg" ;
} elsif ( $ target =~ m !(server|clients)/go\b! ) {
$ type = "cmd" ;
2011-06-18 18:58:55 +00:00
} elsif ( $ target =~ m !^camlistore\.org/! ) {
# type to be set later
2011-03-20 04:20:35 +00:00
} else {
return ;
}
my $ t = $ targets { $ target } or die "Bogus or undeclared build target: $target\n" ;
2011-06-17 21:13:01 +00:00
my $ override_target ; # optional override of what to write to Makefile
2011-03-20 04:20:35 +00:00
my @ deps = @ { $ t - > { deps } } ;
2011-06-17 21:13:01 +00:00
my $ target_dir = dir ( $ target ) ;
opendir ( my $ dh , $ target_dir ) or die ;
my @ dir_files = readdir ( $ dh ) ;
my @ go_files = grep { ! m !^\.\#! } grep { ! /_testmain\.go$/ } grep { /\.go$/ } @ dir_files ;
2011-03-20 04:20:35 +00:00
closedir ( $ dh ) ;
2011-03-19 07:27:03 +00:00
2011-06-17 21:13:01 +00:00
if ( $ t - > { tags } { fileembed } ) {
$ type = "pkg" ;
die "No fileembed.go file in $target, but declared with tag 'fileembed'\n" unless
grep { $ _ eq "fileembed.go" } @ go_files ;
open ( my $ fe , "$target_dir/fileembed.go" ) or die ;
my ( $ pattern , $ embed_pkg ) ;
while ( <$fe> ) {
if ( ! $ embed_pkg && /^package (\S+)/ ) {
$ embed_pkg = $ 1 ;
}
if ( ! $ pattern && /^#fileembed pattern (\S+)\s*$/ ) {
$ pattern = $ 1 ;
}
if ( ! $ override_target && /^#fileembed target (\S+)\s*$/ ) {
$ override_target = $ 1 ;
}
}
close ( $ fe ) ;
die "No #filepattern found in $target_dir/fileembed.go" unless $ pattern ;
foreach my $ resfile ( grep { /^$pattern$/o } @ dir_files ) {
my $ gores = "_embed_${resfile}.go" ;
push @ go_files , $ gores ;
if ( modtime ( "$target_dir/$gores" ) < max ( modtime ( "build.pl" ) , modtime ( "$target_dir/$resfile" ) ) ) {
generate_embed_file ( $ embed_pkg , $ resfile , "$target_dir/$resfile" , "$target_dir/$gores" ) ;
}
}
}
2011-05-11 18:43:07 +00:00
# Generate the Makefile
my $ mfc = "\n\n" ;
$ mfc . = "###### NOTE: THIS IS AUTO-GENERATED FROM build.pl IN THE ROOT; DON'T EDIT\n" ;
$ mfc . = "\n\n" ;
$ mfc . = "include \$(GOROOT)/src/Make.inc\n" ;
2011-06-30 04:07:37 +00:00
my $ pr = "" ;
2011-03-19 07:27:03 +00:00
if ( @ deps ) {
foreach my $ dep ( @ deps ) {
my $ cam_lib = $ dep ;
$ cam_lib =~ s!^lib/go/!! ;
$ pr . = '$(QUOTED_GOROOT)/pkg/$(GOOS)_$(GOARCH)/' . $ cam_lib . ".a\\\n\t" ;
}
chop $ pr ; chop $ pr ; chop $ pr ;
}
2011-06-30 04:07:37 +00:00
$ mfc . = "PREREQ=$gc_bin $pr\n" ;
2011-03-19 07:27:03 +00:00
if ( $ type eq "pkg" ) {
my $ targ = $ target ;
$ targ =~ s!^lib/go/!! ;
2011-06-17 21:13:01 +00:00
$ targ = $ override_target || $ targ ;
2011-05-11 18:43:07 +00:00
$ mfc . = "TARG=$targ\n" ;
2011-03-19 07:27:03 +00:00
} else {
my $ targ = $ target ;
$ targ =~ s!^.*/!! ;
2011-05-11 18:43:07 +00:00
$ mfc . = "TARG=$targ\n" ;
2011-03-19 07:27:03 +00:00
}
my @ non_test_files = grep { ! /_test\.go/ } @ go_files ;
2011-05-11 18:43:07 +00:00
$ mfc . = "GOFILES=@non_test_files\n" ;
$ mfc . = "include \$(GOROOT)/src/Make.$type\n" ;
2011-06-17 21:13:01 +00:00
set_file_contents ( "$target_dir/Makefile" , $ mfc ) ;
2011-03-19 07:27:03 +00:00
2011-03-19 08:13:01 +00:00
# print "DEPS of $target: @{ $t->{deps} }\n";
2011-03-19 05:33:43 +00:00
}
2011-05-11 18:43:07 +00:00
sub set_file_contents {
my ( $ fn , $ new ) = @ _ ;
2011-05-13 02:11:28 +00:00
if ( - e $ fn ) {
open ( my $ fh , $ fn ) or die "Failed to write to $fn: $!" ;
my $ cur = do { local $/ ; <$fh> } ;
return if $ new eq $ cur ;
}
2011-05-11 18:43:07 +00:00
open ( my $ fh , ">$fn" ) or die ;
print $ fh $ new ;
close ( $ fh ) or die ;
}
2011-01-04 23:04:08 +00:00
sub read_targets {
my $ last ;
for ( <DATA> ) {
2011-02-04 01:32:34 +00:00
if ( m !^\TARGET:\s*(.+)\s*$! ) {
2011-01-04 23:04:08 +00:00
my $ target = $ 1 ;
$ last = $ target ;
$ targets { $ target } || = { deps = > [] } ;
next ;
}
2011-02-04 01:40:53 +00:00
s/\#.*// ;
2011-01-04 23:04:08 +00:00
if ( m !^\s+\-\s(\S+)\s*$! ) {
my $ dep = $ 1 ;
my $ t = $ targets { $ last } or die "Unexpected dependency line: $_" ;
push @ { $ t - > { deps } } , $ dep ;
2011-02-04 01:40:53 +00:00
next ;
}
2011-06-17 21:13:01 +00:00
if ( m !^\s+\=\s*(\S+):(\S+)\s*$! ) {
my $ tag = $ 1 ;
my $ t = $ targets { $ last } or die "Unexpected dependency line: $_" ;
$ t - > { tags } { $ tag } = $ 2 ;
next ;
}
2011-02-04 01:40:53 +00:00
if ( m !^\s+\=\s*(\S+)\s*$! ) {
my $ tag = $ 1 ;
my $ t = $ targets { $ last } or die "Unexpected dependency line: $_" ;
$ t - > { tags } { $ tag } = 1 ;
next ;
2011-01-04 23:04:08 +00:00
}
}
#use Data::Dumper;
#print Dumper(\%targets);
}
2011-05-30 00:34:32 +00:00
sub record_go_version {
return unless $ ENV { USER } eq "bradfitz" ;
return unless `uname -m` =~ /x86_64/ ;
my $ ver = `6g -V` ;
open ( my $ fh , ">.last_go_version" ) or return ;
print $ fh $ ver ;
close ( $ fh ) ;
}
2011-05-30 19:22:14 +00:00
sub filter_os_targets {
my @ targets = @ _ ;
my @ out ;
my $ is_linux = ( `uname` =~ /linux/i ) ;
foreach my $ t ( @ targets ) {
if ( $ targets { $ t } { tags } { only_os_linux } && ! $ is_linux ) {
next ;
}
push @ out , $ t ;
}
return @ out ;
}
2011-06-17 21:13:01 +00:00
sub modtime {
my $ file = shift ;
my @ st = stat ( $ file ) ;
return $ st [ 9 ] ;
}
sub max {
my $ n = shift ;
foreach my $ c ( @ _ ) {
$ n = $ c if $ c > $ n ;
}
return $ n ;
}
sub generate_embed_file {
my ( $ pkg , $ base_file , $ source , $ dest ) = @ _ ;
print STDERR "# Generating $base_file -> $dest\n" ;
open ( my $ sf , $ source ) or die "Error opening $source for embedding: $!\n" ;
open ( my $ dest , ">$dest" ) or die "Error creating $dest for embedding: $!\n" ;
my $ contents = do { local $/ ; <$sf> } ;
print $ dest "// THIS FILE IS AUTO-GENERATED FROM $base_file\n" ;
print $ dest "// DO NOT EDIT.\n" ;
print $ dest "package $pkg\n" ;
my $ escaped ;
for my $ i ( 0 .. length ( $ contents ) - 1 ) {
my $ ch = substr ( $ contents , $ i , 1 ) ;
my $ b = ord ( $ ch ) ;
if ( $ b >= 32 && $ b < 127 && $ b != ord ( "\"" ) && $ b != ord ( "\\" ) ) {
$ escaped . = $ ch ;
} else {
$ escaped . = "\\x" . sprintf ( "%02x" , $ b ) ;
}
if ( + + $ i % 70 == 50 ) {
$ escaped . = "\"+\n\t\"" ;
}
}
print $ dest "func init() {\n\tFiles.Add(\"$base_file\", \"$escaped\");\n}\n" ;
}
2011-01-04 23:04:08 +00:00
__DATA__
2011-02-04 01:32:34 +00:00
2011-05-02 01:21:22 +00:00
TARGET: clients /go/c amdbinit
2011-02-04 01:32:34 +00:00
TARGET: clients /go/c amget
2011-03-19 05:33:43 +00:00
TARGET: clients /go/c amput
2011-03-20 17:25:17 +00:00
TARGET: clients /go/c ammount
2011-05-30 19:22:14 +00:00
= only_os_linux
2011-03-02 02:02:01 +00:00
TARGET: clients /go/c amsync
2011-03-19 05:33:43 +00:00
TARGET: lib /go/c amli / auth
2011-03-19 04:24:10 +00:00
TARGET: lib /go/c amli / blobref
TARGET: lib /go/c amli / blobserver
2011-06-04 04:52:56 +00:00
TARGET: lib /go/c amli /blobserver/co nd
2011-03-19 04:24:10 +00:00
TARGET: lib /go/c amli /blobserver/ handlers
TARGET: lib /go/c amli /blobserver/ localdisk
2011-05-09 13:32:24 +00:00
TARGET: lib /go/c amli /blobserver/ remote
2011-05-23 04:22:21 +00:00
TARGET: lib /go/c amli /blobserver/ replica
2011-05-21 16:26:20 +00:00
TARGET: lib /go/c amli /blobserver/s hard
2011-03-28 05:06:29 +00:00
TARGET: lib /go/c amli /blobserver/s 3
2011-03-19 05:33:43 +00:00
TARGET: lib /go/c amli / client
2011-04-16 00:17:33 +00:00
TARGET: lib /go/c amli / errorutil
2011-03-19 05:33:43 +00:00
TARGET: lib /go/c amli / httputil
2011-04-16 05:22:30 +00:00
TARGET: lib /go/c amli / jsonconfig
2011-03-19 05:33:43 +00:00
TARGET: lib /go/c amli / jsonsign
2011-03-26 01:58:14 +00:00
TARGET: lib /go/c amli / lru
2011-03-19 07:48:33 +00:00
TARGET: lib /go/c amli / magic
2011-05-11 15:19:23 +00:00
TARGET: lib /go/c amli / misc
2011-03-27 22:25:21 +00:00
TARGET: lib /go/c amli /misc/ amazon / s3
2011-06-17 21:13:01 +00:00
TARGET: lib /go/c amli /misc/ fileembed
2011-04-26 01:19:48 +00:00
TARGET: lib /go/c amli /misc/ httprange
2011-05-17 04:52:01 +00:00
TARGET: lib /go/c amli /misc/g pgagent
2011-05-15 01:43:07 +00:00
TARGET: lib /go/c amli /misc/ pinentry
2011-06-15 08:42:18 +00:00
TARGET: lib /go/c amli /misc/ resize
2011-06-18 19:01:34 +00:00
TARGET: lib /go/c amli /misc/ vfs
2011-03-19 04:24:10 +00:00
TARGET: lib /go/c amli / mysqlindexer
2011-04-01 19:47:07 +00:00
TARGET: lib /go/c amli / netutil
2011-04-02 05:26:33 +00:00
TARGET: lib /go/c amli / osutil
2011-06-04 19:00:53 +00:00
TARGET: lib /go/c amli / rollsum
2011-03-19 05:33:43 +00:00
TARGET: lib /go/c amli / schema
TARGET: lib /go/c amli / search
TARGET: lib /go/c amli / test
TARGET: lib /go/c amli /test/ asserts
2011-03-20 04:26:00 +00:00
TARGET: lib /go/c amli /third_party/gi thub . com /hanwen/go - fuse / fuse
2011-03-20 04:40:32 +00:00
= skip_tests
2011-05-30 19:22:14 +00:00
= only_os_linux
2011-03-20 04:25:24 +00:00
TARGET: lib /go/c amli /third_party/gi thub . com /Philio/ GoMySQL
2011-03-20 04:40:32 +00:00
= skip_tests
2011-03-19 05:33:43 +00:00
TARGET: lib /go/c amli / webserver
2011-03-30 03:29:32 +00:00
TARGET: server /go/c amlistored
2011-06-17 21:13:01 +00:00
TARGET: camlistore . org /server/ uistatic
= fileembed
= dir:server /go/c amlistored / ui
2011-03-19 05:33:43 +00:00
TARGET: server /go/sigs erver
TARGET: website
TARGET: clients / android
= not_in_all # too slow
2011-06-10 18:40:41 +00:00
# foo