Should I create a local repository to change the dependencies of a dependency in my project?
I have a clojure project that is using docjure. docjure contains a dependency on poi 3.6.
Because of a bug in generated Excel files I am reading, I have a local version of poi 3.8 that I hacked to workaround the bug.
It's easy enough to stick my poi 3.8 jars into my projects lib/ directory so that my project will run ok at the repl.
But, lein deps (or jar and uberjar) happily cleans the lib/ directory and reinstalls the 3.6 versions of poi, breaking my build.
I think the probable solution is two-fold:
1 - put my hacked poi 3.8 into a local repository
2 - create my own local copy of docjure and update it's dependencies to point to that local repository.
I am looking for confirmation that this is the "right thing" to do in this case or someone to point out that it is much easier to just do something else.
It is worth reading Leiningen's Repeatability wiki page if you haven't already. To quote part of it:
If the code is public, you should open a bug report with upstream to get them to publish it in a public repository like Clojars, Sonatype, or Maven Central, depending on the project. If they are resistant or too slow it's always possible to publish "Clojars forks"; see lein help deploying for further details there.
The ultimate solution is to try and get your changes pushed upstream. Then you can depend on the version you need, and I think Leiningen will prefer that version if it's higher than the transitive version.
Another option might be to include your jar in a safe (checked-in) directory. Then write a plugin that can hook into a built-in task and copy the jar to your lib directory for you. I really don't know if this will be successful, but it's worth looking into.
Related
I have multiple, separate leiningen projects that ostensibly could depend on one-another.
Example:
~/projects/mywebapp (my own project)
~/projects/noir (a clone of the github repo)
~/projects/clojureql (a clone of the github repo)
I want to have them all compiled into the same JVM at the same time. I would like to run the git repos bleeding edge (pulling new commits/making my own commits) and not have to run lein jar or lein deps and certainly not have to restart the VM if I change any of the projects.
Here's a use case:
After running lein swank, from within emacs, I connect to the repl and compile a file from mywebapp (with C-c-k), which requires a file from noir. It finds the version of the file in my projects directory. Later, I open that file, edit it, and compile it (with C-c-k).
Note that I'm not asking for auto-compiling when I do git pull. I just don't want to have to restart the JVM or do lengthy jar compiling processes.
Is this possible in leiningen? How can I set this up?
Does this question from the Lein FAQ help?
Q: I want to hack two projects in parallel, but it's annoying to switch between them.
A: Use a feature called checkout dependencies. If you create a directory called checkouts in your project root and symlink some other
project roots into it, Leiningen will allow you to hack on them in
parallel. That means changes in the dependency will be visible in the
main project without having to go through the whole
install/switch-projects/deps/restart-repl cycle. Note that this is not
a replacement for listing the project in :dependencies; it simply
supplements that for tighter change cycles.
If you're already using swank, you don't need lein checkout dependencies. You can just C-c C-k your project (which will load the jarred versions of noir/whatever), and then browse to your local version of noir and C-c C-k that as well. Swank happily sends all the code to your repl, and the jvm never need know that it came from a different place!
I can only recommend this for smallish changes though, because I think if you compile noir.core, which depends on (say) noir.internal, clojure will load the jarred version of noir.internal even while you compile the local version of noir.core. Even so, it's a handy trick in general.
Say I'm using a library in a leiningen project, hosted on Clojars. And I run into a bug. I fork the project on Github, and fix the bug. Now what?
What's the most appropriate way to use my version of the library in my leiningen project?
P.S. I'm coming from the Ruby world, so I've obviously got Bundler on the mind...
If you only want your modified version available locally, you can follow Arthur's process up to the "Test my program" step. This is fine if you're working on an application which you'll package together with its dependencies for deployment (with lein uberjar, say). You might also want to use Leiningen's checkouts feature to work on your main project and the modified library in parallel (documented in Leiningen's tutorial -- link to the version from the current 2.2.0 release).
If you want your modified version to be accessible in a public Maven repository, the accepted thing to do (indeed, encouraged for this specific use case and no other) is to release a version of the project with the original artefact id and a group id of org.clojars.{your-clojars-account-name}.
For example, if you wanted to release your own version of project foo with (defproject foo "upstream-version" ...) in its project.clj, you'd change its defproject form to (defproject org.clojars.kendallb/foo "your-version" ...) before release. Then you could depend on [org.clojars.kendallb/foo "your-version"] in your projects.
This way there won't be any conflict either with the original artefact id or any other forks.
As for getting your change merged upstream, Arthur's process is perfectly reasonable.
my process:
Fork the project on github
Change the version from project-0.1.2-SNAPSHOT to project-0.1.2-arthur-SNAPSHOT in project.clj of the dependency
Fix the bug
Run "lein install" to add my fork to my local repo
cd to my project (the one using the dependency)
Change my porject.clj to depend on project-0.1.2-arthur-SNAPSHOT
Test my program
Submit a pull request to the maintainer of the dependency
Hop onto IRC and chat with the maintainer about the fix, and ask politely if my coding style matches their vision for the project. (this also helps expedite their merging)
Once they merge the fix remove the -arthur- from the name and test their SNAPSHOT branch
Beg and plead for them to release the fixed project so you can drop the SNAPSHOT dependency.
While you are waiting for the dependency to merge and release you can push your fork to clojars under your name and with a version string that identifies it as your fork (in my case I use -arthur-.
Tt's tempting to apply lots of "style fixes" to a project when you're just in there digging around to fix a bug. If you want to do this do try to work with the project maintainer because they are in it for the long haul and more emotionally invested in the code.
Context
I want to use JavaFx with clojure.
I am aware of http://nailthatbug.net/2011/06/clojure-javafx-2-0-simple-app/
Question:
Is there a way to make JavaFX work with Clojure using native-deps in lein instead?
Thanks!
I've created a simple Clojure and JavaFX example on Github. Testing on Ubuntu I had to install the JavaFX runtime into my local Maven repository, using the deploy:deploy-file target (install:install-file did not work for me).
mvn deploy:deploy-file -DgroupId=local.oracle -DartifactId=javafxrt -Dversion=2.2.0 -Dpackaging=jar -Dfile=/usr/lib/jvm/java-7-oracle-amd64/jre/lib/jfxrt.jar -Durl=file:/home/raju/.m2/repository
Make sure you have the following arguments set correctly:
-Dfile={full path to jfxrt.jar in jre/lib folder}
-Durl=file:{full path to Maven repository, e.g. $HOME/m2.repository}
In the project.clj, I added the dependency based on the -DgroupId and -DartifactId values when installing the JAR into the repository. If you use change these values, make sure to change the dependency accordingly:
[local.oracle/javafxrt "2.2.0"]
Java was able to load the binary libraries without any problems. If Java reports problems loading a binary library, e.g.
Caused by: java.lang.UnsatisfiedLinkError: Can't load library:
/usr/lib/jvm/javafx-sdk/rt/lib/amd64/libglass.so
check out these two question on SO:
What is LD_LIBRARY_PATH and how to use it?
java.lang.UnsatisfiedLinkError no *****.dll in java.library.path
Because JavaFx has native dependencies your option are limited to, ]
shipping these dependencies with your project (including them),
creating a package that you can depend on which has them (providing them),
or having your package require the user to install them in some other way.
Because the tutorial you link to covers the case where the user of your package/program installs JavaFx on their own, by using robert.hook and depending on the end-user's package manager to provide the actual native dependencies. I'll cover how to have your package/program include the dependencies.
native-deps can be used to ship native dependencies with your package. You just need to add all the .so, .dll, .etc files in the appropriate directories. I think the projects github page does a better job than I of explaining the structure.
The link in the question is broken so I can't see your example, but with Java 8, JavaFX is now part of the standard JDK/JRE. I therefore expect the native dependency issue to be irrelevant at this point.
Not sure if this will work for others, but this appears (so far) to have worked for me:
mvn install:install-file -DgroupId=javafx -DartifactId=javafx -Dversion=2.1.0 -Dpackaging=jar -Dfile=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfxrt.jar
I have no idea why this works, but I believe jfxrt.jar has the files I need. Then, after this, I kindle it in project.clj as
[javafx "2.1.0"]
in the :dependencies (not :native-deps) section.
[Having written this, I really have no idea why this even appears to work.]
I have multiple, separate leiningen projects that ostensibly could depend on one-another.
Example:
~/projects/mywebapp (my own project)
~/projects/noir (a clone of the github repo)
~/projects/clojureql (a clone of the github repo)
I want to have them all compiled into the same JVM at the same time. I would like to run the git repos bleeding edge (pulling new commits/making my own commits) and not have to run lein jar or lein deps and certainly not have to restart the VM if I change any of the projects.
Here's a use case:
After running lein swank, from within emacs, I connect to the repl and compile a file from mywebapp (with C-c-k), which requires a file from noir. It finds the version of the file in my projects directory. Later, I open that file, edit it, and compile it (with C-c-k).
Note that I'm not asking for auto-compiling when I do git pull. I just don't want to have to restart the JVM or do lengthy jar compiling processes.
Is this possible in leiningen? How can I set this up?
Does this question from the Lein FAQ help?
Q: I want to hack two projects in parallel, but it's annoying to switch between them.
A: Use a feature called checkout dependencies. If you create a directory called checkouts in your project root and symlink some other
project roots into it, Leiningen will allow you to hack on them in
parallel. That means changes in the dependency will be visible in the
main project without having to go through the whole
install/switch-projects/deps/restart-repl cycle. Note that this is not
a replacement for listing the project in :dependencies; it simply
supplements that for tighter change cycles.
If you're already using swank, you don't need lein checkout dependencies. You can just C-c C-k your project (which will load the jarred versions of noir/whatever), and then browse to your local version of noir and C-c C-k that as well. Swank happily sends all the code to your repl, and the jvm never need know that it came from a different place!
I can only recommend this for smallish changes though, because I think if you compile noir.core, which depends on (say) noir.internal, clojure will load the jarred version of noir.internal even while you compile the local version of noir.core. Even so, it's a handy trick in general.
I have been able to run a custom plugin from within my projects project.clj, and even leiningen/plugin.clj (ie just a private plugin) - but when I go to put this plugin in its own project - I am unable to get it to work at all.
Following the advice, I should create a new project, and have a namespace of leiningen.myplugin etc etc... but the jar that I produce doesn't seem to provide the new task in the project (either via jar, or via clojars).
http://nakkaya.com/2010/02/25/writing-leiningen-plugins-101/
https://github.com/technomancy/leiningen/blob/stable/doc/PLUGINS.md
Anyone who has published a plugin care to confirm if the above is correct - or is there some crucial step I am missing? (I assume my task goes in core.clj in the plugin project)
Do you have the :eval-in-leiningen option set to true in the project.clj?
In addition if you want to use the task all around with your leiningen without having to add it to the dev dependencies of the project where you need to use it you need to use lein plugin install
Or did i miss something about your problem
Note that eval-in-leiningen doesn't need to be used for very simple project-specific plugins or tasks, and it can sometimes wreak build havoc. You can enable a Leiningen task for a given project by just using .lein-classpath for that project. More information here:
Project-level Leiningen Plugin