【问题标题】:A Clojure project building several related small tools一个构建几个相关小工具的 Clojure 项目
【发布时间】:2017-03-15 23:37:39
【问题描述】:

我正在开发一个具有通用功能库的 Clojure 项目,但我想从许多小型命令行工具中使用这个库。

我们称它们为 tool1、tool2、tool3。

这些工具中的每一个都封装了库的大部分内容。

我应该如何组织我的 Clojure 源代码以及我的 project.clj 文件中需要什么?

现在我的代码在

src/projectname/core.cljc ; a default executable

cljc/projectname/lib1.cljc 
cljc/projectname/lib2.cljc ; cljc because I want to use from clojurescript too later

等等

我应该把tool1.clj、tool2.clj等放在哪里?

我的项目是

(defproject 
   ....
     :aot [projectname.core]
     :main project.core )

我需要输入什么来告诉它我想制作三个独立的可执行工具?

【问题讨论】:

    标签: clojure leiningen


    【解决方案1】:

    你可以这样做using the lein-exec library

    首先,像这样(或类似)设置 ~/bin:

    > ls -ldF  ~/bin/l*
    lrwxrwxrwx 1 alan alan 26 Oct 31 08:29 /home/alan/bin/lein -> /home/alan/cool/tools/lein*
    lrwxrwxrwx 1 alan alan 31 Oct 31 08:29 /home/alan/bin/lein-exec -> /home/alan/cool/tools/lein-exec*
    lrwxrwxrwx 1 alan alan 33 Oct 31 08:29 /home/alan/bin/lein-exec-p -> /home/alan/cool/tools/lein-exec-p*
    

    我有指向实际文件的符号链接,但您可以直接复制它们。当然,请确保 ~/bin 在您的路径中。

    然后只需编写一个可执行的 clojure “脚本”,如下所示。当然,它必须是可执行的:

    > ls -l say-hello 
    -rwxrwxr-x 1 alan alan 212 Nov  2 09:10 say-hello
    
    > cat say-hello
    
    #!/usr/bin/env lein-exec
    
    (defn say-hello [name] 
      (println (format "Hello from the command line, %s!" name)))
    
    (do 
      ; *command-line-args* = <cmd> <arg1> <arg2> ...
      (say-hello (second *command-line-args*)))
    

    我们走吧!

    > ./say-hello buckaroo    
    Hello from the command line, buckaroo!
    

    至于项目组织,我会从简单开始(就像任何项目一样!)。也许只从 1 个源文件开始,每个“脚本”都有不同的功能作为入口点。随着项目的发展,您将更容易看到您想在哪里划分不同的命名空间/文件。

    更新

    你也可以使用lein uberjar,然后直接调用java:

    (ns clj.core
      (:gen-class))
    
    (defn say-hello [name] 
      (println (format "Hello from the command line, %s!" name)))
    
    (defn -main [& args]
      (say-hello (first args)))
    
    > lein uberjar
    Compiling 1 source files to /home/alan/clj/target/uberjar/classes
    Compiling clj.core
    Created /home/alan/clj/target/uberjar/clj-0.1.0-SNAPSHOT.jar
    Created /home/alan/clj/target/uberjar/clj-0.1.0-SNAPSHOT-standalone.jar
    
    > java -jar /home/alan/clj/target/uberjar/clj-0.1.0-SNAPSHOT-standalone.jar pardner
    Hello from the command line, pardner!
    

    所以只需将java 命令放入shell 脚本即可启动。另请注意,:gen-class 是必需的,args 不再包含脚本名称。当然,您必须同时部署脚本文件和 uberjar。

    更新 #2

    你也可以使用这个版本:

    来源:

    (ns clj.core
      (:gen-class))
    
    (defn say-howdy [args]
      (println (format "Howdy, %s!" (first args))))
    
    (defn give-reply [args]
      (println (format "Back at ya, %s!" (first args))))
    
    (defn -main [& args]
      (let [method-name  (first  args)
            message      (second args) ]
        (cond 
          (= method-name "say-howdy" ) (say-howdy  (rest args))
          (= method-name "give-reply") (give-reply (rest args))
          :else (throw (NoSuchMethodException. (str "clj.core: invalid method='" method-name \')))))
    )
    

    脚本:

    > ls -l say*
    -rwxrwxr-x 1 alan alan 212 Nov  2 16:24 say-hello
    -rwxrwxr-x 1 alan alan 104 Nov  2 16:35 say-howdy
    -rwxrwxr-x 1 alan alan 105 Nov  2 16:35 say-reply
    
    > cat ./say-howdy
    #!/bin/bash
    java -jar /home/alan/clj/target/uberjar/clj-0.1.0-SNAPSHOT-standalone.jar say-howdy pardner
    
    > cat ./say-reply 
    #!/bin/bash
    java -jar /home/alan/clj/target/uberjar/clj-0.1.0-SNAPSHOT-standalone.jar give-reply $1
    

    运行工具:

    ~/clj > ./say-howdy 
    Howdy, pardner!
    
    ~/clj > ./say-reply
    Back at ya, null!
    
    ~/clj > ./say-reply buckaroo
    Back at ya, buckaroo!
    

    让脚本更智能并决定如何部署 N 个脚本和单个 JAR 文件留给读者作为练习。

    ;)

    【讨论】:

    • 这很有趣。但不是我想要的。这样做比制作可执行文件有优势吗?我认为这需要在 USER(不仅仅是开发人员)机器上设置 lein 等。
    • 感谢您的更新。但是每个工具我都需要一个 uberjar 吗? (我注意到当你运行它时,你没有在 jar 中指定特定的文件名)。如果是这样,我应该在 project.clj 中放入什么来制作多个 uberjar?
    • 感谢@alan thompson 更新 #2。另一个有用的解决方法。但是我是否正确地假设我真正想做的事情......让 Lein 从一个项目中创建多个单独的可执行文件......由于某种原因无法完成?
    • Lein 只创建编译后的 java 代码(*.class 和 *.jar 文件)。插件lein-exec 将即时编译和执行 clojure,但是您需要同时分发“脚本”文件和 lein+java。以上方式需要分发脚本文件和uberjar+java。
    猜你喜欢
    • 2017-02-19
    • 2011-10-10
    • 2023-03-09
    • 2015-07-29
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    相关资源
    最近更新 更多