Sådan installeres program fra kildekode… og fjern det bagefter

Sådan installeres program fra kildekode

kort: Denne detaljerede vejledning forklarer, hvordan du installerer et program fra kildekoden, og hvordan du fjerner det installerede program fra kildekoden.

en af de største styrker i din distribution er dens pakkehåndtering og det tilhørende programlager. Med dem har du alle de nødvendige værktøjer og ressourcer til at hente og installere nye programmer på din computer på en fuldstændig automatiseret måde.

men på trods af alle deres bestræbelser kan pakkevedligeholdere ikke håndtere hver eneste brugssag. De kan heller ikke pakke alle tilgængelige programmer derude. Så der er stadig situationer, hvor du selv skal kompilere og installere nye programmer. For mig er den mest almindelige årsag, at jeg langt skal kompilere nogle programmer, når jeg skal køre en meget specifik version eller ændre kildekoden ved hjælp af nogle fancy kompileringsmuligheder.

Hvis dine behov hører til sidstnævnte kategori, er chancerne for, at du allerede ved, hvad du skal gøre. Men for langt de fleste brugere kan kompilering og installation af programmer fra kildekoden for første gang se ud som en indvielsesceremoni: noget skræmmende; men med løftet om at komme ind i en ny verden af muligheder og et prestigested i et privilegeret samfund.

A. installation af program fra kildekoden i Linuk

og det er præcis, hvad vi vil gøre her. Med henblik på denne artikel, lad os sige, at jeg skal installere NodeJS 8.1.1 på mit system. Netop den version. En version, der ikke er tilgængelig fra Debian-depotet:

sh$ apt-cache madison nodejs | grep amd64 nodejs | 6.11.1~dfsg-1 | http://deb.debian.org/debian experimental/main amd64 Packages nodejs | 4.8.2~dfsg-1 | http://ftp.fr.debian.org/debian stretch/main amd64 Packages nodejs | 4.8.2~dfsg-1~bpo8+1 | http://ftp.fr.debian.org/debian jessie-backports/main amd64 Packages nodejs | 0.10.29~dfsg-2 | http://ftp.fr.debian.org/debian jessie/main amd64 Packages nodejs | 0.10.29~dfsg-1~bpo70+1 | http://ftp.fr.debian.org/debian wheezy-backports/main amd64 Packages

nu er det ret simpelt at installere NodeJs på Ubuntu eller Debian, hvis du gør det med pakkehåndteringen. Men lad os gøre det via kildekoden.

Trin 1: Hent kildekoden fra GitHub

ligesom mange open source-projekter kan kilderne til NodeJS findes på GitHub: https://github.com/nodejs/node

så lad os gå direkte der.

NodeJS officielle GitHub repository

Hvis du ikke er bekendt med GitHub, git eller et andet versionskontrolsystem, der er værd at nævne, indeholder depotet den aktuelle kilde til programmet, samt en historik, der viser, at GitHub, git eller et andet versionskontrolsystem, der er værd at nævne af alle de ændringer, der er foretaget gennem årene til dette program. Til sidst op til den allerførste linje skrevet til dette projekt. For udviklerne har det mange fordele at holde denne historie. For os i dag, den vigtigste er, at vi vil være i stand til at få kilderne fra til projektet, som de var på et givet tidspunkt. Mere præcist vil jeg være i stand til at få kilderne, som de var, da den 8.1.1-version, jeg ønsker, blev frigivet. Selvom der var mange ændringer siden da.

Vælg V8.1.1 tag i NodeJS GitHub repository

på GitHub kan du bruge knappen “branch” til at navigere mellem forskellige versioner af programmet. “Branch” og “tags” er noget relaterede begreber i Git. Grundlæggende opretter udviklerne” branch “og” tags ” for at holde styr på vigtige begivenheder i projekthistorikken, som når de begynder at arbejde på en ny funktion, eller når de udgiver en udgivelse. Jeg vil ikke gå ind i detaljerne her, alt hvad du behøver at vide er, at jeg leder efter den version, der er mærket “v8.1.1”

NodeJS GitHub repository, som det var på det tidspunkt, hvor V8.1.1 tag blev oprettet

efter at have valgt på “V8.1.1 “tag, siden opdateres, den mest oplagte ændring er tagget vises nu som en del af URL’ en. Derudover vil du bemærke, at filændringsdatoen også er anderledes. Kildetræet, du nu ser, er det, der eksisterede på det tidspunkt, hvor V8.1.1-mærket blev oprettet. På en eller anden måde kan du tænke på et versionsstyringsværktøj som git som en tidsrejsemaskine, så du kan gå frem og tilbage i en projekthistorik.

NodeJS GitHub repository Hent som lynlås

på dette tidspunkt kan vi hente kilderne til NodeJS 8.1.1. Du kan ikke gå glip af den store blå knap, der foreslår at hente projektets LYNLÅSARKIV. Som for mig, vil jeg hente og udtrække lynlås fra kommandolinjen af hensyn til forklaringen. Men hvis du foretrækker at bruge et GUI-værktøj, tøv ikke med at gøre det i stedet:

wget https://github.com/nodejs/node/archive/v8.1.1.zipunzip v8.1.1.zipcd node-8.1.1/

hentning af LYNLÅSARKIVET fungerer godt. Men hvis du vil gøre det “som en pro”, vil jeg foreslå at bruge direkte git værktøj til at hente kilderne. Det er slet ikke kompliceret— og det vil være en god første kontakt med et værktøj, du ofte vil støde på:

# first ensure git is installed on your systemsh$ sudo apt-get install git# Make a shallow clone the NodeJS repository at v8.1.1sh$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/nodesh$ cd node/

forresten, hvis du har et problem, skal du bare overveje den første del af denne artikel som en generel introduktion. Senere har jeg mere detaljerede forklaringer på Debian – og RedHat-baserede distributioner for at hjælpe dig med at fejlfinde almindelige problemer.

under alle omstændigheder, når du hentede kilden ved hjælp af git eller som et LYNARKIV, skal du nu have nøjagtigt de samme kildefiler i den aktuelle mappe:

sh$ lsandroid-configure BUILDING.md common.gypi doc Makefile srcAUTHORS CHANGELOG.md configure GOVERNANCE.md node.gyp testbenchmark CODE_OF_CONDUCT.md CONTRIBUTING.md lib node.gypi toolsBSDmakefile COLLABORATOR_GUIDE.md deps LICENSE README.md vcbuild.bat

Trin 2: forståelse af programmets byggesystem

vi taler normalt om “kompilering af kilderne”, men kompileringen er kun en af de faser, der kræves at producere et arbejdsprogram fra sin kilde. Et build-system er et sæt værktøjer og fremgangsmåder, der bruges til at automatisere og formulere de forskellige opgaver for at opbygge programmet helt ved blot at udstede få kommandoer.

hvis konceptet er enkelt, er virkeligheden noget mere kompliceret. Fordi forskellige projekter eller programmeringssprog kan have forskellige krav. Eller på grund af programmørens smag. Eller de understøttede platforme. Eller af historisk grund. Eller … eller.. der er en næsten uendelig liste over grunde til at vælge eller oprette et andet byggesystem. Alt det for at sige, at der er mange forskellige løsninger, der bruges derude.NodeJS bruger et GNU-stil build-system, det er et populært valg i open source-samfundet og endnu en gang en god måde at starte din rejse på.

skrivning og tuning af et build-system er en temmelig kompleks opgave, men for “slutbrugeren” Letter GNU-style build-systemer opgaven ved at bruge to værktøjer:configure ogmake.

configure filen er et projektspecifikt script, der kontrollerer destinationssystemkonfigurationen og den tilgængelige funktion for at sikre, at projektet kan bygges og til sidst beskæftiger sig med specifikationerne for den nuværende platform.

en vigtig del af et typisk configure job er at opbygge Makefile. Det er den fil, der indeholder de instruktioner, der kræves for effektivt at opbygge projektet.

make værktøjet er på den anden side et POSIKSVÆRKTØJ tilgængeligt på ethvert unikt system. Det vil læse det projektspecifikke Makefile og udføre de nødvendige operationer for at opbygge og installere dit program.

men som altid har du stadig en vis lempelse i at tilpasse bygningen til dine specifikke behov.

./configure --help

configure -help kommandoen viser dig alle de tilgængelige konfigurationsindstillinger. Endnu en gang er dette meget projektspecifikt. Og for at være ærlig er det nogle gange nødvendigt at grave ind i projektet, før man fuldt ud forstår betydningen af hver konfigurationsindstilling.

men der er mindst en standard GNU Autotools mulighed, som du skal kende:--prefix mulighed. Dette har at gøre med filsystemhierarkiet og det sted, hvor dit program vil blive installeret.

Trin 3: FHS

Linuks-filsystemhierarkiet på en typisk distribution overholder for det meste Filsystemhierarkistandarden (FHS)

denne standard forklarer formålet med de forskellige mapper i dit system: /usr/tmp/var og så videre.

når du bruger GNU Autotools— og de fleste andre byggesystemer— vil standardinstallationsstedet for dit nye program være /usr/local. Hvilket er et godt valg som ifølge FSH ” er/usr / local hierarkiet til brug af systemadministratoren, når du installerer programmer lokalt? Det skal være sikkert at blive overskrevet, når systemprogrammet opdateres. Det kan bruges til programmer og data, der kan deles mellem en gruppe værter, men ikke findes i /usr.”

/usr/local hierarki replikerer på en eller anden måde rodmappen, og du finder der/usr/local/bin for de eksekverbare programmer,/usr/local/lib for bibliotekerne,/usr/local/share for arkitekturuafhængige filer og div-filer, /usr/local/lib så videre.

det eneste problem, når du bruger /usr/local træet til brugerdefineret programinstallation er filerne til alle dine programmer vil blive blandet der. Især efter at have installeret et par programmer, vil det være svært at spore til hvilken fil præcis af /usr/local/bin og /usr/local/lib tilhører hvilket program. Det vil dog ikke medføre noget problem for systemet. Når alt kommer til alt er /usr/bin næsten det samme rod. Men det bliver et problem den dag, du vil fjerne et manuelt installeret program.

for at løse dette problem foretrækker jeg normalt at installere brugerdefinerede programmer i /opt undertræet i stedet. Endnu en gang for at citere FHS:

_ ” / opt er forbeholdt installation af tilføjelsesprogrampakker.

en pakke, der skal installeres i /opt, skal finde sine statiske filer i en separat /opt/<pakke> eller /opt/<provider> katalogtræ, hvor <pakke> er et navn, der beskriver programpakken og <provider> er udbyderens lanana registrerede navn.”_

så vi opretter en underkatalog over /opt specifikt til vores brugerdefinerede NodeJS-installation. Og hvis jeg en dag vil fjerne det program, bliver jeg simpelthen nødt til at fjerne den mappe:

sh$ sudo mkdir /opt/node-v8.1.1sh$ sudo ln -sT node-v8.1.1 /opt/node# What is the purpose of the symbolic link above?# Read the article till the end--then try to answer that# question in the comment section!sh$ ./configure --prefix=/opt/node-v8.1.1sh$ make -j9 && echo ok# -j9 means run up to 9 parallel tasks to build the software.# As a rule of thumb, use -j(N+1) where N is the number of cores# of your system. That will maximize the CPU usage (one task per# CPU thread/core + a provision of one extra task when a process# is blocked by an I/O operation.

alt andet end “ok” efter make kommandoen er afsluttet ville betyde, at der opstod en fejl under byggeprocessen. Da vi kørte en parallel build på grund af -j er det ikke altid let at hente fejlmeddelelsen i betragtning af den store mængde output, der produceres af build-systemet.

i tilfælde af et problem skal du bare genstartemake, men uden-j denne gang. Og fejlen skal vises nær slutningen af udgangen:

sh$ make

endelig, når kompileringen er gået til slutningen, kan du installere dit program til dets placering ved at køre kommandoen:

sh$ sudo make install

og teste det:

sh$ /opt/node/bin/node --versionv8.1.1

B. Hvad hvis tingene går galt, mens du installerer fra kildekode?

det, jeg har forklaret ovenfor, er for det meste det, du kan se på siden “build instruction” i et veldokumenteret projekt. Men i betragtning af denne artikel er målet at lade dig kompilere dit første program fra kilder, det kan være værd at tage sig tid til at undersøge nogle almindelige problemer. Så jeg vil gøre hele proceduren igen, men denne gang fra et nyt og minimalt Debian 9.0-og CentOS 7.0-system, så du kan se de fejl, jeg stødte på, og hvordan jeg løste dem.

fra Debian 9.0 “Stretch”

:~$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node-bash: git: command not found

dette problem er ret nemt at diagnosticere og løse. Bare installer git pakke:

:~$ sudo apt-get install git
:~$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node && echo okok
:~/node$ sudo mkdir /opt/node-v8.1.1:~/node$ sudo ln -sT node-v8.1.1 /opt/node

intet problem her.

:~/node$ ./configure --prefix=/opt/node-v8.1.1/WARNING: failed to autodetect C++ compiler version (CXX=g++)WARNING: failed to autodetect C compiler version (CC=gcc)Node.js configure error: No acceptable C compiler found! Please make sure you have a C compiler installed on your system and/or consider adjusting the CC environment variable if you installed it in a non-standard prefix.

det er klart, at du har brug for en kompilator for at kompilere et projekt. NodeJS bliver skrevet ved hjælp af C++ sprog, vi har brug for en C++ compiler. Her vil jeg installere ‘ g++’, GNU C++ compiler til dette formål:

:~/node$ sudo apt-get install g++:~/node$ ./configure --prefix=/opt/node-v8.1.1/ && echo okok
:~/node$ make -j9 && echo ok-bash: make: command not found

et andet manglende værktøj. Samme symptomer. Samme løsning:

:~/node$ sudo apt-get install make:~/node$ make -j9 && echo okok
:~/node$ sudo make install:~/node$ /opt/node/bin/node --versionv8.1.1

succes!

Bemærk venligst: Jeg har installeret de forskellige værktøjer en efter en for at vise, hvordan man diagnosticerer kompileringsproblemerne og viser dig den typiske løsning til at løse disse problemer. Men hvis du søger efter mere information om emnet eller læser andre tutorials, vil du opdage, at de fleste distributioner har “metapakker”, der fungerer som en paraply til at installere nogle eller alle de typiske værktøjer, der bruges til at kompilere et program. På Debian-baserede systemer vil du sandsynligvis støde på build-essentials-pakken til dette formål. Og på Red-Hat-baserede distributioner vil det være gruppen” udviklingsværktøjer”.

fra CentOS 7.0

 ~]$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node-bash: git: command not found

kommando ikke fundet? Bare installer det ved hjælp af yum pakkehåndtering:

 ~]$ sudo yum install git
 ~]$ git clone --depth 1 \ --branch v8.1.1 \ https://github.com/nodejs/node && echo okok
 ~]$ sudo mkdir /opt/node-v8.1.1 ~]$ sudo ln -sT node-v8.1.1 /opt/node
 ~]$ cd node node]$ ./configure --prefix=/opt/node-v8.1.1/WARNING: failed to autodetect C++ compiler version (CXX=g++)WARNING: failed to autodetect C compiler version (CC=gcc)Node.js configure error: No acceptable C compiler found! Please make sure you have a C compiler installed on your system and/or consider adjusting the CC environment variable if you installed it in a non-standard prefix.

du gætter det: NodeJS er skrevet ved hjælp af C++ – sproget, men mit system mangler den tilsvarende kompilator. Yum til undsætning. Da jeg ikke er en almindelig CentOS-bruger, måtte jeg faktisk søge på internettet det nøjagtige navn på pakken, der indeholder g++ – kompilatoren. Fører mig til den side: https://superuser.com/questions/590808/yum-install-gcc-g-doesnt-work-anymore-in-centos-6-4

 node]$ sudo yum install gcc-c++ node]$ ./configure --prefix=/opt/node-v8.1.1/ && echo okok
 node]$ make -j9 && echo okok
 node]$ sudo make install && echo okok
 node]$ /opt/node/bin/node --versionv8.1.1

succes. Igen.

C. ændring af programmet installeret fra kildekoden

Du kan installere programmet fra kilden, fordi du har brug for en meget specifik version, der ikke er tilgængelig i dit distributionslager, eller fordi du vil ændre programmet for at rette en fejl eller tilføje en funktion. Når alt kommer til alt handler open source om at foretage ændringer. Så jeg vil benytte lejligheden til at give dig en smagsprøve på den magt, du har ved hånden, nu hvor du er i stand til at kompilere dit eget program.

Her vil vi foretage en mindre ændring af kilderne til NodeJS. Og vi vil se, om vores ændring vil blive indarbejdet i den kompilerede version af programmet:

Åbn filen node/src/node.cc i din foretrukne teksteditor (Vim, nano, gedit,…). Og prøv at finde det fragment af kode:

 if (debug_options.ParseOption(argv, arg)) { // Done, consumed by DebugOptions::ParseOption(). } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { printf("%s\n", NODE_VERSION); exit(0); } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { PrintHelp(); exit(0); }

det er omkring linje 3830 i filen. Rediger derefter linjen indeholdende printf for at matche den ene i stedet:

 printf("%s (compiled by myself)\n", NODE_VERSION);

gå derefter tilbage til din terminal. Før du går videre— og for at give dig mere indsigt i kraften bag git-kan du kontrollere, om du har ændret den rigtige fil:

diff --git a/src/node.cc b/src/node.ccindex bbce1022..a5618b57 100644--- a/src/node.cc+++ b/src/node.cc@@ -3828,7 +3828,7 @@ static void ParseArgs(int* argc, if (debug_options.ParseOption(argv, arg)) { // Done, consumed by DebugOptions::ParseOption(). } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {- printf("%s\n", NODE_VERSION);+ printf("%s (compiled by myself)\n", NODE_VERSION); exit(0); } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { PrintHelp();

Du skal se et ” – ” (minustegn) før linjen, som den var før du ændrede den. Og et “+” (plustegn) før linjen efter dine ændringer.

det er nu tid til at kompilere og geninstallere dit program:

make -j9 && sudo make install && echo okok

denne gang er den eneste grund til, at det kan mislykkes, at du har lavet en skrivefejl, mens du ændrer koden. Hvis dette er tilfældet, skal du åbne node/src/node.cc filen i din teksteditor og rette fejlen.

når du har formået at kompilere og installere den nye ændrede NodeJS-version, vil du kunne kontrollere, om dine ændringer faktisk blev indarbejdet i programmet:

:~/node$ /opt/node/bin/node --versionv8.1.1 (compiled by myself)

Tillykke! Du har foretaget din første ændring til et open source-program!

D. lad skallen finde vores brugerdefinerede byggeprogram

Du har måske bemærket, at jeg altid har lanceret mit nyligt kompilerede NodeJS-program ved at angive den absolutte sti til den binære fil.

/opt/node/bin/node

det virker. Men det er mildt sagt irriterende. Der er faktisk to almindelige måder at løse det på.

der er faktisk to almindelige måder at løse det irriterende problem med at specificere den absolutte sti til de binære filer,
men for at forstå dem skal du først vide, at din shell lokaliserer de eksekverbare filer ved kun at kigge efter dem i de mapper, der er angivet af PATH-miljøvariablen.

:~/node$ echo $PATH/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Her på det Debian-system, hvis du ikke udtrykkeligt angiver nogen mappe som en del af et kommandonavn, vil skallen først kigge efter de eksekverbare programmer i /usr/local/bin, så hvis ikke fundet i /usr/bin, så hvis ikke fundet i /bin så hvis ikke fundet i /usr/local/games så hvis ikke fundet i /usr/games, så hvis ikke fundet … vil skallen rapportere en fejl “kommando ikke fundet”.

i betragtning af at vi har to måder at gøre en kommando tilgængelig for skallen: ved at tilføje det til en af de allerede konfigurerede PATH mapper. Eller ved at tilføje den mappe, der indeholder vores eksekverbare fil til PATH.

tilføjelse af et link fra /usr/local/bin

bare kopiering af noden binær eksekverbar fra/opt/node/bin til/usr/local/bin ville være en dårlig ide, da det eksekverbare program ved at gøre det ikke længere kunne lokalisere de andre krævede komponenter, der tilhører/opt/node/ (det er en almindelig praksis for programmel at finde sine ressourcefiler i forhold til sin egen placering).

så den traditionelle måde at gøre det på er ved at bruge et symbolsk link:

:~/node$ sudo ln -sT /opt/node/bin/node /usr/local/bin/node:~/node$ which -a node || echo not found/usr/local/bin/node:~/node$ node --versionv8.1.1 (compiled by myself)

Dette er en enkel og effektiv løsning, især hvis en programpakke er lavet af kun få kendte eksekverbare programmer— da du skal oprette et symbolsk link til hver bruger-invokable kommando. For eksempel, hvis du er bekendt med NodeJS, kender du npm companion ansøgning jeg skal symlink fra /usr/local/bin også. Men jeg lod det til dig som en øvelse.

ændring af stien

først, hvis du prøvede den foregående løsning, skal du fjerne det node symbolske link, der blev oprettet tidligere for at starte fra en klar tilstand:

:~/node$ sudo rm /usr/local/bin/node:~/node$ which -a node || echo not foundnot found

og nu er her den magiske kommando til at ændre din PATH:

:~/node$ export PATH="/opt/node/bin:${PATH}":~/node$ echo $PATH/opt/node/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

simpelthen sagt, jeg erstattede indholdet af PATH miljøvariablen med dets tidligere indhold, men forud for /opt/node/bin. Så som du kan forestille dig det nu, vil skallen først se ind i /opt/node/bin – mappen til eksekverbare programmer. Vi kan bekræfte, at ved hjælp af which kommando:

:~/node$ which -a node || echo not found/opt/node/bin/node:~/node$ node --versionv8.1.1 (compiled by myself)

mens “link” – løsningen er permanent, så snart du har oprettet det symbolske link til /usr/local/binPATH skift er kun effektiv i den nuværende skal. Jeg vil lade dig undersøge, hvordan du foretager ændringer i PATH permanente. Som et tip har det at gøre med din “profil”. Hvis du finder løsningen, tøv ikke med at dele det med de andre læsere ved at bruge kommentarfeltet nedenfor!

E. Sådan fjerner du det nyinstallerede program fra kildekoden

da vores brugerdefinerede kompilerede NodeJS-program sidder helt i mappen /opt/node-v8.1.1, kræver fjernelse af programmet ikke mere indsats end at bruge kommandoen rm til at fjerne denne mappe:

sudo rm -rf /opt/node-v8.1.1

pas på: sudo og rm -rf er en farlig cocktail! Kontroller altid din kommando to gange, før du trykker på “enter” – tasten. Du vil ikke have nogen bekræftelsesmeddelelse og ingen genopretter hvis du fjerner den forkerte mappe…

så hvis du har ændret din PATH, bliver du nødt til at vende tilbage disse ændringer, hvilket slet ikke er kompliceret.

og hvis du har oprettet links fra /usr/local/bin du bliver nødt til at fjerne dem alle:

:~/node$ sudo find /usr/local/bin \ -type l \ -ilname "/opt/node/*" \ -print -delete/usr/local/bin/node

vent? Hvor var afhængigheden helvede?

som en sidste kommentar, hvis du læser om kompilering af dit eget brugerdefinerede program, har du måske hørt om afhængighedshelvet. Dette er et kaldenavn for den irriterende situation, hvor før du er i stand til at kompilere et program, skal du først kompilere en forudsætning bibliotek, som igen kræver et andet bibliotek, der kan i sin tur være uforenelig med nogle andre programmer, du allerede har installeret.

en del af jobbet for pakkevedligeholdere i din distribution er faktisk at løse dette afhængighedshelvede og sikre, at de forskellige programmer i dit system bruger kompatible biblioteker og installeres i den rigtige rækkefølge.

til denne artikel valgte jeg med vilje at installere NodeJS, da det næsten ikke har afhængigheder. Jeg sagde “næsten”, fordi det faktisk har afhængigheder. Men kildekoden af disse afhængigheder er til stede i kilden repository af projektet (i node/deps undermappe), så du ikke behøver at hente og installere dem manuelt før hånd.

Related Posts

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *