add a db stats page.
[sgn.git] / lib / SGN / Build.pm
blobfe6c64c07cfb5dd34b674f26959545cc6ce5d65b
1 package SGN::Build;
2 use strict;
3 use warnings;
5 use version;
7 my $HAVE_PARSE_DEB_CONTROL;
9 BEGIN {
10 eval { require Parse::Deb::Control };
11 if( $@ ) {
12 warn "WARNING: Failed to load Parse::Deb::Control, and it is needed to check R dependencies:\n$@\n"
14 $HAVE_PARSE_DEB_CONTROL = !$@;
17 use Module::Build;
18 use base 'Module::Build';
20 my $HAVE_CAPTURE;
21 BEGIN {
22 eval { require Capture::Tiny };
23 $HAVE_CAPTURE = !$@;
26 # we should probably convert this to autodie at some point
28 # build action just runs make on programs
29 sub ACTION_build {
30 my $self = shift;
31 $self->SUPER::ACTION_build(@_);
32 system "make -C programs";
33 if($?) {
34 _handle_errors($?);
35 die "make -C programs failed\!n";
38 unless( $ENV{SGN_SHIPWRIGHT_BUILDING} ) {
39 $self->check_R
40 or die "R dependency check failed, aborting.\n";
45 # override install to just copy the whole dir into the install_base
46 sub ACTION_install {
47 my $self = shift;
49 # installation is just copying the entire dist into
50 # install_base/sgn
51 require File::Spec;
52 my $tgt_dir = File::Spec->catdir($self->install_base,'sgn');
53 system 'cp', '-rl', '.', $tgt_dir;
54 if($?) {
55 _handle_errors($?);
56 die "SGN site copy ( cp -rl . $tgt_dir ) failed!\n";
60 sub ACTION_clean {
61 shift->SUPER::ACTION_clean(@_);
62 system "make -C programs clean";
63 if($?) {
64 _handle_errors($?);
65 die "make -C programs clean failed!\n";
69 sub ACTION_installdeps {
70 my $self = shift;
72 $self->_R_installdeps;
74 $self->SUPER::ACTION_installdeps( @_ );
77 sub create_build_script {
78 my $self = shift;
80 $self->check_R
81 or warn $self->{R}{check_output};
83 return $self->SUPER::create_build_script(@_);
86 sub check_R {
87 my ( $self, @args ) = @_;
89 if( $HAVE_CAPTURE ) {
90 my $ret;
91 my $out = Capture::Tiny::capture_merged {
92 $ret = $self->_check_R_version;
95 $self->{R}{check_output} = $out;
97 return $ret;
98 } else {
99 return $self->_check_R_version
103 sub _R_installdeps {
104 my ( $self ) = @_;
106 print "\n\nInstalling R dependencies in ~/cxgn/R_libs. \nDepending on the number of deps to install, this may take long time.\n\nAfter the installation completes, set the env variable R_LIBS_USER in your system (/etc/R/Renviron) to \"~/cxgn/R_libs\". This will ensure deps you manually install in R will be in the same place as sgn R libraries and avoid installation of the same R packages in multiple places. It will also add packages in the \"~/cxgn/R_libs\" to the search path\n\n";
108 my $rout = qx /Rscript R\/sgnPackages.r 2>&1 /;
110 print "\nR dependencies installation output:\n $rout\n";
112 if( $? ) {
113 _handle_errors($?);
114 warn "Failed to automatically install R dependencies\n\n";
115 } else {
116 print "Successfully installed R dependencies.\n\n";
121 sub _handle_errors {
122 my ($exit_code) = @_;
123 if ($exit_code == -1) {
124 print "Error: failed to execute: $!\n";
125 } elsif ($exit_code & 127) {
126 warn sprintf("Error: child died with signal %d, %s coredump\n",
127 ($exit_code & 127), ($exit_code & 128) ? 'with' : 'without');
128 } else {
129 warn sprintf("Error: child exited with value %d\n",$exit_code >> 8);
133 sub _run_R_check {
134 my $self = shift;
136 # check the R version ourself, since R CMD check apparently does
137 # not do it.
138 $self->_check_R_version
139 or return 0;
141 if ( $? ) {
142 _handle_errors($?);
143 warn "\nR version PREREQUISITE CHECK FAILED.\n\n";
144 return 0;
145 } else {
146 print "\nR version prerequisite OK.\n\n";
147 return 1;
151 sub _check_R_version {
152 my $self = shift;
154 unless ($HAVE_PARSE_DEB_CONTROL) {
155 warn "Parse::Deb::Control not present, skipping R configuration";
156 return 0;
158 my ( $cmp, $v ) = $self->_R_version_required;
160 if( eval '$self->_R_version_current'." $cmp version->parse('$v')" ) {
161 return 1;
162 } else {
163 warn "R VERSION CHECK FAILED, we have ".$self->_R_version_current.", but we require $cmp $v.\n";
164 warn "To install R : sudo apt-get update; sudo apt-get install r-base r-base-dev\n\n";
165 return 0;
169 # parse and return the R cran deps file
170 sub _R_desc {
171 return Parse::Deb::Control->new([qw[ R_files cran ]]);
174 # parse and return the version of R we require as string list like
175 # ('>=','2.10.0')
176 sub _R_version_required {
177 my $self = shift;
179 my @k = $self->_R_desc->get_keys('Depends')
180 or return ( '>=', 0 );
181 my ($version) = ${$k[0]->{value}} =~ / \b R \s* \( ([^\)]+) /x
182 or return ( '>=', 0 );
184 my @v = split /\s+/, $version;
185 unshift @v, '==' unless @v > 1;
187 return @v;
190 # parse and return the current R version as a version object
191 sub _R_version_current {
192 my $r = `R --version`;
193 return 0 unless $r;
195 $r =~ /R version ([\d\.]+)/;
197 return version->new($1);