summary refs log tree commit diff
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)
downloadnixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.tar
nixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.tar.gz
nixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.tar.bz2
nixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.tar.lz
nixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.tar.xz
nixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.tar.zst
nixpkgs-153d4e65a1c4ed37877c4db982727d89df15ea82.zip
* 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 00000000000..5515f55d6e4
--- /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 00000000000..9f150d8bda2
--- /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];
+}