Zmiana wartości zmiennej CHOST

Wernfried Haas  Autor
Mike Frysinger  Redaktor
Chris White  Redaktor
Jakub Hudak  Tłumaczenie

Zaktualizowano 29 lipca 2007

1.  Wstęp

Zmiana wartości zmiennej CHOST może być problemem, który poważnie może uszkodzić system. Zatem dlaczego jest do tego w ogóle przewodnik?

Istnieje sporo przypadków, kiedy zmiana wartości zmiennej CHOST jest nieunikniona, np. jeśli chce się zaktualizować glibc 2.4, które wspiera tylko nptl, a zmienna CHOST to i386, co uniemożliwia wykorzystanie nptl. W takim wypadku nie ma zbyt dużej liczby rozwiązań problemu. Zmiana wartości zmiennej CHOST jest jedną z nich.

Nawet jeśli wykona się poniższe instrukcje, mogą powstać problemy, dlatego trzeba być podczas całego procesu bardzo uważnym. W tym przykładzie zmienna CHOST będzie zmieniania z i386 na i686. Aby dokonać zmiany z innych wartości zmiennej CHOST, należy zmienić odpowiednio komendy.

2.  Zmiana wartości zmiennej CHOST

Instalowanie pakietów

Aby zmienić wartość zmiennej CHOST, otwieramy plik /etc/make.conf i zmieniamy wartość CHOST na taką, jakiej potrzebujemy. Potem należy przebudować następujące pakiety:

Listing 2.1: Przebudowanie ważnych narzędzi systemowych

# emerge -av1 binutils gcc glibc

Ważne: Aktualizacja gcc i zmiana wartości zmiennej CHOST w tym samym czasie (np. wersja gcc 3.3, wartość zmiennej CHOST i386 zmieniane na gcc w wersji 4.1 i wartość zmiennej CHOST na i686) mogą powodować szereg problemów dodatkowych. Może się okazać niemożliwe wykonanie tej zmiany. Dlatego ostrzegamy, należy wykonywać tylko jedną czynność naraz, np. zaktualizować najpierw gcc (korzystając z podręcznika aktualizacji gcc) a następnie zmienić wartość zmiennej CHOST. Jeśli wartość zmiennej CHOST to i386, trzeba zamaskować pakiet glibc w wersji 2.4 (lub nowszej) podczas aktualizacji gcc, tak by nie mógł on być użyty z i386. Po skończonej aktualizacji odmaskowujemy go.

Sprawdzenie wprowadzonych zmian

Teraz sprawdzimy czy ustawienia gcc-config i binutils-config są w porządku i czy nie ma żadnych pozostałości w /etc/env.d/.

Wynik poleceń gcc-config i binutils-config powinien wyglądać mniej więcej tak jak poniżej (mogą się nieznacznie różnić z zależności od wersji gcc i wartości CHOST). My podajemy przykłady dla wersji 4.1.1 i 2.16.1.

Listing 2.2: Sprawdzenie poprawności ustawień

# gcc-config -l
 [1] i686-pc-linux-gnu-4.1.1 *
# gcc-config -c
i686-pc-linux-gnu-4.1.1

# binutils-config -l
 [1] i686-pc-linux-gnu-2.16.1 *
# binutils-config -c
i686-pc-linux-gnu-2.16.1

Następnie wyszukujemy odwołania do starej wartości zmiennej CHOST w katalogu /etc/env.d/:

Listing 2.3: Sprawdzenie odwołań do starej wartości zmiennej CHOST

# cd /etc/env.d/
# grep 386 *
05gcc-i386-pc-linux-gnu:PATH="/usr/i386-pc-linux-gnu/gcc-bin/4.1.1"
05gcc-i386-pc-linux-gnu:ROOTPATH="/usr/i386-pc-linux-gnu/gcc-bin/4.1.1"

Uwaga: Może się to nie zdarzyć każdemu, ale akurat w tym wypadku plik 05gcc-i386-pc-linux-gnu zawiera odwołanie do starej wartości zmiennej CHOST. Ustawienia w systemie, które odwołują się do wartości zmiennej CHOST mogą się różnić od przykładu albo być w porządku. Nazwa powinna wyglądać tak: 05gcc-nowa_wartość_CHOST-pc-linux-gnu.

Przed skasowaniem tego pliku należy sprawdzić pliki ze zaktualizowaną wartością zmiennej CHOST:

Listing 2.4: Sprawdzenie plików ze zaktualizowaną wartością zmiennej CHOST

# grep 686 *
05binutils:MANPATH=/usr/share/binutils-data/i686-pc-linux-gnu/2.16.1/man
05binutils:INFOPATH=/usr/share/binutils-data/i686-pc-linux-gnu/2.16.1/info
05binutils:LDPATH=/usr/i686-pc-linux-gnu/lib
05gcc:PATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
05gcc:ROOTPATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
05gcc:MANPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/man"
05gcc:INFOPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/info"
05gcc:LDPATH="/usr/lib/gcc/i686-pc-linux-gnu/4.1.1"

Ten plik wygląda dobrze. Jest tylko jeden problem. Powinien być tylko jeden plik dla gcc w katalogu /etc/env.d/ (05gcc w tym przykładzie), więc kasujemy ten drugi z niepoprawnym odwołaniem:

Listing 2.5: Usuwanie plików z niepoprawnymi odwołaniami

# rm 05gcc-i386-pc-linux-gnu

To same kroki należy wykonać dla binutils. Jeśli jest jakiś dodatkowy niepasujący do wersji zmiennej CHOST plik, należy go usunąć. Następnie sprawdzamy katalog /etc/env.d/binutils/

Listing 2.6: Sprawdzenie zawartości katalogu binutils

# cd /etc/env.d/binutils/
# ls -la
total 8
-rw-r--r-- 1 root root  15 Sep  3 13:48 config-i686-pc-linux-gnu
-rw-r--r-- 1 root root 126 Sep  3 13:48 i686-pc-linux-gnu-2.16.1

# cat config-i686-pc-linux-gnu
CURRENT=2.16.1
# cat i686-pc-linux-gnu-2.16.1
TARGET="i686-pc-linux-gnu"
VER="2.16.1"
LIBPATH="/usr/lib/binutils/i686-pc-linux-gnu/2.16.1"
FAKE_TARGETS="i686-pc-linux-gnu"

Ten katalog wygląda dobrze, te dwa pliki powinny w nim zostać. Teraz czas na przejście do katalogu gcc.

Listing 2.7: Sprawdzenie zawartości katalogu gcc

# cd /etc/env.d/gcc
# ls -la
total 12
-rw-r--r-- 1 root root  32 Sep  3 16:43 config
-rw-r--r-- 1 root root  32 Aug  3 14:25 config-i386-pc-linux-gnu
-rw-r--r-- 1 root root 292 Sep  3 16:43 i686-pc-linux-gnu-4.1.1

# cat config
CURRENT=i686-pc-linux-gnu-4.1.1

# cat config-i386-pc-linux-gnu
CURRENT=i386-pc-linux-gnu-4.1.1

# cat i686-pc-linux-gnu-4.1.1
PATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
ROOTPATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1"
LDPATH="/usr/lib/gcc/i686-pc-linux-gnu/4.1.1"
GCCBITS="32"
MANPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/man"
INFOPATH="/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/info"
STDCXX_INCDIR="g++-v4"

Pliki config i i686-pc-linux-gnu-4.1.1 wyglądają w porządku, ale plik config-i386-pc-linux-gnu jest kolejną pozostałością do usunięcia.

Uwaga: Ponownie nazwa pliku zawiera odwołanie do nieistniejącej wersji gcc, np. config-i686-pc-linux-gnu, nawet jeśli zmieniono wartość na i686. Jest ważne, aby sprawdzać pliki po ich zawartości, a nie tylko po nazwie.

Listing 2.8: Usuwanie niepoprawnego pliku konfiguracyjnego dla gcc

# rm config-i386-pc-linux-gnu

Następnie wykonujemy poniższe komendy, aby zaktualizować środowisko:

Listing 2.9: Aktualizacja środowiska

# env-update && source /etc/profile

Następnie sprawdzamy czy wszystko jest w porządku:

Listing 2.10: Sprawdzenie odwołań do starej wartości zmiennej CHOST

# grep -r 386 /etc/env.d/

Jeśli ciągle istnieją niepoprawne odwołania, najprawdopodobniej pominięto jakiś plik. Trzeba znaleźć go ręcznie przed przejściem dalej.

Kończenie zmian

Następnie koniecznie należy przekompilować pakiet libtool i wykonać polecenie /usr/share/gcc-data/$CHOST/<gcc-version>/fix_libtool_files.sh. Należy upewnić się, że używa się odpowiedniej wersji gcc. Zmienną $CHOST zastępujemy nową wartością CHOST, a <gcc-version> nową wersją gcc. W przykładzie tym przyjęto i686 jako wartość CHOST.

Listing 2.11: Zapewnienie poprawności biblioteki

# emerge -av1 libtool
# /usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/fix_libtool_files.sh 4.1.1 --oldarch i386-pc-linux-gnu

Teraz jest dobra okazja by przebudować cały system:

Listing 2.12: Przebudowa world

# emerge -e world

Przebudowa systemu jest wskazana, ale nie konieczna, poza tym nie ma 100% pewności, że to ten przypadek. Jeśli nie przebudowano całego systemu na pewno pewne pakiety wymagają rekompilacji. Zaczynamy od:

Listing 2.13: Rekompilacja pythona

# emerge -av1 python

Pakiety związane z perlem instalują się do katalogu, który ma zmienną CHOST w nazwie. W związku z tym należy je teraz wszystkie przebudować. Jeśli w systemie nie ma jeszcze programu qfile, trzeba będzie najpierw zainstalować pakiet app-portage/portage-utils.

Listing 2.14: Ponowna instalacja pakietów perla

# emerge -av portage-utils
# emerge -av1 `qfile /usr/lib/perl* -Cq | sort -u`

Jeśli jakiś pakiet nie wymieniony w tym dokumencie wymaga przebudowy po zmianie CHOST, należy o tym poinformować autora tego dokumentu.

Częste problemy

Po aktualizacji gcc z wersji 3.3 do 4.1 z równoczesną zmianą zmiennej CHOST (nie jest to wskazane), kilku użytkowników zgłosiło, że pakiety takie jak groff i courier wymagają rekompilacji:

Listing 2.15: Błąd

error while loading shared libraries: libstdc++.so.5: cannot open shared object
file: No such file or directory

Dzieje się tak, ponieważ po aktualizacji zmienna CHOST nie pasuje do zmiennej CTARGET i kompilator wybiera kompilację skrośną (ang. cross-compiling). W konsekwencji zmienna LDPATH nie zostaje załadowana do ld.so.conf, powodując ten błąd.

Aby dowiedzieć się, co trzeba zrobić po przejściu na inną wersję gcc, należy przeczytać tekst o aktualizacji gcc.

W rzadkich przypadkach może to również spowodować popsucie starych wersji pythona. Może to zostać naprawione poprzez dodanie /usr/lib/gcc-lib/i386-pc-linux-gnu/3.3.6 (należy odpowiednio zmienić wartość chost i wersję gcc na używane poprzednio) w /etc/ld.so.conf, wykonać polecenie ldconfig i dopiero wtedy emerge libstdc++-v3. Jednak jak widać powinno się unikać tego problemu - stąd wniosek: nie powinno się zmieniać wartości zmiennej CHOST z jednoczesną aktualizacją gcc.

Kontakt

Wszelkie komentarze na temat tego tekstu (zarówno pozytywne jak i konstruktywną krytykę) należy przesyłać na adres Wernfried Haas lub publikować w tym wątku na forum. Sporą część tego tekstu napisał vapier, dziękujemy!