Reputation: 1651
Trying to do a simple clojure program without that includes a function defined in another file. It is unable to find the file in the same directory.
helloInclude
src
main.clj
importer.clj
main.clj
(ns main
(:gen-class)
(:require [importer]))
(defn -main
[& args]
(println "Hello, World!"))
(-main)
(println (func 5 6))
importer.clj
(ns importer
(:gen-class))
(defn func
[a b]
(+ a b 1))
Executed from within the src
directory with:
java -jar "Path\To\Clojure\clojure-1.8.0\clojure-1.8.0.jar" -i main.clj
Returns error:
Exception in thread "main" java.io.FileNotFoundException: Could not locate importer__init.class or importer.clj on classpath., compiling:(C:\Users\jamesjenkinson\Clojure\helloInclude\src\main.clj:1:1)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$init_opt.invokeStatic(main.clj:277)
at clojure.main$init_opt.invoke(main.clj:277)
at clojure.main$initialize.invokeStatic(main.clj:308)
at clojure.main$null_opt.invokeStatic(main.clj:342)
at clojure.main$null_opt.invoke(main.clj:339)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.io.FileNotFoundException: Could not locate import__init.class or import.clj on classpath.
at clojure.lang.RT.load(RT.java:456)
at clojure.lang.RT.load(RT.java:419)
at clojure.core$load$fn__5677.invoke(core.clj:5893)
at clojure.core$load.invokeStatic(core.clj:5892)
at clojure.core$load.doInvoke(core.clj:5876)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5697)
at clojure.core$load_one.invoke(core.clj:5692)
at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
at clojure.core$load_lib.invokeStatic(core.clj:5736)
at clojure.core$load_lib.doInvoke(core.clj:5717)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:648)
at clojure.core$load_libs.invokeStatic(core.clj:5774)
at clojure.core$load_libs.doInvoke(core.clj:5758)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:648)
at clojure.core$require.invokeStatic(core.clj:5796)
at clojure.core$require.doInvoke(core.clj:5796)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at src.main$eval3$loading__5569__auto____4.invoke(main.clj:1)
at src.main$eval3.invokeStatic(main.clj:1)
at src.main$eval3.invoke(main.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.eval(Compiler.java:6916)
at clojure.lang.Compiler.load(Compiler.java:7379)
... 14 more
Also tried explicitly calling classpath to be the current directory with:
java -classpath . -jar "Path\To\Clojure\clojure-1.8.0\clojure-1.8.0.jar" -i main.clj
I am unable to use Leiningen for this. How should I properly reference the file?
Edit: Changed namespaces to top level.
Upvotes: 3
Views: 1499
Reputation: 1357
I hope I'm getting you correctly and we have the similar problem which I seem to have solved. My current directory structure is (forgive the humorous nature of things):
.
├── chikaka
│ ├── main.clj
│ └── tools
│ └── dog.clj
├── core.clj
└── deps.edn
The key for me was deps.edn
file which had the following contents:
{:paths ["."]}
Source: https://clojure.org/reference/deps_and_cli#_paths
When you add paths
to the deps file, each is added the to glorious CLASSPATH that Java likes so much. Then you will have requires like this working for example:
(ns chikaka.main
(:require [chikaka.tools.dog :refer [bark]]))
Upvotes: 1
Reputation: 20194
require
only finds files that are under your classpath. If you want to be able to use require, the path to your code relative to the classpath has to match the package and name of the namespace. The -cp
arg to java can add directories to the classpath, and the current directory is not implicitly in the classpath.
If the file is just import
it must be directly in the top directory, and its package must be changed so it is a top level namespace. To require it with its current location and package, you must use src.import
instead of import
.
Also, top level namespaces are not recommended.
Finally, the proper option to run a -main
is -m
.
+$ ls
import.clj main.clj
+$ cat import.clj
(ns import)
(defn foo
[]
(println "hello"))
+$ cat main.clj
(ns main
(:require [import])
(:gen-class))
(defn -main
[& args]
(import/foo))
:$ java -cp ~/bin/clojure.jar:. clojure.main -m main
hello
Upvotes: 0