[PATCH 7/7] Fix experimental multiarch support.

Jon Severinsson <[email protected]>
Newsgroups gmane.linux.debian.devel.embedded
Message-ID <[email protected]>
---
 examples/multiarch.conf |   31 ++++----
 multistrap              |  187 +++++++++++++++++++++++------------------------
 pod/multistrap          |   59 ++++++++++-----
 3 filer ändrade, 146 tillägg(+), 131 borttagningar(-)

diff --git a/examples/multiarch.conf b/examples/multiarch.conf
index dfa7fd50..a058a334 100644
--- a/examples/multiarch.conf
+++ b/examples/multiarch.conf
@@ -1,4 +1,4 @@
-# Example multistrap configuration file for the sid shortcut.
+# Example a multistrap configuration file for a multiarch chroot.
 
 [General]
 arch=
@@ -15,29 +15,26 @@ explicitsuite=false
 # extract all downloaded archives (default is true)
 unpack=true
 # enable MultiArch for the specified architectures
-multiarch=armel mipsel
+multiarch=amd64 i386 x32
 # the order of sections is not important.
 # the bootstrap option determines which repository
 # is used to calculate the list of Priority: required packages.
-bootstrap=Debian Foreign Test
-aptsources=Debian
+bootstrap=Debian DebianPorts
+aptsources=Debian DebianPorts
 
 [Debian]
+suite=sid
+multiarch=amd64 i386
 packages=apt
+packages=libc6:amd64 libgcc1:amd64
+packages=libc6:i386 libgcc1:i386
 source=http://cdn.debian.net/debian
 keyring=debian-archive-keyring
-suite=wheezy
-
-[Foreign]
-packages=libgcc1
-packages=libc6
-architecture=armel
-source=http://cdn.debian.net/debian
-keyring=debian-archive-keyring
-suite=wheezy
 
-[Test]
-packages=
-source=http://ftp.uk.debian.org/emdebian-multiarch/
-keyring=
+[DebianPorts]
 suite=sid
+arch=x32
+packages=libc6 libgcc1
+source=http://ftp.debian-ports.org/debian
+keyring=debian-ports-archive-keyring
+omitdebsrc=true
diff --git a/multistrap b/multistrap
index 6f81fd56..6c812235 100755
--- a/multistrap
+++ b/multistrap
@@ -36,7 +36,7 @@ use vars qw/ $progname $ourversion $dstrap $extra @aptsources
  $explicit_suite $allow_recommends %omitdebsrc @dsclist @sectoutput
  %flatfile %important $addimportant @debconf $hookdir %hooks
  $warn_count $use_shortcut @foreignarches $olddpkg $ignorenative
- %foreignpkgs $markauto $default_release /;
+ %arches %multiarches $markauto $default_release /;
 
 setlocale(LC_MESSAGES, "");
 textdomain("multistrap");
@@ -45,7 +45,6 @@ $ourversion = &our_version();
 $default_release = "*";
 $unpack = "true";
 %omitdebsrc=();
-%foreignpkgs=();
 while( @ARGV ) {
 	$_= shift( @ARGV );
 	last if m/^--$/;
@@ -200,23 +199,24 @@ if (not -d "${dir}etc/network") {
 if (not -d "${dir}dev") {
 	mkdir_fatal ("${dir}dev");
 }
-if (($olddpkg == 0) and (scalar (@foreignarches) > 0)) {
+if (scalar (@foreignarches) > 0) {
+	# Support old unoffical version
 	if (not -d "${dir}etc/dpkg/dpkg.cfg.d/") {
 		system_fatal ("mkdir -p ${dir}etc/dpkg/dpkg.cfg.d/");
 	}
-	if (not -f "${dir}etc/dpkg/dpkg.cfg.d/multiarch") {
-		open (MA, ">${dir}etc/dpkg/dpkg.cfg.d/multiarch");
-		foreach my $farch (@foreignarches) {
-			print MA "foreign-architecture $farch\n";
-		}
-		close (MA);
-		open (VMA, ">${dir}${dpkgdir}arch");
-		print VMA "$host\n";
-		foreach my $farch (@foreignarches) {
-			print VMA "$farch\n";
-		}
-		close (VMA);
+	open (MA, ">${dir}etc/dpkg/dpkg.cfg.d/multiarch");
+	foreach my $farch (@foreignarches) {
+		print MA "foreign-architecture $farch\n";
+	}
+	close (MA);
+
+	# Support new offical version
+	open (VMA, ">${dir}${dpkgdir}arch");
+	print VMA "$arch\n";
+	foreach my $farch (@foreignarches) {
+		print VMA "$farch\n";
 	}
+	close (VMA);
 }
 
 &guard_lib64($dir);
@@ -253,20 +253,12 @@ foreach my $aptsrc (@debootstrap) {
 			or die _g("Cannot open sources list"). $!;
 		my $mirror = $sources{$aptsrc};
 		my $suite = (exists $flatfile{$aptsrc}) ? "" : $suites{$aptsrc};
-		my $component = (exists $flatfile{$aptsrc}) ? ""
-			: (defined $components{$aptsrc}) ? $components{$aptsrc} : "main";
+		my $component = (exists $flatfile{$aptsrc}) ? "" : $components{$aptsrc};
+		my @arches=();
+		push @arches, $arches{$aptsrc};
+		push @arches, split(/ /, $multiarches{$aptsrc});
 		if (defined $mirror and defined $suite) {
-			if ($olddpkg != 0) {
-				print SOURCES "deb $mirror $suite $component\n";
-			} else {
-				if (scalar (@foreignarches) == 0) {
-					print SOURCES "deb [arch=$arch] $mirror $suite $component\n";
-				} else {
-					foreach my $farch (@foreignarches) {
-						print SOURCES "deb [arch=$farch] $mirror $suite $component\n";
-					}
-				}
-			}
+			print SOURCES "deb [arch=" . join(",", @arches) . "] $mirror $suite $component\n";
 			print SOURCES "deb-src $mirror $suite $component\n" if (not defined $omitdebsrc{$aptsrc});
 			close SOURCES;
 		}
@@ -331,26 +323,23 @@ if ((defined $k) and (not defined $noauth)) {
 }
 $config_str = '';
 $config_str .= " -o Apt::Architecture=$arch";
-$config_str .= " -o Dir::Etc::TrustedParts=${dir}${etcdir}trusted.gpg.d";
-$config_str .= " -o Dir::Etc::Trusted=${dir}${etcdir}trusted.gpg.d/trusted.gpg";
+$config_str .= " -o Dir=$dir";
+$config_str .= " -o Dir::Etc=${dir}${etcdir}";
+$config_str .= " -o Dir::State=${dir}${libdir}";
+$config_str .= " -o Dir::State::Status=${dir}${dpkgdir}status";
+$config_str .= " -o Dir::Cache=${dir}${cachedir}";
+$config_str .= " -o DPkg::options::=--root=${dir}";
 $config_str .= " -o Apt::Get::AllowUnauthenticated=true"
 	if (defined $noauth);
 $config_str .= " -o Apt::Get::Download-Only=true";
 $config_str .= " -o Apt::Install-Recommends=false"
 	if (not defined $allow_recommends);
-$config_str .= " -o Dir=$dir";
-$config_str .= " -o Dir::Etc=${dir}${etcdir}";
-$config_str .= " -o Dir::Etc::Parts=${dir}${etcdir}apt.conf.d/";
-$config_str .= " -o Dir::Etc::PreferencesParts=${dir}${etcdir}preferences.d/";
 $config_str .= " -o APT::Default-Release=$default_release";
 #	if (not defined $preffile);
 if (defined $deflist) {
 	$sourcesname = "sources.list.d/multistrap.sources.list";
 	$config_str .= " -o Dir::Etc::SourceList=${dir}${etcdir}$sourcesname";
 }
-$config_str .= " -o Dir::State=${dir}${libdir}";
-$config_str .= " -o Dir::State::Status=${dir}${dpkgdir}status";
-$config_str .= " -o Dir::Cache=${dir}${cachedir}";
 printf (_g("Getting package lists: apt-get %s update\n"), $config_str);
 $retval = system ("apt-get $config_str update");
 $retval >>= 8;
@@ -450,20 +439,12 @@ foreach my $aptsrc (@aptsources) {
 			or die _g("Cannot open sources list"). $!;
 		my $mirror = $sources{$aptsrc};
 		my $suite = (exists $flatfile{$aptsrc}) ? "" : $suites{$aptsrc};
-		my $component = (exists $flatfile{$aptsrc}) ? ""
-			: (defined $components{$aptsrc}) ? $components{$aptsrc} : "main";
+		my $component = (exists $flatfile{$aptsrc}) ? "" : $components{$aptsrc};
+		my @arches=();
+		push @arches, $arches{$aptsrc};
+		push @arches, split(/ /, $multiarches{$aptsrc});
 		if (defined $mirror and defined $suite) {
-			if ($olddpkg != 0) {
-				print SOURCES "deb $mirror $suite $component\n";
-			} else {
-				if (scalar (@foreignarches) == 0) {
-					print SOURCES "deb [arch=$arch] $mirror $suite $component\n";
-				} else {
-					foreach my $farch (@foreignarches) {
-						print SOURCES "deb [arch=$farch] $mirror $suite $component\n";
-					}
-				}
-			}
+			print SOURCES "deb [arch=" . join(",", @arches) . "] $mirror $suite $component\n";
 			print SOURCES "deb-src $mirror $suite $component\n" if (not defined $omitdebsrc{$aptsrc});
 			close SOURCES;
 		}
@@ -1142,8 +1123,8 @@ sub cascade {
 		$value = $key if (ref $key eq "HASH");
 		$keys{$type} = $value;
 	}
-	foreach $section (sort keys %keys) {
-		if ($section eq "general") {
+	my $section = "general";
+	{
 			$arch = $keys{$section}{'arch'}
 				if (defined $keys{$section}{'arch'} and (not defined $arch));
 			$dir = $keys{$section}{'directory'}
@@ -1212,10 +1193,8 @@ sub cascade {
 				}
 			}
 			my @ma=();
-			if ($olddpkg == 0) {
-				@ma = split(' ',lc($keys{$section}{'multiarch'}))
-					if (defined $keys{$section}{'multiarch'});
-				}
+			@ma = split(' ',lc($keys{$section}{'multiarch'}))
+				if (defined $keys{$section}{'multiarch'});
 			push @foreignarches, @ma;
 			my @d=();
 			@d = split(' ', lc($keys{$section}{'debootstrap'}))
@@ -1244,54 +1223,74 @@ sub cascade {
 				}
 			}
 			push @includes, @i;
-		} else {
+			if ($olddpkg != 0 && (scalar (@foreignarches) > 0)) {
+				my $dpkgmsg = _g("ERR: Unsupportable option: 'multiarch'. ".
+					"Current dpkg version does not support MultiArch. ");
+				warn $dpkgmsg;
+				die ("\n");
+			}
+	}
+	foreach $section (sort keys %keys) {
+		if ($section ne "general") {
 			$sources{$section}=$keys{$section}{'source'} if (not exists $source{$section});
 			# don't set suite or component if URL is of apt-ftparchive trailing-slash form
 			# regexp is: optional string in '[]', string without '[' or ']', string ending in '/'
 			$flatfile{$section}++ if (($sources{$section} =~ /^(\[.*\] )*[^\[\]]+ .+\/$/));
-			if ((exists $keys{$section}{'architecture'}) and
-				($keys{$section}{'architecture'} ne "")) {
-				my $frgn_arch = $keys{$section}{'architecture'};
+			$suites{$section}=$keys{$section}{'suite'}
+				if (not exists $suites{$section});
+			$components{$section}=$keys{$section}{'components'}
+				if (not exists $components{$section});
+			$components{$section}='main'
+				if (not defined $components{$section});
+			$arches{$section}=$keys{$section}{'arch'}
+				if (not exists $arches{$section});
+			$arches{$section}=$arch
+				if (not defined $arches{$section} or $arches{$section} eq "");
+			$multiarches{$section}=$keys{$section}{'multiarch'}
+				if (not exists $multiarches{$section});
+			$multiarches{$section}=""
+				if (not defined $multiarches{$section});
+			{
+				my @pkglist=();
 				my @tmp=();
 				if (ref ($keys{$section}{'packages'}) eq 'ARRAY') {
-					foreach my $p (@{$keys{$section}{'packages'}}) {
-						push @tmp, "$p:$frgn_arch";
-						push @req_arches, $frgn_arch;
-					}
+					push @pkglist, @{$keys{$section}{'packages'}};
 				} else {
-					foreach my $p (split(' ', $keys{$section}{'packages'})) {
-						push @tmp, "$p:$frgn_arch";
-						push @req_arches, $frgn_arch;
-					}
-				}
-				if ($olddpkg == 0) {
-					$packages{$section} = join(' ', @tmp);
-				} else {
-					my $dpkgmsg = sprintf (_g("ERR: Unsupportable option: 'architecture'. ".
-					"Current dpkg version does not support MultiArch. ".
-					"Packages for '%s' have been ignored.\n"), $section);
-					warn $dpkgmsg;
-					$warn_count++;
+					push @pkglist, $keys{$section}{'packages'};
 				}
-			} else {
-				if (ref ($keys{$section}{'packages'}) eq 'ARRAY') {
-					$packages{$section}=join(' ', @{$keys{$section}{'packages'}});
-				} else {
-					$packages{$section}=join(' ', $keys{$section}{'packages'});
+				my $pkgname;
+				my $pkgarch;
+				foreach my $p (@pkglist) {
+					if ($p =~ /^([^:]+):([^:]+)$/) {
+						($pkgname = $p) =~ s/^([^:]+):([^:]+)$/$1/;
+						($pkgarch = $p) =~ s/^([^:]+):([^:]+)$/$2/;
+					} else {
+						$pkgname = $p;
+						$pkgarch = $arches{$section};
+					}
+					if ($pkgarch eq $arch) {
+						push @tmp, "$pkgname";
+					} else {
+						push @tmp, "$pkgname:$pkgarch";
+						push @req_arches, $pkgarch;
+					}
 				}
+				$packages{$section} = join(' ', @tmp);
 			}
-			$suites{$section}=$keys{$section}{'suite'}
-				if (not exists $suites{$section} and not exists $flatfile{$section});
-			$components{$section}=$keys{$section}{'components'}
-				if (not exists $components{$section} and not exists $flatfile{$section});
-			$omitdebsrc{$section}=$section if ((defined $keys{$section}{'omitdebsrc'})
-				and ($keys{$section}{'omitdebsrc'} eq "true"));
 			push @reinstall, split (/ /, lc($keys{$section}{'reinstall'}))
 				if (defined $keys{$section}{'reinstall'});
-			$components{$section}='main' if (not defined $components{$section});
-			$keyrings{$section}=$keys{$section}{'keyring'} if (not exists $keyrings{$section});
 			push @extrapkgs, split (' ', lc($keys{$section}{'additional'}))
 				if (defined $keys{$section}{'additional'});
+			$omitdebsrc{$section}=$section
+				if ((defined $keys{$section}{'omitdebsrc'}) and ($keys{$section}{'omitdebsrc'} eq "true"));
+			$keyrings{$section}=$keys{$section}{'keyring'}
+				if (not exists $keyrings{$section});
+			if ($olddpkg != 0 && $multiarches{$section} ne "") {
+				my $dpkgmsg = sprintf (_g("ERR: Unsupportable option: 'multiarch'. ".
+				"Current dpkg version does not support MultiArch. "));
+				warn $dpkgmsg;
+				die ("\n");
+			}
 		}
 	}
 	my %archchk=();
@@ -1301,9 +1300,9 @@ sub cascade {
 	foreach my $req (@req_arches) {
 		if (not exists $archchk{$req}) {
 			# Translators: %1 and %2 are the same value here - the erroneous architecture name
-			my $reqmsg = sprintf (_g("ERR: Misconfiguration in: 'architecture' option. ".
-			"Packages of architecture=%s requested but '%s' is not included in the multiarch=".
-			join (" ", @foreignarches) . " option.\n"), $req, $req);
+			my $reqmsg = sprintf(_g("ERR: Misconfiguration in: 'architecture' option. ".
+				"Packages of architecture=%s requested but '%s' is not included in the multiarch=".
+				join (" ", @foreignarches) . " option.\n"), $req, $req);
 			warn $reqmsg;
 			die ("\n");
 		}
@@ -1314,7 +1313,7 @@ sub cascade {
 
 # returns zero on success, non-zero on fail
 sub check_multiarch_dpkg {
-	my $retval = system ("dpkg --print-foreign-architectures > /dev/null 2>&1");
+	my $retval = system ("dpkg --assert-multi-arch >/dev/null 2>&1");
 	$retval >>=8;
 	return $retval;
 }
diff --git a/pod/multistrap b/pod/multistrap
index b511fa51..59b3a725 100644
--- a/pod/multistrap
+++ b/pod/multistrap
@@ -823,45 +823,64 @@ people on the [email protected] mailing list and
 does not parse correctly. You would need to put the C<--simulate> output
 on a pastebin website and put the URL in your message.
 
-=head1 MultiArch support
+=head1 Multiarch Support
 
 Multiarch support is experimental - please report issues and file bugs
 with full details of your setup, the full multistrap config file and
 the errors reported.
 
-C<multistrap> overrides the existing multiarch support of the external
-system so that a MultiArch aware system can still create a non-MultiArch
-chroot from repositories which do not support all of the architectures
-supported by the external dpkg.
+Multiarch support in C<multistrap> depends on a multiarch-capable dpkg
+in the external system, but it does not require multiarch to be enabled
+on it. You can create a multiarch C<multistrap> configuration on a
+non-multiarch system, or a non-multiarch C<multistrap> configuration on
+a multiarch system.
 
-If multiarch is enabled within the multistrap chroot, C<multistrap>
-writes out the list into F</var/lib/dpkg/arch> inside the chroot.
+For multiple foreign architectures, specify the option once and use a
+space separated list of architectures. You do not need to add the base
+architecture to the multiarch list.
 
-For multiple architectures, specify the option once and use a space
-separated list for the architecture list. Ensure you include what will
-be the host architecture of the chroot.
+Note that the C<multiarch> option in the [General] section only enables
+multiarch in dpkg, not in apt. For that you need to either provide a
+separate Section for each architecture, or add the C<multiarch> option
+to the repository Section as well.
 
-See also http://wiki.debian.org/Multiarch/
+The C<packages> option supports arch-qualified package names.
+Unqualified package names will be installed for the architecture
+specified in the C<arch> option of the Section, or for the base
+architecture if none is specified.
+
+The following example configuration would install the base system for
+C<amd64>; zlib1g for C<amd64> and C<sparc64>; and liblzma5 for
+C<sparc> and C<sparc64>.
 
  [General]
  ...
- multiarch=i386 armel armhf
-
-Each Section will install packages from the base architecture unless
-the C<Architecture> option is specified for particular sections.
+ arch=amd64
+ multiarch=sparc sparc64
 
- [Foreign]
- packages=libgcc1 libc6
- architecture=armel
+ [Debian]
+ suite=sid
+ multiarch=sparc
+ packages=zlib1g liblzma5:sparc
  source=http://ftp.uk.debian.org/debian
  keyring=debian-archive-keyring
+
+ [DebianPorts]
  suite=sid
+ architecture=sparc64
+ packages=zlib1g liblzma5
+ source=http://ftp.debian-ports.org/debian
+ keyring=debian-ports-archive-keyring
+ omitdebsrc=true
 
 In the C<--simulate> output, the architecture(s) specified in the
 MultiArch option will be listed under the "Foreign architectures"
-listing. Packages for a specific architecture will be listed as the
-package name followed by a colon followed by the architecture.
+listing. Packages for a foreign architecture will be listed as
+a architecture-qualified package name, eg the base package name
+followed by a colon followed by the architecture.
 
  libgcc1:armel libc6:armel
 
+See also http://wiki.debian.org/Multiarch/
+
 =cut
-- 
1.7.10.4


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]
Archive: http://lists.debian.org/[email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.