2013-11-01 18 views
5

Napisałem program w Clojure i chciałbym go wykonać w linii poleceń bez specyficznego wywoływania java w linii poleceń (np. java -jar). Chcę jednego pliku wykonywalnego, takiego jak myprogram, który akceptuje dowolne argumenty i uruchamia mój program. Oto kilka rzeczy, które mogą ułatwić to:Jak utworzyć plik wykonywalny wiersza poleceń w Clojure

  1. Można założyć, że Java jest zainstalowana i że na ścieżce znajduje się java.
  2. Chociaż rozwiązanie działające w systemie Windows byłoby wielkim plusem, można założyć, że wszystko to dzieje się w systemie operacyjnym podobnym do UNIX, takim jak Mac OS X lub Ubuntu.
  3. Można wywołać Javę w jakimś skrypcie.
  4. Można używać innych języków, takich jak Ruby, Python lub Perl, które użytkownik zainstalował lub nie. All-bash byłoby fajne, ponieważ mogę założyć, że ludzie to mają.
  5. Jest OK, jeśli muszę użyć jakiegoś narzędzia do zbudowania binarnego, który będzie wykonywany, ale nie szukam pliku .app lub .exe, który oczekuje działania z interfejsem GUI (na przykład aplikacja Oracle Oracle nie jest tym, czego szukam tutaj).

Dostałem się dość daleko na tej ścieżce jednym podejściem, ale muszę się zastanowić, czy istnieje lepszy sposób.

tylko w celach: Co Próbowałem już

opiszę moje podejście poniżej, ale żadnych odpowiedzi nie trzeba stosować to podejście w ogóle.

Co mam zrobić, to stworzyć plugin Lein nazwie makescript który generuje uberjar, base64 koduje je i umieszcza go wewnątrz skryptu Ruby w tzw zmiennej heredoc, tak:

# ...ruby script... 
BASE64_JAR = <<-JAR_BOUNDARY 
# [...base64 encoded file here...] 
JAR_BOUNDARY 

Ty powinien wtedy móc uruchomić skrypt ruby. Spowoduje to zmianę zmiennej BASE64_JAR, jej kodowanie, umieszczenie w pliku tymczasowym i wykonanie go przez wywołanie java -jar <filename>.

Problem mam z tego podejścia jest to, że base64 biblioteki Ruby i clojure.data.codec.base64 biblioteki Clojure zdają się produkować różne struny do reprezentowania słoika, a ciąg zakodowany przez Clojure nie dekodować do oryginalnego pliku, jeśli mogę użyć Ruby . Może to mieć coś wspólnego z kodowaniem samych łańcuchów (może być związanych z UTF-8) pomiędzy tymi dwoma językami. Oto Repl/IRB sesje, które zilustrują odłączyć:

repl=> (def jar-contents (slurp "../target/myproj-0.1.0-SNAPSHOT-002-standalone.jar")) 
repl=> (count jar-contents) ;; => 9433328 
repl=> (def a-str (String. (clojure.data.codec.base64/encode (.getBytes jar-contents)) "UTF-8")) 
repl=> (count a-str)  ;; => 23265576 

irb> f = File.open("target/pwgen-0.1.0-SNAPSHOT-002-standalone.jar", "r").read() 
irb> p f.length # => 9657639 
irb> b = Base64.encode64(f) 
irb> p b.length # => 13564973 

Uwaga surowe rozmiary są blisko, ale nie takie same, ale zakodowane wersje są bardzo różne.

Chociaż jest to zagadkowe i chciałbym się dowiedzieć, dlaczego tak się dzieje, myślę, że mogę ominąć problem poprzez napisanie po prostu konstruktora uberjara i przekazanie ścieżki do innego skryptu Ruby, który następnie będzie kodował base64 (i później dekodowanie, również przy użyciu Ruby) autonomicznego JAR. Pozostaje pytanie: czy istnieje lepszy, prostszy sposób? Czy brakuje mi czegoś oczywistego, czy jest to naprawdę tak trudne, jak się wydaje?

Odpowiedz

2

Wygląda na to, że próbujesz uruchomić aplikację ze skryptu, używając czystszej składni.To może być najłatwiej zrobić tak:

utworzyć nowy skrypt bash nazwie myprogram:

#!/usr/bin/bash 
# pass whatever command line args you have down through the script 
java -jar myjar.jar 

nadać mu uprawnienia do wykonywania

chmod +x myprogram 

uruchomić go

./myprogram (with whatever params) 

Jeśli chcesz się pozbyć ./ musisz przenieść rzeczy w pobliżu, więc skrypt zostanie odebrany przez Twój PATH.

Pamiętaj, że jesteś nie stworzenie platformy specyficzne binarny plik wykonywalny. Mogłoby to zniszczyć cel używania jvm w pierwszej kolejności. Po prostu wywoływałbyś to przez dodatkową warstwę pośrednią.

+0

Problem polega na tym, że wymaga mnie mieć osobny plik jar gdzieś. Przypuszczam, że jest to możliwe, ale jest trochę nieprzyjemne. Jeśli chodzi o binarną platformę, to myślę, że większość dużych aplikacji, które używają JVM, dokładnie to robi - myśląc o Eclipse lub jEdit na przykład. W końcu jednak wszystko, czego chcę, to samodzielny skrypt z linii poleceń. –

+0

@door_number_three Masz rację - dzięki takiemu podejściu będziesz musiał odwołać się do słoika w systemie hosta. Może mógłbyś napisać skrypt instalacyjny, który umieści słoik tam, gdzie go potrzebujesz, a następnie połączyć go ze skryptem. – yamafontes

Powiązane problemy