Introduksjon til Leiningen for Clojure

1. Introduksjon

Leiningen er et moderne byggesystem for våre Clojure-prosjekter. Det er også skrevet og konfigurert helt i Clojure.

Det fungerer på samme måte som Maven, og gir oss en deklarativ konfigurasjon som beskriver prosjektet vårt, uten å måtte konfigurere nøyaktige trinn som skal utføres.

La oss hoppe inn og se hvordan vi kommer i gang med Leiningen for å bygge våre Clojure-prosjekter.

2. Installere Leiningen

Leiningen er tilgjengelig som frittstående nedlasting, så vel som fra et stort antall pakkeforvaltere for forskjellige systemer.

Frittstående nedlastinger er tilgjengelige for Windows så vel som for Linux og Mac. I alle tilfeller laster du ned filen, gjør den kjørbar om nødvendig, og så er den klar til bruk.

Første gang skriptet kjøres, vil det laste ned resten av Leiningen-applikasjonen, og deretter blir dette lagret fra dette punktet fremover:

$ ./lein Laster ned Leiningen til /Users/user/.lein/self-installs/leiningen-2.8.3-standalone.jar nå ... ..... Leiningen er et verktøy for å jobbe med Clojure-prosjekter. Flere oppgaver er tilgjengelige: ..... Kjør `lein help $ TASK` for detaljer. .....

3. Opprette et nytt prosjekt

Når Leiningen er installert, kan vi bruke den til å lage et nytt prosjekt ved å påkalle lein ny.

Dette oppretter et prosjekt ved hjelp av en bestemt mal fra et sett med alternativer:

  • app - Brukes til å lage et program
  • misligholde - Brukes til å lage en generell prosjektstruktur, typisk for biblioteker
  • plugg inn - Brukt til å lage en Leiningen Plugin
  • mal - Brukt til å lage nye Leiningen-maler for fremtidige prosjekter

For eksempel, for å lage en ny applikasjon kalt “mitt-prosjekt” vil vi utføre:

$ ./lein ny app my-project Generere et prosjekt kalt my-project basert på 'app'-malen.

Dette gir oss et prosjekt som inneholder:

  • En byggedefinisjon - prosjekt.clj
  • En kildekatalog - src - inkludert en innledende kildefil - src / my_project / core.clj
  • En testkatalog - test - inkludert en innledende testfil - test / my_project / core_test.clj
  • Noen ekstra dokumentasjonsfiler - README.md, LISENS, CHANGELOG.md og doc / intro.md

Når vi ser på byggdefinisjonen vår, ser vi at den forteller oss hva vi skal bygge, men ikke hvordan vi skal bygge den:

(defprojekt mitt prosjekt "0.1.0-SNAPSHOT": beskrivelse "FIXME: skriv beskrivelse": url "//eksempel.com/FIXME": lisens {: navn "EPL-2.0 ELLER GPL-2.0-eller-senere MED Classpath -exception-2.0 ": url" //www.eclipse.org/legal/epl-2.0/ "}: avhengigheter [[org.clojure / clojure" 1.9.0 "]]: hoved ^: hopp over alt mitt prosjekt .core: target-path "target /% s": profiler {: uberjar {: aot: all}})

Dette forteller oss:

  • Detaljene i prosjektet består av prosjektnavn, versjon, beskrivelse, hjemmeside og lisensdetaljer.
  • Hovednavnområdet som skal brukes når programmet kjøres
  • Listen over avhengigheter
  • Målet banen du vil bygge utdataene i
  • En profil for å bygge en uberjar

Legg merke til at hovedkildens navneområde er mitt-prosjekt.core, og finnes i filen my_project / core.clj. Det frarådes i Clojure å bruke enkeltsegment-navneområder - tilsvarende klasser på toppnivå i et Java-prosjekt.

I tillegg genereres filnavnene med understreker i stedet for bindestreker fordi JVM har noen problemer med bindestrek i filnavn.

Den genererte koden er ganske enkel:

(ns my-project.core (: gen-class)) (defn -hoved "Jeg gjør ikke veldig mye ... ennå." [& args] (println "Hello, World!"))

Legg også merke til at Clojure bare er en avhengighet her. Dette gjør det trivielt å skrive prosjekter ved hjelp av hvilken versjon av Clojure-bibliotekene som er ønsket, og spesielt å ha flere forskjellige versjoner som kjører på samme system.

Hvis vi endrer denne avhengigheten, får vi den alternative versjonen i stedet.

4. Bygging og løping

Prosjektet vårt er ikke verdt mye hvis vi ikke kan bygge det, kjøre det og pakke det opp for distribusjon, så la oss se på det neste.

4.1. Starte en REPL

Når vi har et prosjekt, kan vi starte en REPL inne i det ved hjelp av lein repl. Dette vil gi oss en REPL som har alt i prosjektet allerede tilgjengelig på klassestien - inkludert alle prosjektfiler samt alle avhengigheter.

Det starter oss også i det definerte hovednavnerommet for prosjektet vårt:

$ lein repl nREPL-server startet på port 62856 på host 127.0.0.1 - nrepl: //127.0.0.1: 62856 [] REPL-y 0.4.3, nREPL 0.5.3 Clojure 1.9.0 Java HotSpot (TM) 64-biters server VM 1.8.0_77-b03 Dokumenter: (doc-funksjon-navn-her) (finn-doc "del-av-navn-her") Kilde: (kilde-funksjon-navn-her) Javadoc: (javadoc java-objekt-eller- klasse-her) Avslutt: Control + D eller (exit) eller (quit) Resultater: Lagret i vars * 1, * 2, * 3, et unntak i * e my-project.core => (-main) Hello, World ! null

Dette utfører funksjonen -hoved i det nåværende navnerommet, som vi så ovenfor.

4.2. Kjører applikasjonen

Hvis vi jobber med et applikasjonsprosjekt - laget med lein ny app - deretter vi kan ganske enkelt kjøre applikasjonen fra kommandolinjen. Dette gjøres ved hjelp av lein run:

$ lein run Hello, World!

Dette vil utføre funksjonen som kalles -hoved i navneområdet definert som :hoved i vår prosjekt.clj fil.

4.3. Å bygge et bibliotek

Hvis vi jobber med et bibliotekprosjekt - laget med lein ny standard - deretter vi kan bygge biblioteket til en JAR-fil for inkludering i andre prosjekter.

Vi har to måter vi kan oppnå dette på lein jar eller lein installere. Forskjellen er rett og slett hvor JAR-filen for utgangen er plassert.

Hvis vi bruker lein jar da vil den plassere den i det lokale mål katalog:

$ lein jar opprettet /Users/user/source/me/my-library/target/my-library-0.1.0-SNAPSHOT.jar

Hvis vi bruker lein installere, så vil den bygge JAR-filen, generere en pom.xml fil og plasser deretter de to i det lokale Maven-depotet (vanligvis under .m2 / depot i brukerens hjemmekatalog)

$ lein install opprettet /Users/user/source/me/my-library/target/my-library-0.1.0-SNAPSHOT.jar Skrev /Users/user/source/me/my-library/pom.xml Installert jar og pom i lokal repo.

4.4. Å bygge en Uberjar

Hvis vi jobber med et søknadsprosjekt, Leiningen gir oss muligheten til å bygge det som kalles en uberjar. Dette er en JAR-fil som inneholder selve prosjektet og alle avhengigheter og er konfigurert slik at det kan kjøres som det er.

$ lein uberjar Kompilering av mitt prosjekt.core Opprettet /Users/user/source/me/my-project/target/uberjar/my-project-0.1.0-SNAPSHOT.jar Opprettet / Brukere / bruker / kilde / meg / min- prosjekt / mål / uberjar / mitt-prosjekt-0.1.0-SNAPSHOT-frittstående.jar

Filen mitt-prosjekt-0.1.0-SNAPSHOT.jar er en JAR-fil som inneholder nøyaktig det lokale prosjektet, og filen my-project-0.1.0-SNAPSHOT-standalone.jar inneholder alt som trengs for å kjøre applikasjonen.

$ java -jar target / uberjar / my-project-0.1.0-SNAPSHOT-standalone.jar Hello, World!

5. Avhengigheter

Selv om vi selv kan skrive alt som trengs for prosjektet vårt, er det generelt bedre å bruke arbeidet som andre allerede har gjort på våre vegne. Vi kan gjøre dette ved å ha prosjektet vårt avhengig av disse andre bibliotekene.

5.1. Legge til avhengigheter i prosjektet vårt

For å legge til avhengigheter i prosjektet vårt, må vi legge dem riktig til vårt prosjekt.clj fil.

Avhengigheter er representert som en vektor som består av navnet og versjonen av den aktuelle avhengigheten. Vi har allerede sett at Clojure selv er lagt til som en avhengighet, skrevet i formen [org.clojure / clojure “1.9.0”].

Hvis vi vil legge til andre avhengigheter, kan vi gjøre det ved å legge dem til vektoren ved siden av : avhengigheter nøkkelord. For eksempel hvis vi vil være avhengige av clj-json vi oppdaterer filen:

 : avhengigheter [[org.clojure / clojure "1.9.0"] [clj-json "0.5.3"]]

Når vi er ferdig, hvis vi starter REPL - eller noen annen måte å bygge eller kjøre prosjektet på - vil Leiningen sørge for at avhengighetene lastes ned og er tilgjengelige på klassestien.:

$ lein repl Henter clj-json / clj-json / 0.5.3 / clj-json-0.5.3.pom fra clojars Henter clj-json / clj-json / 0.5.3 / clj-json-0.5.3.jar fra clojars nREPL-server startet på port 62146 på vert 127.0.0.1 - nrepl: //127.0.0.1: 62146 REPL-y 0.4.3, nREPL 0.5.3 Clojure 1.9.0 Java HotSpot (TM) 64-biters server VM 1.8.0_77 -b03 Docs: (doc-funksjon-navn-her) (finn-doc "del-av-navn-her") Kilde: (kilde-funksjon-navn-her) Javadoc: (javadoc java-objekt-eller-klasse-her) Avslutt: Control + D eller (exit) eller (quit) Resultater: Lagret i vars * 1, * 2, * 3, et unntak i * e my-project.core => (krever '(clj-json [core: as json])) null my-project.core => (json / generere-streng {"foo" "bar"}) "{\" foo \ ": \" bar \ "}" my-project.core =>

Vi kan også bruke dem fra innsiden av prosjektet vårt. For eksempel kan vi oppdatere den genererte src / my_project / core.clj filen som følger:

(ns my-project.core (: gen-class)) (require '(clj-json [core: as json])) (defn -main "Jeg gjør ikke veldig mye ... ennå." [& args] (println (json / generere-streng {"foo" "bar"})))

Og å kjøre det vil gjøre akkurat som forventet:

$ lein run {"foo": "bar"}

5.2. Finne avhengigheter

Ofte kan det være vanskelig å finne avhengighetene vi ønsker å bruke i prosjektet vårt. Leiningen kommer med en innebygd søkefunksjonalitet for å gjøre dette lettere. Dette gjøres ved hjelp av leinsøk.

For eksempel kan vi finne våre JSON-biblioteker:

$ leinsøk json Søker i sentral ... [com.jwebmp / ​​json "0.63.0.60"] [com.ufoscout.coreutils / json "3.7.4"] [com.github.iarellano / json "20190129"] ... .. Søker i kappe ... [cheshire "5.8.1"] JSON og JSON SMILE-koding, raskt. [json-html "0.4.4"] Gi JSON og få en DOM-node med en menneskelig representasjon av den JSON [ring / ring-json "0.5.0-beta1"] Ring mellomvare for håndtering av JSON [clj-json "0.5. 3 "] Rask JSON-koding og dekoding for Clojure via Jackson-biblioteket. .....

Dette søker i alle arkivene som prosjektet vårt jobber med - i dette tilfellet Maven Central og Clojars. Deretter returnerer den nøyaktige strengen du vil legge inn i vår prosjekt.clj filen og, hvis tilgjengelig, beskrivelsen av biblioteket.

6. Testing av prosjektet vårt

Clojure har innebygd støtte for enhetstesting av applikasjonen vår, og Leiningen kan utnytte dette for våre prosjekter.

Vårt genererte prosjekt inneholder testkode i test katalog, ved siden av kildekoden i src katalog. Den inkluderer også en enkelt, mislykket test som standard - funnet i test / my_project / core-test.clj:

(ns my-project.core-test (: krever [clojure.test: refer: all] [my-project.core: refer: all])) (deftest a-test (testing "FIXME, I fail." (er (= 0 1))))

Dette importerer mitt-prosjekt.core navneområdet fra prosjektet vårt, og clojure.test navneområdet fra kjerne-språket. Vi definerer deretter en test med dyktig og testing ringer.

Vi kan umiddelbart se navnene på testen, og det faktum at den bevisst er skrevet for å mislykkes - det hevder det 0 == 1.

La oss kjøre dette ved hjelp av lein test kommando, og umiddelbart se testene kjøre og mislykkes:

$ lein test lein test my-project.core-test lein test: bare my-project.core-test / a-test FAIL i (a-test) (core_test.clj: 7) FIXME, jeg mislykkes. forventet: (= 0 1) faktisk: (ikke (= 0 1)) Ran 1-tester som inneholder 1 påstander. 1 feil, 0 feil. Testene mislyktes.

Hvis vi i stedet fikser testen, endrer vi den for å hevde det 1 == 1 i stedet, så får vi en passerende melding i stedet:

$ lein test lein test my-project.core-test Ran 1 tester som inneholder 1 påstander. 0 feil, 0 feil.

Dette er en mye mer kortfattet produksjon, og viser bare det vi trenger å vite. Dette betyr at når det er feil, skiller de seg umiddelbart ut.

Hvis vi vil, kan vi også kjøre en bestemt delmengde av testene. Kommandolinjen gjør det mulig å oppgi et navneområde, og bare tester i dette navneområdet utføres:

$ lein test my-project.core-test lein test my-project.core-test Ran 1-tester som inneholder 1 påstander. 0 feil, 0 feil. $ lein test my-project.unknown lein test my-project.unknown Ran 0 tester som inneholder 0 påstander. 0 feil, 0 feil.

7. Oppsummering

Denne artikkelen har vist hvordan du kommer i gang med Leiningen-bygningsverktøyet, og hvordan du bruker det til å administrere våre Clojure-baserte prosjekter - både kjørbare applikasjoner og delte biblioteker.

Hvorfor ikke prøve det på neste prosjekt og se hvor godt det kan fungere.


$config[zx-auto] not found$config[zx-overlay] not found