I recently started using Rake to build some of my (non-ruby) packages. Rake is nice, but what I found missing is a way to do hierarchical builds (aggregate Rakefiles in subdirectories). Since this is a common feature in most other build tools, I'm wondering if someone more familiar with Rake has a good solution.
I would recommend Buildr for non-Ruby build tasks. It is based on Rake (sits on top of it, allowing you to use all of Rake's features) but fits the semantics of compiled languages better. It also supports hierarchical builds.
I, too, could not figure out a way to do this. I ended up doing:
SUBDIR = "subdir"
task :subtask => SRC_FILES do |t|
chdir(SUBDIR) do
system("rake")
end
end
task :subtaskclean do |t|
chdir(SUBDIR) do
system("rake clean")
end
end
task :subtaskclean do |t|
chdir(SUBDIR) do
system("rake clobber")
end
end
task :default => [:maintask, :subtask]
task :clean => :subtaskclean
task :clobber => :subtaskclobber
Kinda sucks. Actually, really sucks. I scoured the docs and could not find the equivalent of <antcall>
I'm sure that since it's all Ruby and I barely know Ruby there's some super obvious way of requireing it or something.
Buildr uses the notion of scopes, coupled with the name of the projects.
Rake.application.current_scope should be the entry point to discover how to work with them. I hope this helps.
The fix I've used to get around this is:
Dir.chdir(File.dirname(Rake.application.rakefile))
This statement has to be run at every level in the hierarchy except for the root, at the start of every rakefile. A shortened example of how this works in practice:
/rakefile:
task :default do
sh "rake -f component/rakefile"
end
/component/rakefile
Dir.chdir(File.dirname(Rake.application.rakefile))
task :binary => OBJECTS do
sh "gcc #{SOURCES} -Iinclude -o #{TARGET}"
end
As I'm new to rake I'm not convinced it's the cleanest method of solving it, but it was how I eventually got it to work.
Related
I would like to add the following to pre-commit for a team:
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v0.720'
hooks:
- id: mypy
args: [--ignore-missing-imports]
My team is worried that this might be too strict. To have a gradual introduction, I would like this hook not to make the commit fail, but only to show the issues. Is that possible?
you can, but I wouldn't suggest it -- warning noise is likely to have your whole team ignore the entire output and the entire tool
here's how you would do such a thing (note that it has reduced portability due to bash -- mostly because the framework intentionally does not suggest this)
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.720
hooks:
- id: mypy
verbose: true
entry: bash -c 'mypy "$#" || true' --
two pieces make this work:
verbose: true always produces the output -- this option is really only intended for debugging purposes, but you can turn it on always (it can be noisy / annoying though)
bash + || true -- ignore the exit code
disclaimer: I am the author of pre-commit
Also note that you can temporarily disable hooks by setting the environment variable SKIP. For example:
SKIP=flake8 git commit -m 'fix thing - work in progress'
This is especially useful when you just want to make local "checkpoint" commits that you'll fix later.
Side note on mypy specifically: there's a potentially big issue with using mypy in a non-blocking way like this. If you allow commits with type errors to be merged, everyone else will start to see those type errors in their pre-commit checks.
When developers are making further changes, it's confusing whether the mypy errors that appear were there from before, or due to their further changes. This can be a recipe for frustration/confusion, and also for allowing further type errors to accumulate.
I think the mypy guide on using mypy with an existing codebase is pretty good advice.
If you just need to temporarily skip mypy checks so you can checkpoint your work, push a PR for initial review, or whatever, you can just do SKIP=mypy as mentioned above.
I have a clojure script that I've been running for several years now.
Recently I had to do a reinstall of leiningen and java 8.
When I run the code I now get multiple StackOverflowErrors on third party libraries.
E.g.
StackOverflowError org.apache.commons.math3.util.FastMath.cosQ (FastMath.java:1850)
and
StackOverflowError clojure.lang.Numbers$DoubleOps.combine (Numbers.java:571)
I would post code but it happens now at multiple points in my code and on third party libraries??
without a stack trace and some code, a specific anser will be hard to find, so here is a general method for these things:
Part 1 "what was running before":
recreate your old environment, by digging through the logs, reverting to a backup etc. then run:
lein deps :tree 2>&1 > old-lein-dependencies
the 2>&1 part ensures that the version range and conflict warnings
are included in the output.
Mark down the leiningen version and java version:
lein version
Part 2: "what is running now"
Repeat the steps and record the same information as before:
lein deps :tree 2>&1 > new-lein-dependencies
lein version
java -version
Part 3: Diff and Compare
pick through all the differences
diff -u old-lein-dependencies new-lein-dependencies
there will be a big block of differences at the top where lein prints all the important warnings. The final clue is almost always here, though it's often not easy to recognise up right away.
Part 4: Do Science
go through every version change, starting from the initial configuration by pinning the versions in the project.clj until you find the change that breaks things. A convenient way to pin these is with the :managed-dependencies block in the project.clj file. It looks something like this:
:managed-dependencies [[http-kit "2.3.0-alpha4"]]
and repeat the process of switching out versions till you get a handle on where the change was introduced. For me this has almost always been the result of using a version range in a dependency rather than a specific version. I'm not too enthusiastic about version ranges anymore :-/
So I could not compare the previous setup as it was on a machine that was wiped clean.
I found that an error had crept into one of the math formulas executed by the tool which basically called itself repeatedly resulting in the stack overflow error.
I'm used to enhance rake tasks, but today rake do not want to collaborate...
In particular I want to enhance rake tmp:clear. And as usual I tried this way:
Rake::Task["tmp:clear"].enhance do
puts "enhanced"
end
I always get a Don't know how to build task 'rake tmp:clear' on execution.
I tried to:
Rename my xxx.rake file that contain this piece of code.
Remove everything but this piece of code.
Look into rake tasks/tmp.rake source code to see if tmp:clear had some other weird treatment.
And of course Googled a lot...
I ended up with no solutions/clues.
Thanks for any help.
Flavien
Footnotes:
It works if I change "tmp:clear" for "assets:clobber" for exemple. But still not for "tmp:cache:clear" or other related to tmp.
I use rails 4.2
This is a problem I was facing as well and I was finally able to trace down what was happening. It seems that rails is not including the tmp tasks until after the local rake tasks were loaded. This does not apply to assets:clobber however since those are not declared in the same location as the tmp rake tasks. You can see more information about the declarations. I was able to fix this by adding
require 'rails/tasks'
to the top of my tmp.rake file in tasks, so in your case it would look like
require 'rails/tasks'
Rake::Task["tmp:clear"].enhance do
puts "enhanced"
end
and then everything worked for me as expected.
I have just begun playing with ClojureScript and I'd like to collect all CSS files into a single folder (out/css). I found leiningen-less and with the following config I get the compiled CSS files into the correct location:
:less {:source-paths ["src/less"]
:target-path "out/css"}
I can't find any documentation on how I can handle the ordinary CSS files (e.g. the file for resetting defaults, css/reset.css). Basically I want the equivalent of cp css/*css out/css.
I did find lein-resource but it does a bit more than I require (pass things through stencil) and more importantly it through an UnsupportedOperationException on my with what I thought would a be a valid configuration:
:resource {:resource-paths ["css" {:target-path "out/css"}]}
Please englighten me!
For your particular use case just rename reset.css to reset.less. less should be able to read CSS without problems.
For more advanced frontend tooling maybe consider adding something like make/grunt/etc. More complexity but more power & flexibility.
I think better and easy solution would be that you write a function that uses clojure.java.io library functions and integrate them with lein-less "compiler" fork, so this is my internal function proposal:
(defn your-fn[]
(remove-folder "./out") ;; => you have to do how to make that fn following io lib doc
(copy-folder "./css ./out") ;; ;; => you have to do how to make that fn following io lib doc
(run-compiler :javascript
{:project-root "your-project-root/"
:source-paths ["less"]
:target-path "out"})))
PS: note that you need to call this fn from your clojurescript compilation process, BTW I didn't know if there is a way for that :)
We've developed some profiling aspects that we would like to include in a testing build, but not in our production build. I'm looking for a best-practices way of structuring the build.gradle file and the source directories.
My initial thought was to create a compileJavaAJ task, and a jarAJ task which depends on compileJavaAJ. compileJavaAJ would look awfully similar to the compileJava defined in the aspectJ plugin, http://github.com/breskeby/gradleplugins/raw/0.9-upgrade/aspectjPlugin/aspectJ.gradle. The problem with just applying this plugin is that it completely replaces compileJava (i.e. the one using javac). I need two build targets - one that uses javac, the other that uses ajc. I welcome suggestions if there's a better approach though.
Next, I need to decide where to put the aspectJ code. I don't want to put it in src/main/java, because the java compiler will choke on it. So, I'm thinking of defining a new SourceSet, src/main/aspectJ, which only compileJavaAJ knows about. A SourceSet is supposed to model java code though, so I'm not quite sure if this is the correct approach.
Any input is greatly appreciated. Thanks!
I would use a property like "withAspectJ" to differentiate between compiling with and without your aspects. Have a look on the following snippet:
if(project.hasProperty('withAspectj') && project.getProperty("withAspectj")){
sourceSets {
main {
java {
srcDir 'src/main/aspectj'
}
}
}
}
This snippets adds the directory src/main/aspectj to your main sourceset if a property named withAspectj evaluates to true. Now you can put all your aspects into this specific directory. If you don't pass the withAspectj property, the replaced compileJava task will compile your code without wiring the aspects into it.
But if you run your build from the command line:
gradle build -PwithAspectj=true
all aspects located in src/main/aspectj will be wired into your code.
hope that helped,
regards,
René