Vraag Leren dingen uit de bron compileren (op Unix / Linux / OSX)


Hoewel ik waar mogelijk software van pakketten (MacPorts / apt-get) installeer, moet ik vaak pakketten uit de bron compileren. ./configure && make && sudo make install is meestal voldoende, maar soms werkt het niet - en als het dat niet doet, loop ik vaak vast. Dit heeft op de een of andere manier bijna altijd te maken met andere bibliotheekafhankelijkheden.

Ik zou graag het volgende willen leren:

  • Hoe weet ik welke argumenten moeten worden doorgegeven ./configure?
  • Hoe gedeelde bibliotheken werken onder OS X / Linux - waar ze op het bestandssysteem wonen, hoe ./configure && make vindt ze, wat er feitelijk gebeurt wanneer ze worden gekoppeld
  • Wat zijn de werkelijke verschillen tussen een gedeelde en een statisch gekoppelde bibliotheek? Waarom kan ik niet gewoon alles statisch koppelen (RAM- en schijfruimte zijn tegenwoordig goedkoop) en daarom vreemde conflicten met bibliotheekversies vermijden?
  • Hoe kan ik zien welke bibliotheken ik heb geïnstalleerd en welke versies?
  • Hoe kan ik meer dan één versie van een bibliotheek installeren zonder mijn normale systeem te onderbreken?
  • Als ik ben dingen uit de bron installeren op een systeem dat anders beheerd wordt met pakketten, wat is de schoonste manier om dit te doen?
  • Ervan uitgaande dat ik erin slaag om iets onhandigs van de bron te compileren, hoe kan ik dat dan verpakken zodat andere mensen niet door dezelfde hoepels hoeven te springen? Vooral op OS X ....
  • Wat zijn de commandoregelhulpmiddelen die ik moet beheersen om goed te worden in dit spul? Dingen zoals otool, pkg-config etc.

Ik ben bereid hier nogal wat tijd en moeite in te investeren - ik wil niet noodzakelijkerwijs directe antwoorden op de bovenstaande vragen, ik zou veel liever aanbevelingen krijgen over boeken / tutorials / veelgestelde vragen die ik kan lezen en die me de kennis die ik nodig heb om te begrijpen wat er werkelijk aan de hand is en daarmee problemen zelf uit te zoeken.


45
2017-07-27 08:48


oorsprong




antwoorden:


Mijn excuses voor het rechtstreeks beantwoorden van alles, maar ik ken geen handige tutorials, veelgestelde vragen, enz. Wat volgt, is in feite 8 jaar bezig met het maken van desktop-apps (die ik help distribueren), frustratie en googlen:

1. Hoe weet ik welke argumenten moeten worden doorgegeven aan ./configure?

Oefen echt. Autotools is eenvoudig genoeg omdat het consistent is. Maar er zijn genoeg dingen die er zijn met behulp van cmake, of aangepaste build-scripts. Over het algemeen zou je niets moeten doorgeven om te configureren, het zou moeten uitzoeken of jouw systeem foo-tool kan bouwen of niet.

Configure en GNU-tools zien allemaal in /, / usr en / usr / local voor afhankelijkheden. Als u ergens anders iets installeert (wat het pijnlijk maakt als de afhankelijkheid door MacPorts of Fink is geïnstalleerd), moet u een vlag doorgeven om de shell-omgeving te configureren of aan te passen om GNU-tools te helpen deze afhankelijkheden te vinden.

2. Hoe gedeelde bibliotheken werken onder OS X / Linux - waar ze op het bestandssysteem wonen, hoe ./configure && make find ze vinden, wat er feitelijk gebeurt wanneer ze worden gekoppeld aan

Op Linux moeten ze worden geïnstalleerd op een pad dat de dynamische linker kan vinden, dit wordt gedefinieerd door de LD_LIBRARY_PATHomgevingsvariabele en de inhoud van /etc/ld.conf. Op Mac is dit vrijwel altijd hetzelfde voor de meeste opensourcesoftware (tenzij het een Xcode-project is). Behalve de env-variabele is DYLD_LIBRARY_PATH in plaats daarvan.

Er is een standaardpad dat de linker zoekt naar bibliotheken. Het is / lib: / usr / lib: / usr / local / lib

U kunt dit aanvullen door de CPATH-variabele of CFLAGS of een willekeurig aantal andere omgevingsvariabelen echt te gebruiken (gemakkelijk gecompliceerd). Ik stel CFLAGS als volgt voor:

CFLAGS exporteren = "$ CFLAGS -L / nieuw / pad"

De parameter -L voegt toe aan het koppelingspad.

Moderne dingen maken gebruik van de pkg-config-tool. Moderne dingen die u installeert, installeren ook een .pc-bestand dat de bibliotheek beschrijft en waar het zich bevindt en hoe u ernaar kunt linken. Dit kan het leven gemakkelijker maken. Maar het komt niet met OS X 10.5 dus je zult dat ook moeten installeren. Ook ondersteunen veel basisdeps dit niet.

De handeling van linken is gewoon "deze functie oplossen tijdens runtime", het is echt een grote stringtabel.

3. Wat zijn de werkelijke verschillen tussen een gedeelde en een statisch gekoppelde bibliotheek? Waarom kan ik niet gewoon alles statisch koppelen (RAM- en schijfruimte zijn tegenwoordig goedkoop) en daarom vreemde conflicten met bibliotheekversies vermijden?

Wanneer u een koppeling maakt naar een statisch bibliotheekbestand, wordt de code onderdeel van uw toepassing. Het zou lijken alsof er één gigantisch .c-bestand voor die bibliotheek was en u het in uw toepassing hebt gecompileerd.

Dynamische bibliotheken hebben dezelfde code, maar wanneer de app wordt uitgevoerd, wordt de code tijdens runtime in de app geladen (vereenvoudigde uitleg).

Je kunt statisch naar alles linken, maar helaas maken nauwelijks build-systemen dit gemakkelijk. Je zou build systeembestanden handmatig moeten bewerken (bijv. Makefile.am, of CMakeLists.txt). Dit is echter waarschijnlijk de moeite waard om te leren als je regelmatig dingen installeert die verschillende versies van bibliotheken vereisen en je vindt afhankelijke installatie-afhankelijkheden moeilijk.

De truc is om de verbindingslijn van -lfoo naar -l / path / to / static / foo.a te wijzigen

U kunt waarschijnlijk vinden en vervangen. Controleer daarna of de tool geen link heeft naar de .so of dylib met ldd foo of otool -L foo

Een ander probleem is dat niet alle bibliotheken compileren naar statische bibliotheken. Velen doen. Maar dan hebben MacPorts of Debian misschien besloten om het niet te verzenden.

4. Hoe kan ik zien welke bibliotheken ik heb geïnstalleerd en welke versies?

Als u pkg-config-bestanden voor die bibliotheken heeft, is dit eenvoudig:

pkg-config --list-all

Anders kan je het vaak niet gemakkelijk. De dylib kan een sonaam hebben (bijv. Foo.0.1.dylib, de soname is 0.1) die hetzelfde is als de versie van de bibliotheek. Dit is echter niet verplicht. De soname is een binaire berekenbaarheidsfunctie, je moet het grootste deel van de soname tegenhouden als je het formaat van de functies in de bibliotheek verandert. Je kunt dus bijvoorbeeld krijgen. versie 14.0.5 soname voor een 2.0-bibliotheek. Hoewel dit niet gebruikelijk is.

Ik raakte gefrustreerd door dit soort dingen en heb hiervoor een oplossing op Mac ontwikkeld, en ik heb het er daarna over.

5. Hoe kan ik meer dan één versie van een bibliotheek installeren zonder mijn normale systeem te onderbreken?

Mijn oplossing hiervoor is hier: http://github.com/mxcl/homebrew/

Ik vind het leuk om vanaf de bron te installeren en wilde een tool die het gemakkelijk maakte, maar met een beetje pakketbeheer. Dus met Homebrew bouw ik, bijvoorbeeld. wget mezelf van de bron, maar zorg ervoor dat u installeert op een speciaal voorvoegsel:

/usr/local/Cellar/wget/1.1.4

Vervolgens gebruik ik de homebrew-tool om dat allemaal te symboliseren in / usr / local, dus ik heb nog steeds / usr / local / bin / wget en /usr/local/lib/libwget.dylib

Later als ik een andere versie van wget nodig heb, kan ik deze parallel installeren en alleen de versie wijzigen die is gekoppeld aan de / usr / local tree.

6. Als ik dingen van de bron installeer op een systeem dat anders wordt beheerd met behulp van pakketten, wat is dan de schoonste manier om dit te doen?

Ik geloof dat de Homebrew manier het schoonst is, dus gebruik het of doe het equivalent. Installeer in / usr / local / pkgs / name / version en symlink of hardlink de rest erin.

Gebruik / usr / local. Elke build-tool die bestaat, zoekt naar afhankelijkheden en headers. Je leven zal zijn veel gemakkelijker.

7. Aangenomen dat ik erin slaag om iets onhandigs van de bron te compileren, hoe kan ik dat dan verpakken zodat andere mensen niet door dezelfde hoepels hoeven te springen? Vooral op OS X ....

Als er geen afhankelijkheden zijn, kunt u de builddirectory taraniseren en aan iemand anders geven die vervolgens "make install" kan doen. Je kunt dit echter alleen betrouwbaar doen voor exact dezelfde versies van OS X. Op Linux zal het waarschijnlijk werken voor vergelijkbare Linux (bijvoorbeeld Ubuntu) met dezelfde Kernel-versie en libc-minorversie.

De reden dat het niet eenvoudig is binaries te distribueren op Unix is ​​vanwege binaire compatibiliteit. De GNU-mensen en de anderen veranderen hun binaire interfaces vaak.

Verdelers in principe niet distribueren. Dingen zullen waarschijnlijk op heel vreemde manieren breken.

Op Mac is de beste optie om een ​​macports-pakket te maken. Iedereen gebruikt macports. Op Linux zijn er zoveel verschillende build-systemen en combinaties, ik denk niet dat er een beter advies is dan een blog-entry te schrijven over hoe je erin slaagde om x tool te bouwen in een vreemde configuratie.

Als u een pakketbeschrijving maakt (voor macports of homebrew), kan iedereen dat pakket installeren en lost het ook de afhankelijkheidsproblemen op. Dit is echter vaak niet gemakkelijk en het is ook niet eenvoudig om je macports-recept in de macabloomstamboom te laten opnemen. Ook macports ondersteunt geen exotische installatietypes, ze bieden één keuze voor alle pakketten.

Een van mijn toekomstige doelen met Homebrew is om het mogelijk te maken om op een link op een website te klikken (bijv. Homebrew: // blah en het zal het Ruby-script downloaden, de deps voor dat pakket installeren en dan de app bouwen. nog niet gedaan, maar niet te lastig gezien het ontwerp dat ik heb gekozen.

8. Wat zijn de commandoregelhulpmiddelen die ik moet beheersen om goed te worden in dit spul? Dingen zoals otool, pkg-config etc.

otool is pas echt nuttig achteraf. Het vertelt je waar de ingebouwde binaire koppelingen naar verwijzen. Wanneer u de afhankelijkheden van een tool die u moet bouwen, uitprobeert, is het nutteloos. Hetzelfde geldt voor pkg-config, omdat je de afhankelijkheid al hebt geïnstalleerd voordat je het kunt gebruiken.

Mijn gereedschapsketen is, lees de README- en INSTALL-bestanden en voer een configuratiehelp uit. Bekijk de uitvoer van de build om te controleren of deze gezond is. Ontleed alle build-fouten. Misschien in de toekomst, vraag op serverfault :)


38
2017-07-27 13:08



Interessant, Homebrew lijkt veel op Portage (de pakketbeheerder van Gentoo Linux). Klinkt als een mooi stuk werk. - David Z


Dit is een enorm onderwerp dus laten we beginnen met gedeelde bibliotheken op Linux (ELF op Linux en Mach-O op OS X), Ulrich Drepper heeft een goed inleiding tot het schrijven van DNB's (dynamische gedeelde objecten) die een geschiedenis van gedeelde bibliotheken op Linux hier beschikbaar omvatten, inclusief waarom ze belangrijk zijn

Ulrich beschrijft ook waarom statische koppeling wordt als schadelijk beschouwd een van de belangrijkste punten hier is beveiligingsupdates. Buffer overflows in een gemeenschappelijke bibliotheek (bijv. Zlib) die statisch statisch gelinkt is, kan een enorme overhead veroorzaken voor distributies - dit gebeurde met zlib 1.1.3 (Red Hat-advies)

ELF

De linker ld.so handleidingpagina

man ld.so 

legt de basispaden en bestanden uit die betrokken zijn bij runtime dynamic linking. Op moderne Linux-systemen zie je extra paden toegevoegd via /etc/ld.so.conf.d/ meestal toegevoegd via een glob opnemen in /etc/ld.so.conf.

Als u wilt zien wat dynamisch beschikbaar is via uw ld.so-configuratie, kunt u uitvoeren

ldconfig -v -N -X

Het lezen van de DSO-howto zou je een goed basiskennisniveau moeten geven om vervolgens te begrijpen hoe die principes van toepassing zijn op Mach-O op OS X.

Macho

Op OS X is het binaire formaat Mach-O. Lokale systeemdocumentatie voor de linker is

man dyld

De Mach formaat documentatie is verkrijgbaar bij Apple

UNIX-bouwtools

Het gemeenschappelijke configure, make, make install proces wordt meestal geleverd door GNU autotools die een online boek die een deel van de geschiedenis van de configure / build-splitsing en de GNU-toolchain beslaat. autoconf maakt gebruik van tests om de beschikbaarheid van functies te bepalen op het doelsysteem dat door het systeem wordt gebruikt M4-macrotaal om dit te rijden. automake is in feite een template-methode voor Makefiles, de sjabloon wordt over het algemeen Makefile.am genoemd, die een Makefile.in uitvoert, die de uitvoer van autoconf (het configure-script) omzet in een Makefile.

De GNU hallo programma werkt als een goed voorbeeld voor het begrijpen van de GNU-toolchain - en de handleiding bevat documentatie voor autotools.


11
2017-07-27 09:18





Simon! Ik weet hoe je je voelt; Ik worstelde ook met dit onderdeel van het leren van Linux. Op basis van mijn eigen ervaringen schreef ik een tutorial over enkele van de items die je toespreekt (meestal als een referentie voor mezelf!): http://easyaspy.blogspot.com/2008/12/buildinginstalling-application-from.html. Ik denk dat je mijn opmerking over het eenvoudig maken van Python-toepassingen om te bouwen / installeren op prijs stelt. :)

Ik hoop dat dit helpt! En gelukkig compileren.

Tim Jones


Een toepassing bouwen / installeren vanuit de bron in Ubuntu Linux

Hoewel de Ubuntu-repositories boordevol geweldige applicaties zijn, kun je op een bepaald moment die "must-have" -tool tegenkomen die niet in de repositories zit (of geen Debian-pakket heeft) of je hebt een nieuwere versie dan in de repositories. Wat doe jij? Nou, je moet de applicatie vanaf de bron bouwen! Maak je geen zorgen, het is echt niet zo ingewikkeld als het klinkt. Hier zijn enkele tips, gebaseerd op mijn ervaringen om van een amateur in rang te worden! (Terwijl ik Ubuntu voor dit voorbeeld gebruik, zouden de algemene concepten van toepassing moeten zijn op vrijwel elke Unix / Linux-distributie, zoals Fedora, en zelfs op het Cygwin-platform op Windows.)

Het basisproces voor het bouwen (compileren) van de meeste applicaties uit de bron volgt deze volgorde: configure -> compile -> install. De typische Unix / Linux-opdrachten om deze dingen te doen zijn: config -> make -> make install. In sommige gevallen vindt u zelfs webpagina's die laten zien dat al deze kunnen worden gecombineerd in één enkele opdracht:

$ config && make && make install

Natuurlijk gaat dit commando ervan uit dat er geen problemen zijn in een van deze stappen. Hier komt het plezier aan!

Ermee beginnen

Als u nog niet eerder een toepassing uit de bron op uw systeem hebt gecompileerd, moet u deze waarschijnlijk instellen met een aantal algemene ontwikkeltools, zoals de gcc compilersuite, enkele veelvoorkomende header-bestanden (denk aan dit als code die al is geschreven door iemand anders die wordt gebruikt door het programma dat u installeert) en de maak-tool. Gelukkig wordt er in Ubuntu een metapackage genoemd build-essential dat zal van dit installeren. Om het te installeren (of zorg ervoor dat je het al hebt!), Voer je deze opdracht in de terminal uit:

$ sudo apt-get install build-essential

Nu u de basisinstellingen hebt, downloadt u de toepassingsbronbestanden en slaat u ze op in een map waarvoor u lees- / schrijfrechten hebt, zoals uw "thuismap". Meestal staan ​​deze in een archiefbestand met een bestandsextensie van een van beide .tar.gz of .tar.bz2. De .tar betekent gewoon dat het een "tape-archief" is, wat een groep bestanden is die hun relatieve directorystructuur behoudt. De .gz staat voor gzip (GNU zip), wat een populair Unix / Linux-compressieformaat is. Evenzo, de .bz2 staat voor bzip2, wat een nieuwer compressieformaat is dat hogere compressie (kleinere gecomprimeerde bestandsgrootte) biedt dan gzip.

Nadat u het bronbestand hebt gedownload, opent u een terminalvenster (System Terminal vanuit het Ubuntu-menu) en gaat u naar de map waar u uw bestand hebt opgeslagen. (Ik zal gebruiken ~/download in dit voorbeeld. Hier is '~' een snelkoppeling naar uw 'thuis'-map.) Gebruik de opdracht tar om de bestanden uit het gedownloade archiefbestand te extraheren:

Als uw bestand een gzip-archief is (bijv. Eindigt met .tar.gz), gebruik de opdracht:

            $ tar -zxvf filename.tar.gz

Als uw bestand een bzip2-archief is (bijv. Eindigt met .tar.bz2), gebruik de opdracht:

            $ tar -jxvf filename.tar.gz

Tip: als u dat niet wilt   onthoud de volledige commandolijn   schakelaars voor het uitpakken van archieven, I   raden aan er een (of beide) van te krijgen   deze hulpprogramma's: dtrx (mijn favoriet!)   of deco (populairder). Met een van beide   deze hulpprogramma's, je komt gewoon in het   naam van het hulpprogramma (dtrx of deco) en   de bestandsnaam, het doet het allemaal   rust uit. Beide "weten" hoe   omgaan met de meeste archiefindelingen die   je zult waarschijnlijk overkomen en zij   heb geweldige foutafhandeling.

Wanneer u bouwt vanuit de bron, zijn er twee veelvoorkomende soorten fouten die u waarschijnlijk zult tegenkomen:

  1. Configuratiefouten treden op wanneer u het configuratiescript uitvoert (meestal configuratie of configuratie genoemd) om een ​​maakbestand te maken dat specifiek is voor uw installatie.
  2. Compilerfouten treden op wanneer u de opdracht make uitvoert (nadat de makefile is gegenereerd) en de compiler geen code kan vinden die deze nodig heeft.

We zullen elk van deze bekijken en bespreken hoe ze kunnen worden opgelost.

Configuratie en configuratiefouten

Nadat u het bronarchiefbestand in de terminal hebt uitgepakt, moet u naar de map met de uitgepakte bestanden gaan. Meestal is deze mapnaam hetzelfde als de naam van het bestand (zonder de .tar.gz of .tar.bz2 uitbreiding). Soms is de mapnaam echter alleen de naam van de toepassing, zonder enige versiegegevens.

Zoek in de brondirectory naar een README bestand en / of een INSTALL bestand (of iets met vergelijkbare namen). Deze bestanden bevatten meestal nuttige informatie over het bouwen / compileren van de applicatie en het installeren ervan, inclusief informatie over afhankelijkheden. "Afhankelijkheden" zijn slechts een mooie naam voor andere componenten of bibliotheken die nodig zijn om met succes te compileren.

Nadat je de. Hebt gelezen README en / of INSTALL bestand (en, hopelijk bekeken naar relevante online documentatie voor de toepassing), zoek naar een uitvoerbaar bestand (heeft de "x" toestemming ingesteld op het bestand) bestand genaamd config of configure. Soms heeft het bestand een extensie, zoals .sh (B.v. config.sh). Dit is meestal een shell-script dat een aantal andere hulpprogramma's uitvoert om te bevestigen dat u een "normale" omgeving hebt om te compileren. Met andere woorden, het zal controleren om ervoor te zorgen dat je alles geïnstalleerd hebt dat je nodig hebt.

Tip: als dit een op Python gebaseerd is   toepassing, in plaats van een configuratiebestand,   je zou een bestand moeten vinden met de naam setup.py.   Python-applicaties zijn meestal erg   eenvoudig te installeren. Om dit te installeren   toepassing, als root (bijv. sudo   voor het volgende commando   onder Ubuntu), voer dit commando uit:

    $ python setup.py install

Dat zou alles moeten zijn wat je moet doen   do. U kunt de rest hiervan overslaan   zelfstudie en ga direct verder met gebruik   en geniet van je sollicitatie.

Voer het configuratiescript uit in de terminal. Meestal kunt u (en zou!) Uw configuratiescript met uw gewone gebruikersaccount moeten uitvoeren.

$ ./config

Het script zal enkele berichten weergeven om u een idee te geven van wat het doet. Vaak geeft het script u een indicatie of het is gelukt of mislukt en, als het niet is gelukt, wat informatie over de oorzaak van de fout. Krijgt u geen foutmeldingen, dan kunt u er meestal vanuit gaan dat alles goed is verlopen.

Als u geen script vindt dat lijkt op een configuratiescript, betekent dit meestal dat de toepassing heel eenvoudig is en platformonafhankelijk. Dit betekent dat je eenvoudigweg naar de onderstaande build / compileer stap kunt gaan, omdat de bijgeleverde Makefilezou op elk systeem moeten werken.

Een voorbeeld

In deze zelfstudie ga ik de op tekst gebaseerde RSS-lezer met de naam Newsbeuter gebruiken als voorbeeld voor de soorten fouten die u kunt tegenkomen bij het bouwen van uw toepassing. Voor Newsbeuter is de naam van het configuratiescript config.sh. Op mijn systeem, als ik ren config.sh, de volgende fouten optreden:

tester@sitlabcpu22:~/download/newsbeuter-1.3$ ./config.sh
Checking for package sqlite3... not found

You need package sqlite3 in order to compile this program.
Please make sure it is installed.

Toen ik wat onderzoek deed, ontdekte ik dat, in feite, de sqlite3 toepassing is geïnstalleerd. Omdat ik echter probeer te bouwen vanaf de bron, is dit een tip wat config.sh is eigenlijk op zoek naar de ontwikkelingsbibliotheken (headers) voor sqlite3. In Ubuntu hebben de meeste pakketten een bijbehorend tegenpakket voor ontwikkeling dat eindigt op -dev. (Andere platforms, zoals Fedora, gebruiken vaak een pakketachtervoegsel van -devel voor de ontwikkelpakketten.)

Om het juiste pakket voor de te vinden sqlite3 ontwikkelingspakket, kunnen we de apt-cache utility in Ubuntu (en, vergelijkbaar, de yum utility in Fedora):

tester@sitlabcpu22:~/download/newsbeuter-1.3$ sudo apt-cache search sqlite

Deze opdracht geeft een vrij grote lijst met resultaten, dus we moeten een beetje detectivewerk doen om te bepalen welk pakket het meest geschikt is. In dit geval blijkt het juiste pakket te zijn libsqlite3-dev. Merk op dat het pakket waarnaar we op zoek zijn soms het lib voorvoegsel, in plaats van alleen dezelfde pakketnaam plus -dev. Dit komt omdat we soms alleen maar op zoek zijn naar een gedeelde bibliotheek die door veel verschillende applicaties kan worden gebruikt. Installeren libsqlite3-dev, voer de typische apt-get install-opdracht in de terminal uit:

tester@sitlabcpu22:~/download/newsbeuter-1.3$ sudo apt-get install libsqlite3-dev

Nu moeten we vluchten config.sh nogmaals om ervoor te zorgen dat we dit afhankelijkheidsprobleem hebben opgelost en dat we geen afhankelijkheidsproblemen meer hebben. (Hoewel ik het hier niet zal laten zien, in het geval van Newsbeuter, moest ik ook het libcurl4-openssl-dev pakket, ook.) Ook als u een ontwikkelpakket installeert (zoals libsqlite3-dev) en het bijbehorende toepassingspakket (bijv. sqlite3) is nog niet geïnstalleerd, de meeste systemen zullen het bijbehorende toepassingspakket automatisch tegelijkertijd installeren.

Wanneer de configuratie met succes wordt uitgevoerd, is het resultaat dat er een of meer make-bestanden worden gemaakt. Deze bestanden worden meestal genoemd Makefile (vergeet niet dat de zaak van de bestandsnaam er toe doet in Unix / Linux!). Als het build-pakket submappen bevat, zoals src, enz., bevat elk van deze sub-directories een Makefile, ook.

Bouw- en compilatiefouten

Nu zijn we klaar om de applicatie daadwerkelijk te compileren. Dit wordt vaak gebouw genoemd en de naam is geleend van het echte proces van het bouwen van iets. De verschillende "stukken" van de toepassing, die meestal meerdere broncodebestanden zijn, worden samen gecombineerd om de algehele toepassing te vormen. Het make-hulpprogramma beheert het bouwproces en roept andere applicaties, zoals de compiler en linker, op om het werk daadwerkelijk te doen. In de meeste gevallen voert u make (met uw gewone gebruikersaccount) gewoon uit vanuit de directory waar u de configuratie hebt uitgevoerd. (In enkele gevallen, zoals het compileren van toepassingen die zijn geschreven met de Qt-bibliotheek, moet u in plaats daarvan een andere "wrapper" -toepassing uitvoeren, zoals qmake. README en / of INSTALLdocumenten voor meer informatie.)

Net als bij het bovenstaande configuratiescript, geeft het, als u make (of het vergelijkbare hulpprogramma) in de terminal uitvoert, enkele berichten weer over wat wordt uitgevoerd en eventuele waarschuwingen en fouten. U kunt waarschuwingen meestal negeren, omdat deze voornamelijk voor de ontwikkelaars van de toepassing zijn en hen vertellen dat er enkele standaardpraktijken zijn die worden geschonden. Gewoonlijk hebben deze waarschuwingen geen invloed op de toepassingsfunctie. Aan de andere kant moeten compilatiefouten worden afgehandeld. Met Newsbeuter, toen ik make maakte, ging het een tijdje goed, maar toen kreeg ik een foutmelding:

tester@sitlabcpu22:~/download/newsbeuter-1.3$ make
...
c++ -ggdb -I/sw/include -I./include -I./stfl -I./filter -I. -I./xmlrss -Wall -Wextra -DLOCALEDIR=\"/usr/local/share/locale\" -o src/configparser.o -c src/configparser.cpp
c++ -ggdb -I/sw/include -I./include -I./stfl -I./filter -I. -I./xmlrss -Wall -Wextra -DLOCALEDIR=\"/usr/local/share/locale\" -o src/colormanager.o -c src/colormanager.cpp
In file included from ./include/pb_view.h:5,
from src/colormanager.cpp:4:
./include/stflpp.h:5:18: error: stfl.h: No such file or directory
In file included from ./include/pb_view.h:5,
from src/colormanager.cpp:4:
./include/stflpp.h:33: error: ISO C++ forbids declaration of \u2018stfl_form\u2019 with no type
./include/stflpp.h:33: error: expected \u2018;\u2019 before \u2018*\u2019 token
./include/stflpp.h:34: error: ISO C++ forbids declaration of \u2018stfl_ipool\u2019 with no type
./include/stflpp.h:34: error: expected \u2018;\u2019 before \u2018*\u2019 token
make: *** [src/colormanager.o] Error 1

Het maakproces stopt zodra de eerste fout is opgetreden. Het verwerken van compilerfouten kan soms lastig zijn. Je moet de fouten bekijken voor enkele aanwijzingen over het probleem. Meestal is het probleem dat sommige header-bestanden, die meestal een extensie hebben van .h of .hpp, ontbreken. In het geval van de fout hierboven, is (of zou moeten zijn!) Duidelijk dat het probleem dat is stfl.h header-bestand kan niet worden gevonden. Zoals in dit voorbeeld wordt getoond, wilt u de eerste regels van het foutbericht bekijken en uw weg naar beneden vinden om de onderliggende oorzaak van het probleem te vinden.

Na het bekijken van de Newsbeuter-documentatie (die ik eerder had moeten doen voordat ik begon, maar dan dit deel van de tutorial niet erg zinvol zou zijn!), Vond ik dat het een bibliotheek van derden vereist, STFL genaamd. Dus wat doen we in dit geval? Welnu, we herhalen in essentie hetzelfde exacte proces voor die vereiste bibliotheek: haal de bibliotheek op en voer het configure-build-install-proces daarvoor uit en ga dan verder met het bouwen van de gewenste applicatie. Bijvoorbeeld in het geval van STFL, moest ik de libncursesw5-dev pakket om goed te kunnen bouwen. (Gewoonlijk is het niet nodig om de configuratiestap opnieuw uit te voeren in onze oorspronkelijke applicatie na het installeren van een andere vereiste toepassing, maar het doet ook nooit pijn.)

Na het succesvol installeren van STFL toolkit, verliep het maakproces voor Newsbeuter succesvol. Het maakproces gaat meestal verder waar het ophoudt (op het punt van de fout). Alle bestanden die al met succes zijn gecompileerd, worden dus niet opnieuw gecompileerd. Als u alles opnieuw wilt compileren, kunt u uitvoeren make clean all uitvoeren om gecompileerde objecten te verwijderen en make opnieuw uitvoeren.

installeren

Nadat het buildproces is voltooid, bent u klaar om de applicatie te installeren. In de meeste gevallen om de toepassing te installeren in de algemene gedeelten van het bestandssysteem (bijv. /usr/bin of /usr/share/bin, etc.), moet u de installatie uitvoeren als root. Installeren is echt de eenvoudigste stap in het hele proces. Om te installeren, in de terminal run:

$ make install

Controleer de uitvoer van dit proces op eventuele fouten. Als alles is gelukt, moet u de opdrachtnaam in de terminal kunnen uitvoeren en deze wordt gestart. (Toevoegen & aan het einde van de opdrachtregel, als het een GUI-toepassing is, of u kunt de terminalsessie niet gebruiken totdat de toepassing is voltooid.)

Wanneer u een toepassing bouwt vanuit de bron, voegt deze meestal geen pictogram of snelkoppeling toe aan de GUI-menu's in Ubuntu. U moet dit handmatig toevoegen.

En dat is in feite het proces, hoewel potentieel iteratief, om een ​​applicatie van de bron in Ubuntu te bouwen en te installeren. Nadat je dit slechts een paar keer hebt gedaan, wordt het een tweede natuur voor jou!


9
2017-07-31 14:09



Tim, ik had je tutorial graag gelezen, maar de link die je hebt gepost werkt niet. - gareth_bowles


Nou, ./configure --help geeft je veel informatie, voor door GNU autotools gegenereerde configuratiebestanden. Het meeste komt neer op - met / - zonder functies in te schakelen (deze kunnen een extra parameter gebruiken, zoals "gedeeld" om te zeggen waar de bibliotheek te vinden is).

Andere belangrijke zijn --prefix (standaard / usr / local / meestal) om te zeggen waar te installeren (als je pakketten samenstelt, wil je dit meestal als --prefix = / usr of misschien --prefix = / opt / YourPackage).

Onder Linux worden / lib, / usr / lib en / usr / local / lib over het algemeen doorzocht op mijn gcc en opgenomen in de standaardconfiguratie van ldconfig. Tenzij je een goede reden hebt, dit is waar je je bibliotheken wilt hebben. /etc/ld.so.conf kan echter extra vermeldingen toevoegen.

configureer en vind ze door gewoon te proberen "gcc -l" uit te voeren en te zien of het fouten bevat. U kunt "-L" toevoegen aan uw CFLAGS-parameter om extra paden toe te voegen om te zoeken.

Je kunt meerdere versies laten installeren en software gekoppeld aan een oudere versie blijft ertegen verbonden (voer ldd uit om de binding op Linux te achterhalen), maar nieuwe compilaties zijn over het algemeen gericht op de nieuwste versie van een dynamische bibliotheek op je systeem.

De meeste software neemt dynamische libs aan, vooral als het libtool gebruikt, dus het is mogelijk dat niet-triviale apps niet correct statisch bouwen.

ls -l is de beste keuze om bibliotheken te vinden.

En dat is waar ik geen informatie meer heb; hoe goed te spelen met pakketten: weet niet. Waar mogelijk probeer ik dingen in een pakket te verpakken om het probleem te voorkomen.


5
2017-07-27 09:11





"Hoe weet ik welke argumenten moeten worden doorgegeven aan ./configure?"

meestal: ./configure --help zal je vertellen wat je daar wilt.

"Hoe kan ik zien welke bibliotheken ik heb geïnstalleerd en welke versies?"

Dat hangt van het systeem af. Eén manier is om gewoon een te doen find /|grep libname|less aangezien de bibliotheekbestanden over het algemeen de versie in de bestandsnaam hebben.

"Hoe kan ik meer dan één versie van een bibliotheek installeren zonder mijn normale systeem te onderbreken?"

Nogmaals, afhankelijk van het systeem en de bibliotheek. sudo make altinstall zal een versie met een naam voor u maken. Bibliotheekbestanden hebben echter meestal een eigen versie. Houd echter in gedachten; aangezien de versies vaak symlinks naar een "genormaliseerde" naam maken, kan dit dingen breken.

"Als ik dingen vanaf de bron installeer op een systeem dat anders via pakketten wordt beheerd, wat is dan de schoonste manier om dat te doen?"

Gebruik de --prefix-parameters in ./configure en plaats ze ergens in /opt is een goede gewoonte om te volgen.

Disclaimer: Ik ben geenszins een expert, maar ik gebruik linux al meer dan 5 jaar oud van de cmd-lijn (slackware, CentOS, redhat, ubuntu, misc others en OS X).


3
2017-07-27 09:13





Om een ​​beetje van je vraag te beantwoorden heb ik onlangs een goede manier gevonden om te zien welke bibliotheken je hebt geïnstalleerd en de versies (dit staat op Linux Debian dus zou ook met andere versies moeten werken).

dpkg --list

Je zou een hele lange lijst moeten krijgen met wat uitvoer zoals deze

ii  libssl0.9.8    0.9.8c-4etch5  SSL shared libraries
ii  libssp0        4.1.1-21       GCC stack smashing protection library
ii  libstdc++5     3.3.6-15       The GNU Standard C++ Library v3
ii  libstdc++5-3.3 3.3.6-15       The GNU Standard C++ Library v3 (development
ii  libstdc++6     4.1.1-21       The GNU Standard C++ Library v3

3
2017-07-27 09:12





Simon,

1.) ./configure --help biedt een goede hoeveelheid informatie. Ik stel voor het te controleren. Het heeft over het algemeen opties voor het compileren van statisch / dynamisch gekoppelde bibliotheken, indien van toepassing.

2.) Libaries leven in het dynamische linkerpad. Dit wordt meestal ingesteld in /etc/ld.so.conf. De linker zoekt naar de juiste bibliotheken zoals de omgevingsvariabele PATH die overeenkomt met de eerste gevonden.

3.) Dat leidt over het algemeen tot problemen omdat je alles opnieuw moet compileren wanneer een bibliotheekversie verandert. Als je wat zoekt, vind je waarschijnlijk een hoop redenen waarom statisch linken een slecht idee is. Ik heb het niet zo lang gedaan, ik kan het hier niet echt uitwerken.

4.) Dit is een beetje moeilijk. U moet uw bibliotheekpad controleren om absoluut zeker te zijn. Bibliotheken hebben over het algemeen een symbolische link naar de versie die is geïnstalleerd.

bijv. libssh2.so.1 -> libssh2.so.1.0.0

Over het algemeen beheren mensen de bibliotheken en programma's die ze installeren door hun eigen debian-pakketten te rollen of een andere techniek te gebruiken. Ik beheer de geïnstalleerde software met behulp van stow (http://www.gnu.org/software/stow/) wat heel eenvoudig is en de bibliotheek installeert met behulp van symbolische koppelingen. Ik vind het gemakkelijker omdat ik geen deb / rpm-pakket hoef te bouwen / installeren / testen.

5.) Meerdere versies van bibliotheken kunnen normaal worden geïnstalleerd in bibliotheekdirectory's. Bibliotheken gekoppeld aan uitvoerbare bestanden blijven gekoppeld aan de versies waaraan ze zijn gekoppeld. ldd uitvoeren op een uitvoerbaar bestand vertelt u naar welke bibliotheken het uitvoerbare bestand is gekoppeld.

6.) Zoals ik eerder al zei, is het rollen van je eigen debian-pakketten of het gebruik van stow waarschijnlijk de schoonste oplossing.

7.) Ik kan niet echt spreken voor Mac OSX, maar voor Linux is het distributiesysteem de beste manier.

8.) Waarschijnlijk zal veel frustratie worden opgelost door ldd te gebruiken en uit te zoeken naar welke versie iets is gelinkt of welke bibliotheek die is gekoppeld aan een uitvoerbaar bestand niet kan worden gevonden. pkg-config helpt je veel, maar alleen voor software die het gebruikt. Het is geen onderdeel van het standaard autotools build-systeem, hoewel het tegenwoordig populair is.


3
2017-07-27 09:22





Statische bibliotheken zijn geen goed idee - als u de bibliotheek moet upgraden (bijvoorbeeld om een ​​beveiligingsprobleem op te lossen), moet u alles opnieuw compileren met een afhankelijkheid van die bibliotheek.

Ik vind het niet leuk om het idee van "make install" mogelijk in de problemen te brengen met mijn systeem, maar zoals anderen al hebben gezegd, is het meestal een stuk minder pijn om dingen in / usr / local te installeren in plaats van --prefix ergens anders te installeren. Dus, ik heb / usr / local gebruikt voor mijn normale (niet-bevoorrechte) gebruiker. Op die manier is "make install" vrijwel gegarandeerd geen rommelen met belangrijke systeembestanden. (Dit werkt uiteraard niet op systemen met meerdere gebruikers. Maar het is geweldig voor virtuele servers.)


3
2017-07-27 16:04





Hoewel het niet expliciet in uw vragenlijst stond, vermeldt u het in uw voorwoord:

./configure && make && sudo make install is meestal voldoende, maar soms werkt het niet - en als het dat niet doet, loop ik vaak vast.

Wanneer ik vastloop op Debian of Ubuntu, zal ik auto-apt gebruiken, dat automatisch de pakketten zal installeren die de bestanden bevatten die niet kunnen worden geconfigureerd.

Zien:

Een ander hulpmiddel dat u misschien handig vindt, is CheckInstall, het voegt toepassingen toe die zijn geïnstalleerd met make install naar uw lijst met geïnstalleerde pakketten: https://help.ubuntu.com/community/CheckInstall


3
2017-07-31 16:28





Voor OS X:

  • Hoe weet ik welke argumenten moeten worden doorgegeven aan ./configure?

./configure --help

  • Wat zijn de werkelijke verschillen tussen een gedeelde en een statisch gekoppelde bibliotheek? Waarom kan ik niet gewoon alles statisch koppelen (RAM- en schijfruimte zijn tegenwoordig goedkoop) en daarom vreemde conflicten met bibliotheekversies vermijden?

Door gedeelde bibliotheken te gebruiken, kunt u de bibliotheek upgraden zonder alles opnieuw te hoeven compileren.

  • Hoe gedeelde bibliotheken onder OS X / Linux werken - waar ze op het bestandssysteem wonen, hoe ./configure && make find ze vindt, wat er feitelijk gebeurt wanneer ze worden gekoppeld aan

Systeembibliotheken leven in / usr / lib.

Bibliotheken die u zelf compileert, leven in / usr / local / lib (/ usr / local is de standaard --prefix-vlag voor ./configure).

Omgevingsvariabelen DYLD_FALLBACK_LIBRARY_PATH en LD_LIBRARY_PATH laten je specificeren in welke mappen je moet kijken, dus / usr / local / lib moet er aan het begin van de lijst staan.

  • Hoe kan ik meer dan één versie van een bibliotheek installeren zonder mijn normale systeem te onderbreken?

Installeer alles naar / usr / local - met de omgevingsvariabelen hierboven, heeft de versie in / usr / local / lib voorrang op de versie in / usr / lib in uw omgeving.

  • Als ik dingen van de bron installeer op een systeem dat anders beheerd wordt met pakketten, wat is dan de schoonste manier om dit te doen?

Installeren naar / usr / local. In Ubuntu probeer ik eerst de checkinstall te gebruiken om een ​​deb-pakket te maken.

  • Ervan uitgaande dat ik erin slaag om iets onhandigs van de bron te compileren, hoe kan ik dat dan verpakken zodat andere mensen niet door dezelfde hoepels hoeven te springen? Vooral op OS X ....

Documenteer de compilatiestappen in een blogpost, zou ik zeggen.


2
2017-07-27 17:36