--- /dev/null
+#!/usr/bin/perl
+# Copyright (c) 2010 Mellanox Technologies. All rights reserved.
+#
+# This Software is licensed under one of the following licenses:
+#
+# 1) under the terms of the "Common Public License 1.0" a copy of which is
+# available from the Open Source Initiative, see
+# http://www.opensource.org/licenses/cpl.php.
+#
+# 2) under the terms of the "The BSD License" a copy of which is
+# available from the Open Source Initiative, see
+# http://www.opensource.org/licenses/bsd-license.php.
+#
+# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+# copy of which is available from the Open Source Initiative, see
+# http://www.opensource.org/licenses/gpl-license.php.
+#
+# Licensee has the right to choose one of the above licenses.
+#
+# Redistributions of source code must retain the above copyright
+# notice and one of the license notices.
+#
+# Redistributions in binary form must reproduce both the above copyright
+# notice, one of the license notices in the documentation
+# and/or other materials provided with the distribution.
+
+use strict;
+use File::Basename;
+use File::Path;
+use File::Find;
+use File::Copy;
+use Cwd;
+use Term::ANSIColor qw(:constants);
+
+my $CWD = getcwd;
+my $GIT = 'git';
+my $GIT_VERSION = `$GIT --version`;
+my $user = getpwuid($<);
+my $verbose = 0;
+my $build_release = 0;
+my $build_daily = 0;
+my $build_scripts = 0;
+my $packages_dir = 'packages';
+my $distribution = 'OFED';
+my $builddir = '/tmp/' . $user;
+my $tmpdir = '/tmp/' . $user;
+my $TOPDIR = $builddir . "/topdir";
+my $destdir;
+my $version;
+my $release;
+my $log;
+my $package;
+my %packages;
+my @plist = ();
+my $starttime = sub{sprintf '%04d%02d%02d-%02d%02d', $_[5]+1900, $_[4]+1, $_[3], $_[2], $_[1]}->(localtime);
+
+sub usage
+{
+ print "\nUsage: $0 --version <version> [-r|--release]|[--daily] [-d|--distribution <distribution name>] [-v|--verbose]\n";
+ print "\t\t[-b|--builddir <build directory>]\n";
+ print "\t\t[-p|--packagesdir <packages directory>]\n";
+ print "\n";
+ exit 0;
+}
+
+sub getch
+{
+ my $c;
+ system("stty -echo raw");
+ $c=getc(STDIN);
+ system("stty echo -raw");
+ # Exit on Ctrl+c or Esc
+ if ($c eq "\cC" or $c eq "\e") {
+ print "\n";
+ exit 1;
+ }
+ print "$c\n";
+ return $c;
+}
+
+sub print_package_info
+{
+ print "\n\nDate:" . localtime(time) . "\n";
+ for my $key ( keys %packages ) {
+ print "$key:\n";
+ print "======================================\n";
+ my %pack = %{$packages{$key}};
+ for my $subkey ( keys %pack ) {
+ print $subkey . ' = ' . $pack{$subkey} . "\n";
+ }
+ print "\n";
+ }
+}
+
+sub print_red
+{
+ print RED @_, RESET "\n";
+}
+
+sub print_blue
+{
+ print BLUE @_, RESET "\n";
+}
+
+sub print_green
+{
+ print GREEN @_, RESET "\n";
+}
+
+sub print_and_log
+{
+ my $msg = shift @_;
+ print LOG $msg . "\n";
+ print $msg . "\n" if ($verbose);
+}
+
+sub ex
+{
+ my $cmd = shift @_;
+ my $sig;
+ my $res;
+
+ print_and_log "Running: $cmd";
+ system("$cmd >> $log 2>&1");
+ $res = $? >> 8;
+ $sig = $? & 127;
+ if ($sig or $res) {
+ print_red "Failed command: $cmd";
+ exit 1;
+ }
+}
+
+sub set_cfg
+{
+ my ($name, $conf) = @_;
+
+ open (CONF, $conf) || die "Can't open $conf: $!\n";
+
+ while (<CONF>) {
+ next if (m@^\s+$|^#.*@);
+ my ($key, $value) = split('=');
+ chomp $key;
+ chomp $value;
+ $value =~ s/["']//g;
+ $packages{$name}{$key} = $value;
+ }
+
+ if (not $packages{$name}{'getMethod'}) {
+ print_red "getMethod is not defined in $conf";
+ exit 1;
+ }
+
+ if ($packages{$name}{'getMethod'} =~ /git/) {
+ if (not $packages{$name}{'git_url'}) {
+ print_red "git_url is not defined in $conf";
+ exit 1;
+ }
+ if (not $packages{$name}{'git_branch'}) {
+ print_red "git_branch is not defined in $conf";
+ exit 1;
+ }
+ } elsif ($packages{$name}{'getMethod'} =~ /tarball/) {
+ if (not $packages{$name}{'URL'} and not $packages{$name}{'local_tarball'}) {
+ print_red "URL is not defined in $conf";
+ exit 1;
+ }
+ } elsif ($packages{$name}{'getMethod'} =~ /srpm/) {
+ if (not $packages{$name}{'URL'}) {
+ print_red "URL is not defined in $conf";
+ exit 1;
+ }
+ } else {
+ print_red "getMethod $packages{$name}{'getMethod'} is not supported";
+ exit 1;
+ }
+
+ close (CONF);
+}
+
+sub get_from_git
+{
+ my $name = shift @_;
+ my $ref;
+ my $targz = 'tar.gz';
+ my $cmd = "$GIT clone -s --bare";
+
+ print "get_from_git: name $name\n" if ($verbose);
+ if ($packages{$name}{'git_reference_dir'} and -d $packages{$name}{'git_reference_dir'}) {
+ $cmd .= " --reference $packages{$name}{'git_reference_dir'}";
+ }
+
+ if ($packages{$name}{'git_extra_flags'}) {
+ $cmd .= " $packages{$name}{'git_extra_flags'}";
+ }
+
+ $cmd .= " $packages{$name}{'git_url'} .git";
+
+ rmtree $tmpdir . '/' . $name;
+ mkpath $tmpdir . '/' . $name;
+ chdir $tmpdir . '/' . $name;
+
+ ex "$cmd";
+
+ if ($GIT_VERSION =~ /1.[5-9].[3-9]|1.[6-9]/) {
+ ex "perl -ni -e \"s/(bare = ).*/\${1}false/;print\" .git/config";
+ }
+
+ # Set ref
+ # TBD: add support for checkout from tag and from commit
+ $ref = $packages{$name}{'git_branch'};
+ if ($name =~ /ofa_kernel/) {
+ ex "$GIT checkout $ref ofed_scripts/ofed_checkout.sh";
+ ex "ofed_scripts/ofed_checkout.sh $ref";
+ print BUILD_ID `git log -1 | head -1` . "\n";
+
+ $packages{$name}{'version'} = (split '-',$version)[0];
+ if ($build_release) {
+ $packages{$name}{'release'} = $release;
+ } else {
+ $packages{$name}{'release'} = '1' . `setlocalversion`;
+ }
+
+ open (IN, "+< ofed_scripts/ofa_kernel.spec");
+ my @file = <IN>;
+ seek IN,0,0;
+ foreach my $line (@file) {
+ $line =~ s/\@VERSION@/$packages{$name}{'version'}/g;
+ $line =~ s/\@RELEASE@/$packages{$name}{'release'}/g;
+ print IN $line;
+ }
+ close IN;
+ ex "ln -s ofed_scripts/ofa_kernel.spec";
+ $targz = 'tgz';
+
+ } elsif ($name =~ /mlnx-ofc/) {
+ ex "$GIT checkout $ref scripts/mlxfc_checkout.sh";
+ ex "scripts/mlxfc_checkout.sh $ref";
+ print BUILD_ID `git log -1 | head -1` . "\n";
+
+ ex "ln -snf scripts/makefile.mlnx_ofc makefile";
+ ex "ln -snf scripts/Makefile.mlnx_ofc Makefile";
+
+ if ($build_release) {
+ $packages{$name}{'release'} = $release;
+ } else {
+ $packages{$name}{'release'} = '1' . `setlocalversion`;
+ }
+ ex "ln -s scripts/mlxfc.spec $name.spec";
+
+ } else {
+ ex "$GIT checkout $ref";
+ print BUILD_ID `git log -1 | head -1` . "\n";
+
+ if ($build_release) {
+ $packages{$name}{'release'} = $release;
+ } else {
+ $packages{$name}{'release'} = '1' . `setlocalversion`;
+ }
+
+ # ofed-scripts and ofed-docs
+ if ($name =~ /ofed/) {
+ $packages{$name}{'version'} = (split '-',$version)[0];
+ open (IN, "+< $name.spec") or die "Can't open $name.spec file: $!\n";
+ my @file = <IN>;
+ seek IN,0,0;
+ foreach my $line (@file) {
+ $line =~ s/\@VERSION@/$packages{$name}{'version'}/g;
+ $line =~ s/\@RELEASE@/$packages{$name}{'release'}/g;
+ $line =~ s/(Version:).*/$1 $packages{$name}{'version'}/g;
+ $line =~ s/(Release:).*/$1 $packages{$name}{'release'}/g;
+ print IN $line;
+ }
+ close IN;
+
+ if ($name =~ /docs/) {
+ copy "README.txt", "$destdir";
+ copy "LICENSE", "$destdir";
+ ex "/bin/cp -a ./ $destdir/docs";
+ } elsif ($name =~ /scripts/) {
+ copy "install.pl", "$destdir";
+ copy "uninstall.sh", "$destdir";
+ chmod 0755, "$destdir/install.pl";
+ chmod 0755, "$destdir/uninstall.sh";
+
+ open (IN, "$destdir/BUILD_ID") or die "Can't open $destdir/BUILD_ID file: $!\n";
+ seek IN,0,0;
+ my @file = <IN>;
+ open (OUT, "> ofed_info") or die "Can't open ofed_info file: $!\n";
+ print OUT "#!/bin/bash\n";
+ print OUT "cat << EOF\n";
+ foreach my $line (@file) {
+ print OUT $line;
+ }
+ print OUT "EOF\n";
+ close OUT;
+ close IN;
+ chmod 0755, 'ofed_info';
+ }
+ }
+
+ # Apply patches
+ if (-f "fixes/series") {
+ print_and_log "Applying patches for $name";
+ open (SERIES, "fixes/series") or die "Can't open file fixes/series: $!\n";
+ my @file = <SERIES>;
+ seek IN,0,0;
+ foreach my $line (@file) {
+ chomp $line;
+ ex "patch -p1 -l -i fixes/$line";
+ }
+ close SERIES;
+ }
+
+ if (-f "autogen.sh") {
+ ex "./autogen.sh";
+ }
+
+ if (not -f "$name.spec" and -f "configure") {
+ ex "./configure";
+ }
+ }
+
+ if (not $packages{$name}{'version'}) {
+ $packages{$name}{'version'} = `grep "^Version:" $name.spec | cut -d ' ' -f 2`;
+ chomp $packages{$name}{'version'};
+ }
+ if (not $packages{$name}{'release'}) {
+ $packages{$name}{'release'} = $release;
+ }
+
+ chdir $tmpdir;
+ rmtree $name-$packages{$name}{'version'};
+ move "$name", "$name-$packages{$name}{'version'}";
+ ex "tar czvf $name-$packages{$name}{'version'}.$targz --exclude=.git $name-$packages{$name}{'version'}";
+ sleep 1;
+ rmtree (["$name", "$name-$packages{$name}{'version'}"]);
+ $packages{$name}{'local_tarball'} = $tmpdir . '/' . "$name-$packages{$name}{'version'}.$targz";
+}
+
+sub get_package
+{
+ my $name = shift @_;
+ my $method = $packages{$package}{'getMethod'};
+ my $url;
+ my $response;
+
+ rmtree $tmpdir . '/' . $name;
+ mkpath $tmpdir . '/' . $name;
+ chdir $tmpdir . '/' . $name;
+
+ $url = $packages{$name}{'URL'};
+ print_and_log "Going to download $name from $url";
+
+ if ($packages{$name}{'use_scp'}) {
+ if ($packages{$name}{'use_latest'}) {
+ $url .= '/latest.txt';
+ ex "scp $url .";
+ $packages{$name}{$method} = `grep $name latest.txt`;
+ chomp $packages{$name}{$method};
+ $url = $packages{$name}{'URL'} . '/' . $packages{$name}{$method};
+ $packages{$package}{'URL'} = $url;
+ print_and_log "Updated $name URL: $url";
+ }
+
+ ex "scp $url .";
+ print_and_log "Downloaded $url";
+
+ } else {
+ if ($packages{$name}{'use_latest'}) {
+ $url .= '/latest.txt';
+ ex "wget $url";
+ $packages{$name}{$method} = `grep $name latest.txt`;
+ chomp $packages{$name}{$method};
+ $url = $packages{$name}{'URL'} . '/' . $packages{$name}{$method};
+ $packages{$package}{'URL'} = $url;
+ print_and_log "Updated $name URL: $url";
+ }
+
+ ex "wget $url";
+ }
+
+ if (not $packages{$name}{$method}) {
+ $packages{$name}{$method} = basename($url);
+ }
+
+ $packages{$name}{'local_' . $method} = $tmpdir . '/' . $name . '/' . $packages{$name}{$method};
+ if (not -f $packages{$name}{'local_' . $method}) {
+ print_and_log "Failed to download $packages{$name}{$method}";
+ exit 1;
+ }
+ print_and_log "Downloaded $packages{$name}{$method}";
+}
+
+sub get_srpm
+{
+ my $name = shift @_;
+ my $cmd;
+ if (not -f $packages{$name}{'local_tarball'}) {
+ print_red "File $packages{$name}{'local_tarball'} not found";
+ exit 1;
+ }
+
+ $cmd = "rpmbuild -ts --nodeps --define '_topdir $TOPDIR'";
+
+ if ($name =~ /mft/) {
+ $cmd .= " --define 'KVERSION 0'"
+ }
+
+ $cmd .= " $packages{$name}{'local_tarball'}";
+
+ ex "$cmd";
+ $packages{$name}{'local_srpm'} = `/bin/ls $TOPDIR/SRPMS/$name*`;
+ chomp $packages{$name}{'local_srpm'};
+ if (not $packages{$name}{'local_srpm'}) {
+ print_and_log "Failed to create $name source rpm";
+ exit 1;
+ }
+ print_and_log "Created $packages{$name}{'local_srpm'}";
+}
+
+### MAIN ###
+
+while ( $#ARGV >= 0 ) {
+
+ my $cmd_flag = shift(@ARGV);
+
+ if ($cmd_flag eq "--version") {
+ $version = shift(@ARGV);
+ } elsif ($cmd_flag eq "-r" or $cmd_flag eq "--release") {
+ $build_release = 1;
+ } elsif ($cmd_flag eq "--daily") {
+ $build_daily = 1;
+ } elsif ($cmd_flag eq "-d" or $cmd_flag eq "--distribution") {
+ $distribution = shift(@ARGV);
+ } elsif ($cmd_flag eq "-p" or $cmd_flag eq "--packagesdir") {
+ $packages_dir = shift(@ARGV);
+ } elsif ($cmd_flag eq "-v") {
+ $verbose = 1;
+ } elsif ($cmd_flag eq "-b" or $cmd_flag eq "--builddir") {
+ $builddir = shift(@ARGV);
+ } else {
+ &usage();
+ exit 1;
+ }
+}
+
+if (! $version) {
+ print_red "version parameter is required";
+ exit 1;
+}
+
+if (not -d "$CWD/$packages_dir") {
+ print_red "Packages directory $CWD/$packages_dir does not exist";
+ print_red "use '--packagesdir' parameter";
+ exit 1
+}
+
+if ($build_release) {
+ $release = $distribution . $version;
+} elsif ($build_daily) {
+ $version .= '-' . $starttime;
+} else {
+ $release = $starttime;
+}
+
+$log = "$CWD/$distribution.build.log";
+rmtree $log;
+open (LOG, "+> $log") or die "Can't open $log: $!\n";
+
+chdir $CWD;
+if (-f "./pre-build") {
+ print_and_log "Running pre-build script";
+ ex "./pre-build";
+}
+
+# Create Distribution directory structure
+$destdir = "$builddir/$distribution-$version";
+print_blue "Building $distribution-$version under $builddir";
+print_blue "See $log";
+print_and_log "Build started at ". localtime(time);
+print_blue "Please wait...\n" if (not $verbose);
+
+if (-d $destdir) {
+ print "$destdir is already exist.\n";
+ print "Do you want to remove $destdir? [y/N]:";
+ my $ans = getch();
+ if ($ans =~ m/[yY]/) {
+ rmtree($destdir);
+ } else {
+ exit 1;
+ }
+}
+
+mkpath([$destdir . '/RPMS', $destdir . '/SRPMS']);
+rmtree($TOPDIR);
+mkpath([$TOPDIR . '/BUILD' ,$TOPDIR . '/RPMS',$TOPDIR . '/SOURCES',$TOPDIR . '/SPECS',$TOPDIR . '/SRPMS']);
+
+open (BUILD_ID, "+> $destdir/BUILD_ID") or die "Can't open $destdir/BUILD_ID file: $!\n";
+print BUILD_ID "$distribution-$version:\n\n";
+
+for my $conf (<$CWD/$packages_dir/*.conf>) {
+ $package = basename($conf);
+ $package =~ s/.conf//;
+
+ set_cfg($package, $conf);
+
+ if ($package eq "ofed-scripts") {
+ $build_scripts = 1;
+ next;
+ }
+
+ if ($packages{$package}{'local_srpm'}) {
+ if (not -f $packages{$package}{'local_srpm'}) {
+ print_red "File $packages{$package}{'local_srpm'} does not exist";
+ exit 1;
+ }
+ print_and_log "Using local copy: $packages{$package}{'local_srpm'}";
+ copy "$packages{$package}{'local_srpm'}", "$destdir/SRPMS";
+ } else {
+ if ($packages{$package}{'getMethod'} =~ /git/) {
+ print BUILD_ID "$package:\n";
+ print BUILD_ID "$packages{$package}{'git_url'} $packages{$package}{'git_branch'}\n";
+
+ if (not $packages{$package}{'local_tarball'}) {
+ get_from_git($package);
+ }
+ get_srpm($package);
+ } elsif ($packages{$package}{'getMethod'} =~ /tarball/) {
+ if (not $packages{$package}{'local_tarball'}) {
+ get_package($package);
+ }
+ print BUILD_ID "$package:\n";
+ print BUILD_ID "$packages{$package}{'URL'}\n\n";
+ get_srpm($package);
+ } elsif ($packages{$package}{'getMethod'} =~ /srpm/) {
+ get_package($package);
+ print BUILD_ID "$package:\n";
+ print BUILD_ID "$packages{$package}{'URL'}\n\n";
+ } else {
+ print_red "Unsupported getMethod: $packages{$package}{'getMethod'}";
+ exit 1;
+ }
+ move "$packages{$package}{'local_srpm'}", "$destdir/SRPMS";
+ }
+
+ # Cleanup
+ for my $file (<$tmpdir/$package*>) {
+ rmtree $file;
+ }
+ push (@plist, $package);
+}
+
+if ($build_scripts) {
+ $package = 'ofed-scripts';
+ print BUILD_ID "$package:\n";
+ print BUILD_ID "$packages{$package}{'git_url'} $packages{$package}{'git_branch'}\n";
+ get_from_git($package);
+ get_srpm($package);
+ push (@plist, $package);
+ move "$packages{$package}{'local_srpm'}", "$destdir/SRPMS";
+}
+close BUILD_ID;
+
+rmtree($TOPDIR);
+chdir $builddir;
+ex "tar czf $distribution-$version.tgz $distribution-$version";
+print_green "$destdir.tgz is ready";
+
+chdir $CWD;
+if (-f "./post-build") {
+ print_and_log "Running post-build script";
+ ex "./post-build $destdir.tgz $distribution $version";
+}
+
+print_and_log "Build finished at ". localtime(time);
+close LOG;
+# print_package_info();