[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#619400: patch providing support for dpkg-crossing multiarch packages



It has become clear that dpkg-cross need to be able to cross multiarch
packages as well as conventional ones. This is because we cannot yet
have cross-arch dependencies to let us simply depend on necessary
cross-libraries, and an arch all package (such as dpkg-cross makes)
cannot install files in the multiarch /usr/lib/<triplet> location
according to multiarch policy (because they could clash with the files
from the real architecture).

This was not really on the roadmap, where we simple expected to be
able to use multiarch packages for crossing-aginst as-is, but we're
not quite there yet.

Here is a patch to provide that functionality without being too hacky.

It also removes all the X11R6 directory special-casing as that is long-gone. 

dpkg-cross will not convert a multiarch package unless
--convert-multiarch is passed to force it to do so. 

It is possible there are still missing fixups needed in pkgconfig and
.la fixup functions, but I've not found any in the tests I've done so
far. 

This has been tested against these ubuntu natty packages:
Multi-Arch:
libc6_2.13-0ubuntu8_amd64.deb 
libc6-dev_2.13-0ubuntu8_amd64.deb
libfreetype6_2.4.4-1ubuntu2_amd64.deb
libfreetype6-dev-2.4.4-1ubuntu2_all.deb (note: this package is not right
because it is not marked Multi-Arch but has its files in multiarch locations 
- this breaks dpkg-cross's behaviour and some files are missed out. I
think that's OK.)

pre-multiarch:
libc6_2.13-0ubuntu1_amd64.deb
libc6-dev_2.13-0ubuntu1_amd64.deb 
libfreetype6_2.4.4-1_amd64.deb 
libfreetype6-dev_2.4.4-1_amd64.deb 


Index: dpkg-cross
===================================================================
RCS file: /cvsroot/dpkg-cross/dpkg-cross/dpkg-cross,v
retrieving revision 1.83
diff -u -r1.83 dpkg-cross
--- dpkg-cross	23 Feb 2011 14:46:33 -0000	1.83
+++ dpkg-cross	25 Mar 2011 15:37:06 -0000
@@ -14,7 +14,7 @@
 @keepdeps $dpkg_statfile $progname $debname $anyway $cross2cross
 $crossdir $crosslib $crosslib64 $crosslib32 $crossinc $data $len
 $retval $dpkg_cmd $mode $pkg @exlist $conffile $removedeps $keepdeps
-$DPKGCROSSVERSION $keep_temp $msg );
+$DPKGCROSSVERSION $keep_temp $msg $multiarchpackage $multiarch $multiarchconv);
 
 setlocale(LC_MESSAGES, "");
 textdomain("dpkg-cross");
@@ -262,14 +262,15 @@
  -?|-h|--help|--version: print this message.
 
 Options:
- -a|--arch ARCH:       set architecture (default: defined in configuration file)
- -v|--verbose:         be verbose
- -q|--quiet:           be quiet
- -A|--convert-anyway:  convert package even if it does not provide any
-                       development files
- -X|--exclude PACKAGE: Exclude this package from the dependency list of the
-                       built package.
- -k|--keep-temp:       Keep the temporary archives when installing.
+ -a|--arch ARCH:         set architecture (default: defined in configuration file)
+ -v|--verbose:           be verbose
+ -q|--quiet:             be quiet
+ -A|--convert-anyway:    convert package even if it does not provide any
+                         development files
+ -M|--convert-multiarch: convert package even if it is a multiarch package
+ -X|--exclude PACKAGE:   Exclude this package from the dependency list of the
+                         built package.
+ -k|--keep-temp:         Keep the temporary archives when installing.
 
 dpkg-cross installs or removes libraries and include files for
 cross-compiling Debian packages. It reads /etc/dpkg-cross/cross-compile
@@ -334,6 +335,8 @@
 		push @removedeps, $pkg;
 	} elsif (/^(-A|--convert-anyway)$/) {
 		$anyway = 1;
+	} elsif (/^(-A|--convert-multiarch)$/) {
+		$multiarchconv = 1;
 	} else {
 		die sprintf (_g("%s: Unknown option %s.\n"), $progname, $_);
 	}
@@ -507,18 +510,24 @@
 	}
 	close(CONTROL);
 
-	if (defined ($control{'multi-arch'})) {
-		my $output = basename ($package);
-		warn sprintf(_g("%s: Skipping the '%s' Multi-Arch package.\n"), $progname, $output);
-		if (not -f $output) {
-			open(CP, "$package");
-			my @cp=<CP>;
-			close (CP);
-			open (CP, ">$output");
-			print CP @cp;
-			close (CP);
+        if (defined ($control{'multi-arch'})) {
+		if ($multiarchconv) {
+			# Carry on and process file anyway if --convert-multiarch given
+			warn sprintf(_g("%s: Multi-Arch package detected; processing anyway as --convert-mulitarch specified.\n"), $progname);
+			$multiarchpackage=1;
+		} else {
+			my $output = basename ($package);
+			warn sprintf(_g("%s: Skipping the '%s' Multi-Arch package.\n"), $progname, $output);
+			if (not -f $output) {
+				open(CP, "$package");
+				my @cp=<CP>;
+				close (CP);
+				open (CP, ">$output");
+				print CP @cp;
+				close (CP);
+			}
+			exit 0;
 		}
-		exit 0;
 	}
 	# check for existence of required fields
 	for $field (qw(package version architecture)) {
@@ -548,7 +557,7 @@
 	# prepare destination filename
 	my $evers = $control{"version"};
 	$evers =~ s/^\d+://;		 # strip epoch for filename
-    $debname = $control{"package"} . "-" . $arch . "-cross_" . $evers . "_all.deb";
+	$debname = $control{"package"} . "-" . $arch . "-cross_" . $evers . "_all.deb";
 
 	# now ready to start preparing destination package
 
@@ -602,6 +611,7 @@
 
 	# Helper: fix ldscript.
 	# Change any occurance of /lib, /usr/lib and /usr/X11R6/lib to $crosslib
+	# Uses global $multiarch regexp modifier
 	sub fix_ldscript {
 		my ($from, $to) = @_;
 		ensure_dir($to) or return 0;
@@ -617,7 +627,7 @@
 			return 0;
 		}
 		while (<FROM>) {
-			s:(^|[^-\w/])(/usr(/X11R6)?)?/lib:$1$crosslib:g;
+			s:(^|[^-\w/])(/usr)?/lib/$multiarch:$1$crosslib/:g;
 			print TO;
 		}
 		close(FROM);
@@ -713,6 +723,8 @@
 	$crosslib = $$config{'crosslib'};
 	$crosslib64 = $$config{'crosslib64'};
 	$crosslib32 = $$config{'crosslib32'};
+	# add extra regexp component for multiarch packages
+	if ($multiarchpackage) { $multiarch="\Q$crosstype/\E" } else {$multiarch=""};
 
 	# Now process regular files ...
 	open(PIPE, "find $src/ -type f -print |") or goto fail;
@@ -757,26 +769,26 @@
 			}
 			close(FROM);
 			close(TO);
-		} elsif (m:^/usr(/X11R6)?/include/:) {
-			# regular file under /usr/include or /usr/X11R6/include
+		} elsif (m:^/usr/include/($multiarch)?:) {
+			# regular file under /usr/include/ or /usr/include/<triplet>
 			link_file("$src$_", "$dst$crossinc/$'") or goto fail;
-		} elsif (m:^/usr/(lib/.*\.([hH]|[hH][hH]|[hH][pP][pP]))$:) {
+		} elsif (m:^/usr/(lib/$multiarch.*\.([hH]|[hH][hH]|[hH][pP][pP]))$:) {
 			# regular .h, .hh, or .hpp file under /usr/lib
 			link_file("$src$_", "$dst$crossdir/$1") or goto fail;
-		} elsif (m:^/usr(/X11R6)?/lib/([^/]+\.[ao])$:) {
-			# regular .a or .o file under /usr/lib or /usr/X11R6/lib
-			link_file("$src$_", "$dst$crosslib/$2") or goto fail;
-		} elsif (m:^/usr(/X11R6)?/lib64/([^/]+\.[ao])$:) {
-			# regular .a or .o file under /usr/lib64 or /usr/X11R6/lib64
-			link_file("$src$_", "$dst$crosslib64/$2") or goto fail;
-		} elsif (m:^/usr(/X11R6)?/lib32/([^/]+\.[ao])$:) {
-			# regular .a or .o file under /usr/lib32 or /usr/X11R6/lib32
-			link_file("$src$_", "$dst$crosslib32/$2") or goto fail;
+		} elsif (m:^/usr/lib/$multiarch([^/]+\.[ao])$:) {
+			# regular .a or .o file under /usr/lib
+			link_file("$src$_", "$dst$crosslib/$1") or goto fail;
+		} elsif (m:^/usr/lib64/([^/]+\.[ao])$:) {
+			# regular .a or .o file under /usr/lib64
+			link_file("$src$_", "$dst$crosslib64/$1") or goto fail;
+		} elsif (m:^/usr/lib32/([^/]+\.[ao])$:) {
+			# regular .a or .o file under /usr/lib32
+			link_file("$src$_", "$dst$crosslib32/$1") or goto fail;
 		} elsif ((m:^/emul/ia32-linux/usr/lib/([^/]+\.[ao])$:)) {
 			# regular .a or .o file under /emul/ia32-linux/ for #463588
 			link_file("$src$_", "$dst$crosslib32/$1") or goto fail;
-		} elsif (m:^(/usr(/X11R6)?)?/lib/([^/]+\.so[^/]*)$:) {
-			# regular .so* file under /lib, /usr/lib or /usr/X11R6/lib
+		} elsif (m:^(/usr)?/lib/($multiarch)?([^/]+\.so[^/]*)$:) {
+			# regular .so* file under /lib, /usr/lib, /lib/<triplet>, /usr/lib/<triplet>
 			if (is_ldscript("$src$_")) {
 				fix_ldscript("$src$_", "$dst$crosslib/$3") or goto fail;
 			} else {
@@ -789,19 +801,19 @@
 			} else {
 				next;
 			}
-		} elsif (m:^(/usr(/X11R6)?)?/lib64/([^/]+\.so[^/]*)$:) {
-			# regular .so* file under /lib64, /usr/lib64 or /usr/X11R6/lib64
+		} elsif (m:^(/usr)?/lib64/([^/]+\.so[^/]*)$:) {
+			# regular .so* file under /lib64, /usr/lib64
 			if (is_ldscript("$src$_")) {
-				fix_ldscript("$src$_", "$dst$crosslib64/$3") or goto fail;
+				fix_ldscript("$src$_", "$dst$crosslib64/$2") or goto fail;
 			} else {
-				link_file("$src$_", "$dst$crosslib64/$3") or goto fail;
+				link_file("$src$_", "$dst$crosslib64/$2") or goto fail;
 			}
-		} elsif (m:^(/usr(/X11R6)?)?/lib32/([^/]+\.so[^/]*)$:) {
-			# regular .so* file under /lib32, /usr/lib32 or /usr/X11R6/lib32
+		} elsif (m:^(/usr)?/lib32/([^/]+\.so[^/]*)$:) {
+			# regular .so* file under /lib32, /usr/lib32
 			if (is_ldscript("$src$_")) {
-				fix_ldscript("$src$_", "$dst$crosslib32/$3") or goto fail;
+				fix_ldscript("$src$_", "$dst$crosslib32/$2") or goto fail;
 			} else {
-				link_file("$src$_", "$dst$crosslib32/$3") or goto fail;
+				link_file("$src$_", "$dst$crosslib32/$2") or goto fail;
 			}
 		} elsif ((m:^/emul/ia32-linux/usr/lib/([^/]+\.so[^/]*)$:)) {
 			# regular .so* file under /emul/ia32-linux/usr/lib
@@ -810,19 +822,19 @@
 			} else {
 				link_file("$src$_", "$dst$crosslib32/$1") or goto fail;
 			}
-		} elsif (m:^/usr(/X11R6)?/lib/([^/]+\.la)$:) {
-			# regular .la file under /usr/lib or /usr/X11R6/lib
-			fix_la_file("$src$_", "$dst$crosslib/$2", $crosslib) or goto fail;
-		} elsif (m:^/usr(/X11R6)?/lib64/([^/]+\.la)$:) {
-			# regular .la file under /usr/lib64 or /usr/X11R6/lib64
-			fix_la_file("$src$_", "$dst$crosslib64/$2", $crosslib64) or goto fail;
-		} elsif (m:^/usr(/X11R6)?/lib32/([^/]+\.la)$:) {
-			# regular .la file under /usr/lib32 or /usr/X11R6/lib32
-			fix_la_file("$src$_", "$dst$crosslib32/$2", $crosslib32) or goto fail;
+		} elsif (m:^/usr/lib/$multiarch([^/]+\.la)$:) {
+			# regular .la file under /usr/lib
+			fix_la_file("$src$_", "$dst$crosslib/$1", $crosslib) or goto fail;
+		} elsif (m:^/usr/lib64/([^/]+\.la)$:) {
+			# regular .la file under /usr/lib64
+			fix_la_file("$src$_", "$dst$crosslib64/$1", $crosslib64) or goto fail;
+		} elsif (m:^/usr/lib32/([^/]+\.la)$:) {
+			# regular .la file under /usr/lib32
+			fix_la_file("$src$_", "$dst$crosslib32/$1", $crosslib32) or goto fail;
 		} elsif ((m:^/emul/ia32-linux/usr/lib/([^/]+\.la)$:)) {
 			# regular .la file under /emul-ia32-linux/usr/lib/
 			fix_la_file("$src$_", "$dst$crosslib32/$1", $crosslib32) or goto fail;
-		} elsif (m:/usr/lib/(pkgconfig/[^/]+.pc)$:) {
+		} elsif (m:/usr/lib/$multiarch(pkgconfig/[^/]+.pc)$:) {
 			# regular .pc file in /usr/lib/pkgconfig
 			fix_pc_file("$src$_", "$dst$crosslib/$1") or goto fail;
 			# not for lib64: I don't know if there is any rationale
@@ -876,7 +888,7 @@
 	while(<PIPE>) {
 		chomp;
 		s/^$src//;
-		# Ignore any symlinks not under /usr or /lib or /lib64
+		# Ignore any symlinks not under /usr or /lib or /lib64 (or /emul/ia32-linux)
 		m:^/(usr|lib|lib64|emul/ia32-linux): or next;
 		next if (m:^/usr/\w+-\w+(-\w+(-\w+)?)?/: && !$cross2cross);
 		# Find out (absolute) symlink destination
@@ -885,11 +897,12 @@
 			m:^(.*)/[^/]*$:;
 			$lv = "$1/$lv";
 		}
-		# Ignore any symlinks pointing outside /usr and /lib and /lib64
+		# Ignore any symlinks pointing outside /usr and /lib and /lib64 (or /emul/ia32-linux)
 		$lv =~ m:^/(usr|lib|lib64|emul/ia32-linux): or next;
 
+	        
 		# Calculate corresponding DESTINATION path
-		$lv = convert_path($lv);
+		$lv = convert_path($multiarch,$lv);
 
 		# Check if destination object exists.
 		# FIXME: this code is not correct for the case of symlink chains.
@@ -903,7 +916,7 @@
 		}
 
 		# Calculate corresponding SOURCE path
-		$_ = convert_path($_);
+		$_ = convert_path($multiarch,$_);
 
 		# Skip links that are going to point to themselves
 		# Example is /usr/include/X11 -> ../X11R6/include/X11:
@@ -1267,9 +1280,14 @@
 
 =head1 Multiarch behaviour
 
-C<dpkg-cross> now does nothing with packages from Debian which already
+By default <dpkg-cross> does nothing with packages from Debian which already
 support Multi-Arch - the package is simply copied to the current work
-directory, if it does not already exist.
+directory, if it does not already exist. Any package containing a Multi-Arch: 
+field in DEBIAN/control is skipped in this manner.
+
+--convert-multiarch can be specified to instead force the generation of a 
+-<arch>-cross package with the files moved into the conventional 
+dpkg-cross locations.
 
 The Multiarch spec ensures that multiarch packages will only be
 available from Debian mirrors once dpkg itself is capable of installing
@@ -1280,7 +1298,5 @@
 multiarch package itself handles the header files and pkg-config
 files.)
 
-Any package containing a Multi-Arch: field in DEBIAN/control is skipped
-in this manner.
 
 =cut
Index: Debian/DpkgCross.pm
===================================================================
RCS file: /cvsroot/dpkg-cross/dpkg-cross/Debian/DpkgCross.pm,v
retrieving revision 1.51
diff -u -r1.51 DpkgCross.pm
--- Debian/DpkgCross.pm	23 Feb 2011 14:46:35 -0000	1.51
+++ Debian/DpkgCross.pm	25 Mar 2011 15:37:06 -0000
@@ -437,29 +437,31 @@
 	return $dir;
 }
 
-=head1 convert_path($path)
+=head1 convert_path($multiarch, $path)
 
 Convert path, substituting '$crossinc', '$crosslib', '$crosslib64',
-'$crosslib32', '$crossdir'. This function will be used while building foreign
-binary packages or converting GCC options.
+'$crosslib32', '$crossdir', allowing for multiarch paths. This function will 
+be used while building foreign binary packages or converting GCC options.
 
- $1: Directory (and file) to convert.
+ $1: Multiarch sub-directory to strip
+ $2: Directory (and file) to convert.
 
 return: Converted path.
 
 =cut
 
 sub convert_path {
-	my $path = &simplify_path ($_[0]);
-	if ($path =~ /^\/usr(\/X11R6)?\/include\//) {
+	my $multiarch = $_[0];
+        my $path = &simplify_path ($_[1]);
+	if ($path =~ /^\/usr\/include\/($multiarch)?/) {
 		$path = "$crossinc/$'";
-	} elsif ($path =~ /^(\/usr(\/X11R6)?)?\/lib\//) {
+	} elsif ($path =~ /^(\/usr)?\/lib\/($multiarch)?/) {
 		$path = "$crosslib/$'";
-	} elsif ($path =~ /^(\/usr(\/X11R6)?)?\/lib64\//) {
+	} elsif ($path =~ /^(\/usr)?\/lib64\/($multiarch)?/) {
 		$path = "$crosslib64/$'";
-	} elsif ($path =~ /^(\/usr(\/X11R6)?)?\/lib32\//) {
+	} elsif ($path =~ /^(\/usr)?\/lib32\/($multiarch)?/) {
 		$path = "$crosslib32/$'";
-	} elsif ($path =~ m:^(/emul/ia32-linux/(usr/)?lib/):) {
+	} elsif ($path =~ m:^(/emul/ia32-linux/(usr/)?lib/($multiarch)?):) {
 		$path = "$crosslib32/$'";
 	} elsif ($path =~ /^\/usr\/\w+-\w+(-\w+(-\w+)?)?\//) {
 		# leave alone
Index: debian/changelog
===================================================================
RCS file: /cvsroot/dpkg-cross/dpkg-cross/debian/changelog,v
retrieving revision 1.213
diff -u -r1.213 changelog
--- debian/changelog	23 Feb 2011 14:46:36 -0000	1.213
+++ debian/changelog	25 Mar 2011 15:37:06 -0000
@@ -1,8 +1,14 @@
 dpkg-cross (2.6.3) unstable; urgency=low
 
+  [ Neil Williams ]
   * Drop old apt-cross multiarch behaviour - outdated.
 
- -- Neil Williams <codehelp@debian.org>  Wed, 23 Feb 2011 13:54:27 +0000
+  [ Wookey ]
+  * Add (interim) --convert-multiarch behaviour to cross even
+    multiarch packages (Closes: #619400)
+  * Drop X11R6 lib/include dirs as they are no longer present
+
+ -- Wookey <wookey@debian.org>  Fri, 25 Mar 2011 03:53:24 +0000
 
 dpkg-cross (2.6.2) unstable; urgency=low
 

Wookey
-- 
Principal hats:  Linaro, Emdebian, Wookware, Balloonboard, ARM
http://wookware.org/



Reply to: