Hvordan lage og bruke statiske biblioteker med «ar»-kommandoen i Linux
Under programvareutvikling er det ofte behov for å organisere og gjenbruke kode. En måte å oppnå dette på i Linux-miljøer er ved å bruke «ar»-kommandoen for å lage funksjonsbiblioteker. Denne veiledningen vil demonstrere hvordan du oppretter et statisk bibliotek, modifiserer det og integrerer det i et program. Vi vil også inkludere eksempler på kode.
«ar»-kommandoen er et velprøvd verktøy som har vært i bruk siden 1971. Navnet «ar» stammer fra den opprinnelige hensikten med verktøyet, nemlig å opprette arkivfiler. En arkivfil er en enkelt fil som fungerer som en container for andre filer. Disse filene kan legges til, fjernes eller hentes ut fra arkivet. Selv om «ar» ikke lenger brukes mye til generell arkivering (andre verktøy som «tar» er mer populære for dette), forblir det et viktig verktøy for spesifikke oppgaver.
I moderne programvareutvikling brukes «ar» hovedsakelig til å lage statiske biblioteker, som er avgjørende for å dele kode mellom ulike programmer. I tillegg brukes det også for å lage pakker, som for eksempel «.deb»-filene som brukes i Debian-baserte Linux-distribusjoner som Ubuntu.
I denne opplæringen skal vi gå gjennom de nødvendige trinnene for å bygge og modifisere et statisk bibliotek. Vi vil vise hvordan du bruker dette biblioteket i et enkelt program. For å gjøre dette, skal vi lage et bibliotek som inneholder funksjoner for å kode og dekode tekststrenger. Det er viktig å understreke at koden vi presenterer her, er for demonstrasjonsformål og bør ikke brukes til reell kryptering. Vi implementerer en enkel substitusjonsalgoritme, hvor hver bokstav i teksten forskyves en posisjon (A blir B, B blir C, osv.).
Funksjonene cipher_encode() og cipher_decode()
Vi begynner med å opprette en katalog som heter «bibliotek», og vi vil senere opprette en underkatalog kalt «test». I «bibliotek»-katalogen lager vi to filer:
cipher_encode.c (inneholder cipher_encode()-funksjonen):
void cipher_encode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]++; } } // end of cipher_encode
cipher_decode.c (inneholder cipher_decode()-funksjonen):
void cipher_decode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]--; } } // end of cipher_decode
Disse filene, som inneholder instruksjoner for datamaskinen, kalles kildekodefiler. Vi skal bygge et bibliotek med navnet «libcipher.a», som vil inneholde de kompilerte versjonene av disse filene. I tillegg lager vi en overskriftsfil, «libcipher.h», som inneholder deklarasjonene av de to funksjonene i biblioteket. Overskriftsfiler gjør det mulig for andre programmer å bruke funksjonene i biblioteket uten å måtte vite hvordan de er implementert.
Med et bibliotek og en overskriftsfil kan andre programmerere enkelt inkludere kode i sine egne prosjekter. Istedenfor å skrive funksjonene på nytt, kan de enkelt benytte funksjonene fra biblioteket.
Kompilering av cipher_encode.c og cipher_decode.c
Vi bruker gcc, standard GNU-kompilatoren, til å kompilere kildekodefilene. Med «-c»-alternativet (kompilering, ingen lenking) instruerer vi gcc om å stoppe etter kompileringen og generere objektfiler. Objektfiler er mellomprodukter som vanligvis kobles sammen av gcc for å lage et kjørbart program, men vi hopper over den prosessen her. Vi trenger kun objektfilene.
Først, la oss verifisere at filene er tilstede ved å bruke kommandoen «ls -l»:
ls -l
Nå bruker vi gcc til å kompilere kildekodene:
gcc -c cipher_encode.c
gcc -c cipher_decode.c
Ingen utskrift fra gcc indikerer at kompileringen gikk bra.
Dette genererer to objektfiler med samme navn som kildekodene, men med «.o»-endelser. Disse objektfilene er klare for å bli lagt til i bibliotekfilen.
Sjekk filene igjen:
ls -l
Opprettelse av libcipher.a biblioteket
Vi oppretter bibliotekfilen, som i praksis er en arkivfil, med «ar»-kommandoen. Vi bruker «-c»-alternativet (opprett) for å lage biblioteksfilen, «-r» (legg til med erstatning) for å legge til filene, og «-s» (indeks) for å bygge en indeks for filene i biblioteket.
Vi kaller bibliotekfilen «libcipher.a». I kommandoen spesifiserer vi også navnene på objektfilene som vi ønsker å legge til.
ar -crs libcipher.a cipher_encode.o cipher_decode.o
Ved å vise innholdet i katalogen ser vi at «libcipher.a» er opprettet.
ls -l
Vi kan se modulene i biblioteket ved å bruke «-t»-alternativet (tabell) med «ar»:
ar -t libcipher.a
Opprettelse av libcipher.h overskriftsfilen
Filen «libcipher.h» vil bli inkludert i alle programmer som bruker «libcipher.a». Denne filen må inneholde deklarasjoner av funksjonene i biblioteket.
Du kan opprette overskriftsfilen ved å skrive funksjonsdeklarasjonene i en teksteditor, f.eks. «gedit». Lagre filen som «libcipher.h» i samme katalogen som «libcipher.a».
void cipher_encode(char *text); void cipher_decode(char *text);
Bruke libcipher-biblioteket
Den beste måten å teste biblioteket vårt på, er å skrive et lite program som bruker det. Først lager vi en ny katalog som heter «test»:
mkdir test
Vi kopierer biblioteket og overskriftsfilen til den nye katalogen:
cp libcipher.* ./test
Deretter går vi inn i den nye katalogen:
cd test
Vi bekrefter at de to filene er der:
ls -l
Nå må vi lage et lite program som bruker biblioteket. I en teksteditor skriver du inn følgende kode og lagrer filen som «test.c» i testkatalogen:
#include <stdio.h> #include <stdlib.h> #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="How-To Geek loves Linux"; puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main
Programmet gjør følgende:
- Inkluderer «libcipher.h» slik at den kan bruke bibliotekfunksjonene.
- Oppretter en tekststreng som inneholder «How-To Geek loves Linux».
- Skriver ut originalstrengen.
- Kaller «cipher_encode()» for å kode strengen og skriver den ut.
- Kaller «cipher_decode()» for å dekode strengen og skriver den ut.
For å generere det kjørbare programmet «test», må vi kompilere «test.c» og lenke inn biblioteket. Med «-o» (output) angir vi navnet på den kjørbare filen.
gcc test.c libcipher.a -o test
Hvis gcc ikke gir noen utskrift, har kompileringen gått bra. Nå kjører vi programmet:
./test
Og vi får den forventede utskriften. Programmet skriver ut den originale teksten, den krypterte teksten og deretter den dekrypterte teksten. Dette viser at biblioteket fungerer som det skal.
Legge til en ny modul til biblioteket
La oss legge til en ny funksjon i biblioteket. Vi lager en funksjon som viser bibliotekets versjon. Først må vi lage koden for den nye funksjonen, kompilere den og legge den til biblioteket.
Skriv inn følgende kode i en ny fil, kalt «cipher_version.c», i «bibliotek»-katalogen:
#include <stdio.h> void cipher_version(void) { puts("How-To Geek :: VERY INSECURE Cipher Library"); puts("Version 0.0.1 Alphan"); } // end of cipher_version
I tillegg må vi legge til deklarasjonen av den nye funksjonen i «libcipher.h»-filen. Legg til en ny linje nederst slik at den ser slik ut:
void cipher_encode(char *text); void cipher_decode(char *text); void cipher_version(void);
Lagre den modifiserte «libcipher.h»-filen.
Kompiler «cipher_version.c» slik at vi får en «cipher_version.o»-fil:
gcc -c cipher_version.c
Med den nye objektfilen kan vi legge den til «libcipher.a»-biblioteket. Med «-v» (verbose)-alternativet vil «ar» gi oss informasjon om hva som skjer:
ar -rsv libcipher.a cipher_version.o
Meldingen «a» betyr at filen er «lagt til».
Vi kan bruke «-t»-alternativet for å liste alle moduler i biblioteket:
ar -t libcipher.a
Nå har vi tre moduler i biblioteket. La oss bruke den nye funksjonen.
Bruke cipher_version()-funksjonen
Vi fjerner det gamle biblioteket og overskriftsfilen fra testkatalogen, og erstatter de med de nye versjonene:
rm ./test/libcipher.*
cp libcipher.* ./test
cd test
Nå kan vi modifisere «test.c»-programmet slik at det bruker den nye funksjonen. Vi legger inn kallet til «cipher_version()» før den første «puts(text);»-linjen:
#include <stdio.h> #include <stdlib.h> #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="How-To Geek loves Linux"; // new line added here cipher_version(); puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // end of main
Lagre filen som «test.c». Deretter kompilerer vi og tester:
gcc test.c libcipher.a -o test
La oss kjøre testprogrammet:
Den nye funksjonen fungerer, og vi ser versjonsinformasjonen i utskriften. Men det finnes et problem.
Erstatte en modul i biblioteket
Dette er ikke den første versjonen av biblioteket vårt; det er den andre. Versjonsnummeret er feil. Den første versjonen hadde ikke «cipher_version()». Derfor skal dette være versjon 0.0.2. Vi må erstatte funksjonen i biblioteket.
Heldigvis er det enkelt å gjøre med «ar».
Først, endrer vi «cipher_version.c» i bibliotekskatalogen. Endre «Version 0.0.1 Alpha» til «Version 0.0.2 Alpha». Resultatet blir:
#include <stdio.h> void cipher_version(void) { puts("How-To Geek :: VERY INSECURE Cipher Library"); puts("Version 0.0.2 Alphan"); } // end of cipher_version
Lagre filen og kompiler på nytt:
gcc -c cipher_version.c
Nå erstatter vi den gamle «cipher_version.o» med den nye versjonen.
Vi bruker «-r» (legg til med erstatning) igjen, og med «-s» (indeks) og «-v» (verbose):
ar -rsv libcipher.a cipher_version.o
Meldingen «r» indikerer at modulen er erstattet.
Bruke den oppdaterte cipher_version()-funksjonen
La oss bruke det oppdaterte biblioteket og bekrefte at alt fungerer.
Kopier biblioteket til testkatalogen:
cp libcipher.* ./test
Gå inn i testkatalogen:
cd ./test
Kompiler testprogrammet med det nye biblioteket:
gcc test.c libcipher.a -o test
Og kjør programmet:
./test
Resultatet er som forventet. Riktig versjonsnummer vises, og krypteringen og dekrypteringen fungerer fortsatt.
Slette moduler fra et bibliotek
La oss, til tross for alt, slette «cipher_version.o»-filen fra biblioteket.
Vi bruker «-d» (slett) og «-v» (verbose) for å vise meldingen, og «-s» (indeks) for å oppdatere indeksen:
ar -dsv libcipher.a cipher_version.o
Meldingen «d» indikerer at modulen er slettet.
Hvis vi lister opp modulene i biblioteket, vil vi se at vi er tilbake til to moduler:
ar -t libcipher.a
Husk å fjerne deklarasjonen fra overskriftsfilen når du sletter moduler fra biblioteket.
Del koden din
Biblioteker gjør det enkelt å dele kode på en privat måte. De som har bibliotekfilen og overskriftsfilen, kan bruke koden i sine egne prosjekter, uten at kildekoden blir offentlig.