emezeske / lein-cljsbuild

Leiningen plugin to make ClojureScript development easy.
Other
1.1k stars 152 forks source link

Problem using 'lein trampoline' with cljsbuild #204

Open deg opened 11 years ago

deg commented 11 years ago

There seems to be a conflict using 'lein trampoline' when my project includes ':hooks [leiningen.cljsbuild]' in the top-level map in project.clj. Operations as simple as 'lein trampoline run' silently exit, with no error message, while 'lein run' works fine.

This bug-report is still half-baked. I'm sending what I've found so far, in the hope that someone will shout back "known bug" or "don't do that", but I can certainly give more detail if this is a real issue I've hit.

What I do know so far:

emezeske commented 11 years ago

Hrm... That is weird, especially the :dev profile part.

This is probably a dumb question, but are you using the very latest version of Leiningen?

I'm trying to think of some way to determine whether the bug is in lein-cljsbuild or Leiningen itself. The only idea I've come up with is to run some other plugin with :hooks under lein trampoline, and see if it fails the same way or not.

deg commented 11 years ago

(smacks self on side of head).

Looks like I’m running Leiningen 2.0.0, and the latest is 2.1.3. For some reason, I had thought that Leiningen or my config would do an auto version check.

I’ll upgrade Leiningen and test again. I should have an answer within an hour or two.

Assuming that the issue remains, I’ll try your idea of testing with another plugin. I’m still pretty new to this; do you suggest any plugin in particular?

David

From: Evan Mezeske [mailto:notifications@github.com] Sent: Tuesday, May 21, 2013 8:31 AM To: emezeske/lein-cljsbuild Cc: David Goldfarb Subject: Re: [lein-cljsbuild] Problem using 'lein trampoline' with cljsbuild (#204)

Hrm... That is weird, especially the :dev profile part.

This is probably a dumb question, but are you using the very latest version of Leiningen?

I'm trying to think of some way to determine whether the bug is in lein-cljsbuild or Leiningen itself. The only idea I've come up with is to run some other plugin with :hooks under lein trampoline, and see if it fails the same way or not.

— Reply to this email directly or view it on GitHubhttps://github.com/emezeske/lein-cljsbuild/issues/204#issuecomment-18190075.

deg commented 11 years ago

Ok, some updates…

  1. I’ve upgraded to Leiningen 2.1.3. No change in behavior. (Side question: the first time I did ‘lein upgrade’, it took me only up to 2.1.2. I had to run it again to get to 2.1.3. Known behavior, or clue to some other weirdness?)
  2. My comment about the :dev profile was a red herring; ignore it. (My carelessness, trying to test and file a bug report late at night. I had a ‘:cljsbuild { .. :builds { .. :dev { …}}}’ section in my projects.clj map, and I stuck the line inside there, where it was obviously ineffective.
  3. I’ve verified that I can duplicate the problem in the latest version of https://github.com/magomimmo/modern-cljs; much cleaner than the messy playground of my current project.

So, revised bug report:

Thanks, David

emezeske commented 11 years ago

Thanks for the detailed updates! I will try to debug further sometime soon. Unfortunately it may have to wait until a weekend.

(Regarding your lein upgrade sidenote -- I have no idea, very weird!)

xavi commented 11 years ago

I have the same problem, i.e. "trampoline" doesn't work with ":hooks [leiningen.cljsbuild]'". I think it's the same problem reported in https://github.com/technomancy/leiningen/issues/956 . Could it be that the latest versions of Leiningen fixed the 30 seconds hang that prompted the explicit exit hack ( https://github.com/emezeske/lein-cljsbuild/commit/d836402217d8ce26bddb0283c2fa9eefed66d5f5 )? If so, maybe just removing the hack fixes the issue?

ccfontes commented 11 years ago

Please try a working fork that removes the exit hack and therefore allows use of trampoline: [ccfontes/lein-cljsbuild "0.3.2-no-exit"] Hopefully this hack would be removed from the main repo.

xavi commented 11 years ago

I don't know if it breaks something else, but I can confirm that ccfontes fork fixes the issue with trampoline. I also hope to see this in lein-cljsbuild main repo soon.

Thanks Carlos!

ccfontes commented 11 years ago

@xavi that's great, thanks! Your links helped me out on this one too.

As stated at d836402217d8ce26bddb0283c2fa9eefed66d5f5 - "Without an explicit exit, the in-project subprocess seems to just hang for around 30 seconds before exiting. I don't fully understand why...", but rumored as comment to that commit to be already fixed at technomancy/leiningen@4f2bc328d73ab37d14c06ae22a2045252d312f55, was my reason to remove the exit hack. As more people give feedback about this fork, we will know if it is fixed in leiningen or not.

ccfontes commented 11 years ago

It happened here that, when deploying to heroku, the process hanged at Compiling ClojureScript for some minutes, but then completed the compilation and proceeded to other tasks.

-----> Deleting 6 files matching .slugignore patterns.
-----> Clojure (Leiningen 2) app detected
-----> Installing OpenJDK 1.6...done
-----> Using cached Leiningen 2.2.0
       Writing: lein script
-----> Building with Leiningen
       Found bin/build; running it instead of default lein invocation.
       Running: bin/build
       Compiling ClojureScript.

hanged, but resumed after some minutes..

       Compiling "target/cljsbuild-main.js" from ["src-cljs"]...
       Successfully compiled "target/cljsbuild-main.js" in 244.567180446 seconds.
       Compiling ClojureScript.
-----> Discovering process types
       Procfile declares types -> web

-----> Compiled slug size: 134.7MB
-----> Launching... done, v92
-----> Deploy hooks scheduled, check output in your logs
ccfontes commented 11 years ago

timed out one time:

> lein repl
Compiling ClojureScript.
Compiling "target/cljsbuild-main.js" from ["src-cljs"]...
Successfully compiled "target/cljsbuild-main.js" in 26.958402 seconds.
REPL server launch timed out.

but next try it didn't.

ccfontes commented 11 years ago

new record: Successfully compiled "target/cljsbuild-main.js" in 312.549677798 seconds.

ccfontes commented 11 years ago

For those using trampoline because of the exceeded memory quota on heroku there is the following alternative: using the uberjar branch of heroku-buildpack-clojure#uberjar . It solved not only boot timeouts but also memory issues, so there's no need to use the fork [ccfontes/lein-cljsbuild "0.3.2-no-exit"] anymore for that purpose. It seems heroku will be using this method in the future. There are some recent closed issues in heroku-buildpack-clojure#uberjar explaining part of the process. I'd be glad to help anyone who wants to try it.

jeluard commented 11 years ago

I also hit this issue. @ccfontes fork apparently fixes it. Any plan to merge it?

cemerick commented 11 years ago

@jeluard I haven't repro'd yet, but would look at a pull request if it were offered.

jeluard commented 11 years ago

I just tried to reproduce and now get an exception when running lein run trampoline (with hook defined): java.io.FileNotFoundException: Could not locate cljsbuild/compiler__init.class or cljsbuild/compiler.clj on classpath. Do you have some public project that I could test?

This is with leinigen 2.3.2 (not sure what else changed).

The previous behaviour was to exit after the line Compiling ClojureScript.. Quite similar to what happens when running lein cljsbuild once and no change is detected (which I think is confusing too).

cemerick commented 11 years ago

I can't point at a sample project, haven't seen the problem myself (though I only just saw this issue 10 minutes ago and I generally don't use trampoline). That said, hooks and trampoline often don't mix well.

General Q: why are people using trampoline when using cljsbuild?

jeluard commented 11 years ago

I can't point at a sample project

I was referring to a project that works for you so that I can check it does work for me and try to reproduce the issue.

why are people using trampoline when using cljsbuild?

It's mostly for convenience. I use trampoline when I want to run something close to production environment. It's simpler if I can do this without having to change my project.clj (as I have cljsbuild hook defined).

xavi commented 11 years ago

@cemerick I was using trampoline with cljsbuild (through hooks) when deploying to Heroku because at the time Heroku docs were recommending the use of trampoline, and OTOH I didn't want to put the compiled ClojureScript files in the repo (I think they don't belong there in the same way as .class files are not put in the repo), so I used hooks to get ClojureScript compiled on deployment.

But recently Heroku changed the recommended way to deploy (as @technomancy mentioned, and Heroku updated docs already reflect). Since then I'm following those recommendations to deploy my projects, and this issue has become non-relevant for me.

magomimmo commented 11 years ago

Here is a sample repository from which is possible to reproduce the issue:

https://github.com/magomimmo/modern-cljs.git

  1. Use case: :hooks [leiningen.cljsbuild]

    $ lein trampoline ring server-headless
    Compiling ClojureScript.
    Exception in thread "main" java.io.FileNotFoundException: Could not locate cljsbuild/compiler__init.class or cljsbuild/compiler.clj on classpath:
    at clojure.lang.RT.load(RT.java:443)
    at clojure.lang.RT.load(RT.java:411)
    at clojure.core$load$fn__5018.invoke(core.clj:5530)
    at clojure.core$load.doInvoke(core.clj:5529)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5336)
    at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
    at clojure.core$load_lib.doInvoke(core.clj:5374)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$load_libs.doInvoke(core.clj:5413)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:619)
    at clojure.core$require.doInvoke(core.clj:5496)
    at clojure.lang.RestFn.invoke(RestFn.java:436)
    at user$eval7.invoke(form-init4607419569722922037.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6619)
    at clojure.lang.Compiler.eval(Compiler.java:6608)
    at clojure.lang.Compiler.load(Compiler.java:7064)
    at clojure.lang.Compiler.loadFile(Compiler.java:7020)
    at clojure.main$load_script.invoke(main.clj:294)
    at clojure.main$init_opt.invoke(main.clj:299)
    at clojure.main$initialize.invoke(main.clj:327)
    at clojure.main$null_opt.invoke(main.clj:362)
    at clojure.main$main.doInvoke(main.clj:440)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:419)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.Var.applyTo(Var.java:532)
    at clojure.main.main(main.java:37)
  2. Use Case: no hooks
$ lein trampoline ring server-headless
2013-09-13 00:34:50.568:INFO:oejs.Server:jetty-7.6.8.v20121106
2013-09-13 00:34:50.604:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:3000
Started server on port 3000

Seems to be a classpath problem.

levand commented 10 years ago

I just wanted to add that this issue also breaks the REPL in the Cursive Intellij plugin, which apparently is using lein trampoline. @cursiveclojure @cemerick

cemerick commented 10 years ago

Looking at this, it's not clear to me why cljsbuild isn't on the classpath (along with e.g. everything else I have in :dev that is on the classpath) when attempting to run a task via lein trampoline. :hooks is not really relevant, it just forces the issue by necessarily attempting to run the cljsbuild task within the scope of the trampoline.

Again, happy to look at a PR on this.

In the meantime: don't use trampoline, or chain the task explicitly, before the trampoline, e.g. lein do cljsbuild once, trampoline repl.

cursive-ide commented 10 years ago

why are people using trampoline when using cljsbuild?

Cursive uses the underlying trampoline mechanism to start all its REPLs. This is so that the REPL startup script can be created in the Cursive process without having to start another external JVM just to create the script. It does create a few problems due to trampoline use and also the fact that the JVM used to run Cursive may be different to the one used to run the REPL, so some config is sometimes incorrect. However it's nothing that can't be worked around so far, and the alternative would be very slow.

realyze commented 9 years ago

Please note that this is also a problem when deploying to Heroku as they suggest to use trampoline.

cemerick commented 9 years ago

Looking back at this, I've since developed and deployed an application to heroku that uses cljsbuild without trampoline, with no problems. That's strictly FWIW, just by way of saying I've still not been able to repro.

This issue has been open ~18 months, but no PR has been offered. If someone could produce one and have at least one other person vouch for it, I'll be happy to merge, if only to make sure that @cursiveclojure doesn't continue to get bitten.

ccfontes commented 9 years ago

When I was cleaning my forks, I accidentally deleted the one where the fix was made, but the source is still in clojars. I think It was a trivial fix though.

That being said, I don't even remember anything about the issue anymore. Sorry :(

cprice404 commented 9 years ago

ran into this with @cursiveclojure today. :(

gdanov commented 9 years ago

me too. it seems to be one of the things getting in the way of having cursive + cljs repls play together

conan commented 8 years ago

This is preventing me from running REPLs in Cursive, sadly. Windows 10, Intellij 15.0.1, Cursive 0.1.70

cprice404 commented 8 years ago

Doing battle with this bug again today. I think I've broken it down into two discrete issues.

The first has to do with the fact that this git repo actually produces two separate artifacts; the lein plugin artifact lein-cljsbuild (from the plugin directory), and another artifact called just cljsbuild (from the support directory).

The code in plugin/src/leiningen/cljsbuild/subproject.clj does some fairly magical stuff to add in a dependency on the cljsbuild artifact, but I don't think that's necessarily causing the problem.

I'm not sure that I understand exactly why, but the temporary script that lein generates for the trampoline execution includes this at the top:

    (require (quote cljsbuild.compiler)
             (quote cljsbuild.crossover)
             (quote cljsbuild.util))

And the classpath that lein launches that script with does not include any of the lein plugin artifacts, nor their dependencies, so cljsbuild is not on the classpath.

This is easy enough to remedy; just add [cljsbuild "1.1.2"] to the dev dependencies for your project. Doing that gets me past the Could not locate cljsbuild/compiler__init.class or cljsbuild/compiler.clj on classpath error.

Which brings us to the second issue, which is the one that @ccfontes mentioned above; in the happy path of the code in plugin/src/leiningen/cljsbuild.clj there is a line that calls System/exit after the cljs compilation has completed. When this happens it kills the trampolined repl session.

I can't find anything in the code that explains why that exit is necessary, and it doesn't seem like lein cljsbuild once runs any slower without it, and it doesn't cause any test failures... so I can file a PR to remove it.

If I do the two things above (add cljsbuild to my dev deps, and remove the exit call from cljsbuild.clj in the plugin), the trampoline REPL works fine for me both from the CLI and via @cursive-ide .

cprice404 commented 8 years ago

I filed a PR, and also deployed a fork with the fix to clojars:

https://clojars.org/cprice404/lein-cljsbuild/versions/1.1.2-noexit

mneise commented 8 years ago

@cprice404 Awesome, thank you for digging into this! Will have a closer look at your PR and your findings in the next couple of days :wink:

cprice404 commented 8 years ago

@mneise ping! just checking to see if this slipped through the cracks.

mneise commented 8 years ago

@cprice404 Merged your PR for the System/exit #436, thank you! This definitely helps when chaining tasks with lein do.

Regarding the missing cljsbuild dependency, we already add it as a dependency to the project's dependencies before running eval-in-project, so there really should be no need for a user to include it again in their project's dependencies. I've also noticed that not every use of lein trampoline has cljsbuild missing on the classpath, for example lein trampoline do clean, cljsbuild once dev works fine for me. Therefore, I think that this might be a bug in leiningen and I've already created an issue for this (https://github.com/technomancy/leiningen/issues/2095).

cprice404 commented 8 years ago

@mneise thanks! Adding cljsbuild as an explicit dependency in my dev profile is a sufficient workaround for now, but I've been digging in the lein source lately for other reasons, so maybe I'll take a peek at that bug you opened if I get a chance.

Any idea when you might do the next release? Looking forward to getting off of my fork :)

mneise commented 8 years ago

@cprice404 Will try to cut a release this weekend :wink:

cprice404 commented 8 years ago

yay, thanks.

cprice404 commented 8 years ago

I presume this went into the 1.1.3 release? If so, thanks!

mneise commented 8 years ago

@cprice404 Yes, just released it this morning. Let me know if you experience any issues :wink:

cprice404 commented 8 years ago

will do, thanks again.

cprice404 commented 8 years ago

Upgraded our project to 1.1.3 today and it seems to be working fine. Thanks!

maiq123 commented 8 months ago

Hi is there any update on this? Or are we still using the same workaround of adding the dependency?