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

[PATCH 7/7] Fix experimental multiarch support.



---
 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 debian-embedded@lists.debian.org 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


Reply to: