poniedziałek, 30 maja 2016

HARDCORE - Kompilacja programu pod własny procesor, cz. 1 - qmake

Kompilując program w Arch Linux makepkg wykorzystuje ustawienia w pliku /etc/makepkg.conf. Tam można m.in. wymusić kompilację uwzględniającą określony rodzaj procesora. Innymi słowy, program skompilowany na danej maszynie winien - przynajmniej w teorii - być do niej bardziej dostosowany. Ma to swoje oczywiste konsekwencje. Program tak zbudowany może nie działać na innym komputerze, który ma inny - choćby nieco - procesor. Także po wymianie procesora możemy zostać niemiło zaskoczeni. Niektóre programy nie lubią też takiej, "wymuszonej" kompilacji.
Ustawienia w /etc/makepkg.conf są jednakże ignorowane, gdy program jest prekompilowany z użyciem qmake, bądź cmake. Nie oznacza to, że nie można w tych przypadkach skompilować go z użyciem odpowiednich flag.
W pierwszej części napiszę jak to zrobić dla qmake.
Po pierwsze musimy mieć skrypty umożliwiające budowę paczki dla Archa. Możemy je stworzyć we własnym zakresie, możemy - jeśli program ma zostać przerobiony z dostępnych w repozytoriach, bądź AUR skryptów - skopiować je do dowolnego katalogu. W tym drugim przypadku, używam:
yaourt -G nazwa_programu
albowiem jest mi najwygodniej.
Przechodzimy do katalogu, w którym mamy skrypty i edytujemy PKGBUILD. Bardzo ogólnie ujmując, składa się on z dwu części:

  • pierwszej, w której wprowadzane są pewne deklaracje dla makepkg, gdzie znajdziemy m.in. informacje o tym, skąd skrypt ma pobrać źródła i
  • drugiej, w której umieszczane są instrukcje służące budowie paczki.

Tę drugą dość łatwo rozpoznać, albowiem po jakiś słowie nastąpi seria znaków: "() {". Np.  build() {.
W pierwszej części, np. na jej końcu umieszczamy zatem deklaracje dla kompilatora, które poinformują go o tym, pod jaki procesor chcemy zbudować paczkę. Dodajemy tam dwa wpisy:
CFLAGS="-march=FLAGA1 -mtune=FLAGA2"
CXXFLAGS="-march=FLAGA1 -mtune=FLAGA2"
Oczywiście możemy jeszcze precyzyjniej wskazać jakich opcji ma użyć kompilator.
W miejscu FLAGA1, FLAGA2, wpisujemy flagi właściwe dla naszego procesora, jeśli ich nie znamy, to wskaże je nam polecenie:
gcc -march=native -E -v - </dev/null 2>&1 | sed -n 's/.* -v - //p'
Możemy również pójść na pewne skróty, albowiem gcc od wersji 4.2 wprowadził flagę "native". Kompilator sam winien rozpoznać właściwe ustawienia dla naszego procesora i ich użyć. Wówczas powyższe deklaracje przyjmą postać:
CFLAGS="-march=native"
CXXGLAGS="-march=native"
Teraz odszukujemy sekcję rozpoczynającą się od: "build() {". Będzie w niej linia rozpoczynająca się od qmake (lub qmake-qt5) dla aplikacji budowanych z użyciem Qt5 lub qmake-qt4, dla zanikającego już, ale nadal obecnego Qt4. Tutaj, w poleceniach przekazywanych qmake musimy dodać:
CONFIG+=LINUX_INTEGRATED \
        QMAKE_CFLAGS_RELEASE="${CFLAGS}" \
        QMAKE_CXXFLAGS_RELEASE="${CXXFLAGS}" 
Sekcja ta może przyjąć zatem następujący wygląd:
build() {
cd build 
qmake PREFIX=/usr \
CONFIG+=LINUX_INTEGRATED \
         QMAKE_CFLAGS_RELEASE="${CFLAGS}" \
QMAKE_CXXFLAGS_RELEASE="${CXXFLAGS}" 
make
}
W zasadzie powinno wystarczyć. Wydajemy teraz polecenie:
makepkg -s
(ewentualnie z innymi opcjami) i mamy nadzieję, że tak skompilowany program będzie działał na naszym komputerze lepiej od skompilowanego z użyciem flag generic i jedynie zadeklarowaniem 32 bądź 64 bitowego procesora.
Pozostaje jeszcze to sprawdzić (namcap) i zainstalować wykorzystując
pacman -U nazwa_paczki