aboutsummaryrefslogtreecommitdiff
path: root/pkgs/build-support/buildenv
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2006-11-28 16:46:12 +0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2006-11-28 16:46:12 +0000
commit153d4e65a1c4ed37877c4db982727d89df15ea82 (patch)
tree065bac3336ce69974796a24fd18cc080f5e4eb92 /pkgs/build-support/buildenv
parent89ba1cba24202f2ca65ae482359b39aee6c8ba97 (diff)
* Fork of build-env in the Nix distribution. This one supports
ignoring collisions and selectively including directories. svn path=/nixpkgs/trunk/; revision=7160
Diffstat (limited to 'pkgs/build-support/buildenv')
-rwxr-xr-xpkgs/build-support/buildenv/builder.pl167
-rw-r--r--pkgs/build-support/buildenv/default.nix29
2 files changed, 196 insertions, 0 deletions
diff --git a/pkgs/build-support/buildenv/builder.pl b/pkgs/build-support/buildenv/builder.pl
new file mode 100755
index 000000000000..5515f55d6e46
--- /dev/null
+++ b/pkgs/build-support/buildenv/builder.pl
@@ -0,0 +1,167 @@
+#! @perl@ -w
+
+use strict;
+use Cwd;
+use IO::Handle;
+use File::Path;
+use File::Basename;
+
+STDOUT->autoflush(1);
+
+my $out = $ENV{"out"};
+mkdir "$out", 0755 || die "error creating $out";
+
+
+my $symlinks = 0;
+
+
+my @pathsToLink = split ' ', $ENV{"pathsToLink"};
+
+sub isInPathsToLink {
+ my $path = shift;
+ $path = "/" if $path eq "";
+ foreach my $elem (@pathsToLink) {
+ return 1 if substr($path, 0, length($elem)) eq $elem;
+ }
+ return 0;
+}
+
+
+sub symLinkMkdir {
+ my $src = shift;
+ my $dst = shift;
+ my $dir = dirname $dst;
+ mkpath $dir;
+ symlink($src, $dst) ||
+ die "error creating link `$dst': $!";
+ $symlinks++;
+}
+
+
+# For each activated package, create symlinks.
+
+sub createLinks {
+ my $relName = shift;
+ my $srcDir = shift;
+ my $dstDir = shift;
+ my $ignoreCollisions = shift;
+
+ my @srcFiles = glob("$srcDir/*");
+
+ foreach my $srcFile (@srcFiles) {
+ my $baseName = $srcFile;
+ $baseName =~ s/^.*\///g; # strip directory
+ my $dstFile = "$dstDir/$baseName";
+ my $relName2 = "$relName/$baseName";
+
+ # Urgh, hacky...
+ if ($srcFile =~ /\/propagated-build-inputs$/ ||
+ $srcFile =~ /\/nix-support$/ ||
+ $srcFile =~ /\/perllocal.pod$/ ||
+ $srcFile =~ /\/info\/dir$/ ||
+ $srcFile =~ /\/log$/)
+ {
+ # Do nothing.
+ }
+
+ elsif (-d $srcFile) {
+
+ if (!isInPathsToLink($relName2)) {
+ # This path is not in the list of paths to link, but
+ # some of its children may be.
+ createLinks($relName2, $srcFile, $dstFile, $ignoreCollisions);
+ next;
+ }
+
+ lstat $dstFile;
+
+ if (-d _) {
+ createLinks($relName2, $srcFile, $dstFile, $ignoreCollisions);
+ }
+
+ elsif (-l _) {
+ my $target = readlink $dstFile or die;
+ if (!-d $target) {
+ die "collission between directory `$srcFile' and non-directory `$target'";
+ }
+ unlink $dstFile or die "error unlinking `$dstFile': $!";
+ mkpath $dstFile;
+ createLinks($relName2, $target, $dstFile, $ignoreCollisions);
+ createLinks($relName2, $srcFile, $dstFile, $ignoreCollisions);
+ }
+
+ else {
+ symLinkMkdir $srcFile, $dstFile;
+ }
+ }
+
+ elsif (-l $dstFile) {
+ if (!$ignoreCollisions) {
+ my $target = readlink $dstFile;
+ die "collission between `$srcFile' and `$target'";
+ }
+ }
+
+ else {
+ next unless isInPathsToLink($relName2);
+ symLinkMkdir $srcFile, $dstFile;
+ }
+ }
+}
+
+
+my %done;
+my %postponed;
+
+sub addPkg;
+sub addPkg {
+ my $pkgDir = shift;
+ my $ignoreCollisions = shift;
+
+ return if (defined $done{$pkgDir});
+ $done{$pkgDir} = 1;
+
+# print "symlinking $pkgDir\n";
+ createLinks("", "$pkgDir", "$out", $ignoreCollisions);
+
+ my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
+ if (-e $propagatedFN) {
+ open PROP, "<$propagatedFN" or die;
+ my $propagated = <PROP>;
+ close PROP;
+ my @propagated = split ' ', $propagated;
+ foreach my $p (@propagated) {
+ $postponed{$p} = 1 unless defined $done{$p};
+ }
+ }
+}
+
+
+# Symlink to the packages that have been installed explicitly by the user.
+my @args = split ' ', $ENV{"paths"};
+
+foreach my $pkgDir (sort @args) {
+ addPkg($pkgDir, $ENV{"ignoreCollisions"} eq "1");
+}
+
+
+# Symlink to the packages that have been "propagated" by packages
+# installed by the user (i.e., package X declares that it want Y
+# installed as well). We do these later because they have a lower
+# priority in case of collisions.
+while (scalar(keys %postponed) > 0) {
+ my @pkgDirs = keys %postponed;
+ %postponed = ();
+ foreach my $pkgDir (sort @pkgDirs) {
+ addPkg($pkgDir, 1);
+ }
+}
+
+
+print STDERR "created $symlinks symlinks in user environment\n";
+
+
+my $manifest = $ENV{"manifest"};
+if ($manifest ne "") {
+ symlink($manifest, "$out/manifest") or die "cannot create manifest";
+}
diff --git a/pkgs/build-support/buildenv/default.nix b/pkgs/build-support/buildenv/default.nix
new file mode 100644
index 000000000000..9f150d8bda20
--- /dev/null
+++ b/pkgs/build-support/buildenv/default.nix
@@ -0,0 +1,29 @@
+# buildEnv creates a tree of symlinks to the specified paths. This is
+# a fork of the buildEnv in the Nix distribution. Most changes should
+# eventually be merged back into the Nix distribution.
+
+{stdenv, perl}:
+
+{ name
+
+, # The manifest file (if any). A symlink $out/manifest will be
+ # created to it.
+ manifest ? ""
+
+, # The paths to symlink.
+ paths
+
+, # Whether to ignore collisions or abort.
+ ignoreCollisions ? false
+
+, # The paths (relative to each element of `paths') that we want to
+ # symlink (e.g., ["/bin"]). Any file not inside any of the
+ # directories in the list is not symlinked.
+ pathsToLink ? ["/"]
+}:
+
+stdenv.mkDerivation {
+ inherit name manifest paths ignoreCollisions pathsToLink;
+ realBuilder = perl + "/bin/perl";
+ args = ["-w" ./builder.pl];
+}