Using bitbake is it possible to have a different do_install for a package based on the target image? - recipe

We have a single MACHINE which we use to build two target images; foo-image and foobar-image. Both images consume the same version of a package, but we would like to add a change to the do_install task based on which image is built. So that the recipe file for the package looks something like this:
do_install (){
//Some work
}
do_install_append_foobar-image(){
//Some foobar work
}
Eventually when we do the build for the two images:
MACHINE=custom bitbake foo-image
MACHINE=custom bitbake foobar-image
The image for foobar will contain the installed package that has done the work in the appends task, but the image for foo will not.
Is there any way to do what I have outlined or what would be an alternative?

No, you can't perform different tasks in a recipe based on which image is being built. There might be a possibility of checking the image name in the do_install though I'm highly unsure.
What I'd do is the following:
In the recipe, add a 2nd package which includes the additional files (if that's what you want to do).
Have your 2nd image recipe include this 2nd package.
Another possibility, depending on if you can detect which image you have built, is to add a post_install-script, that does the modification for you. A third, maybe less good option would be to do changes in a ROOTFS_POSTPROCESS_COMMAND.
Which solution you choose, will depend on what kind of customization you want to.

After some deliberation we were probably thinking about this backwards. We probably want to inject separation at the MACHINE level. Since both will be separate products in the end this makes the most sense. Doing it this way will allow us to introduce changes to packages for that specific product.
Our build lines will become:
MACHINE=custom1 bitbake foo-image
MACHINE=custom2 bitbake foobar-image
And our install task for the package can be:
do_install (){
//Some work
}
do_install_append_custom2(){
//Some more work
}

Related

premake: how to get a list of the defined configurations?

ie, I'd like a hypothetical function get_configurations() that would let me do something like this in my premake5.lua:
workspace "myworkspace"
configurations { "debug", "release" }
project "myproject"
configurations { "projconfig" }
for _, cfg in ipairs(get_configurations()) do
print(cfg)
end
...and have it output:
debug
release
projconfig
Is this possible? I saw that there is premake.configset, but it's not clear how to use it...
No, that is not possible. In your simple example it looks easy, but in larger projects there may be many considerations that go into deciding what values end up in that list. It could be filtered by target platform, or toolset, or any number of other variables. Some later block may remove a value that was set earlier. The actual list can't be determined until after all scripts have been run and the final configuration is compiled for export.
However, Premake is just Lua, so you can always define a list of configurations and associate it with a variable, or wrap your settings up in a function and pass in the values.

SBT run code in project after compile

we need to run some code after the compile step. Making things happen after the compile step seems easy:
compile in Compile <<= (compile in Compile) map{x=>
// post-compile work
doFoo()
x
}
but how do you run something in the freshly compiled code?
More info on the scenario: we are using less for css in a lift project. We wanted lift to compile less into css on the fly (if needed) to help dev, but produce less using the same code, during the build, before tests etc run. less-sbt may help but we are interested in how to solve this generally.
You can use the triggeredBy method like this:
yourTask <<= (fullClasspath in Runtime) map {classpath =>
val loader: ClassLoader = ClasspathUtilities.toLoader(classpath.map(_.data).map(_.getAbsoluteFile))
loader.loadClass("your.class.Here").newInstance()
} triggeredBy(compile in Compile)
This will instantiate your class that has just been compiled, using the runtime classpath for your application, after any compile.
It would probably help if you explained your use scenario for this, since there are some different possible solution paths here and choosing between them might involve considerations that you haven't told us.
You won't be able to just write down an ordinary method call into the compiled code. That would be impossible since at the time your build definition is compiled, sbt hasn't looked at your project code yet.
Warning: rambling and thinking out loud ahead.
One trick I can suggest is to access testLoader in Test to get a classloader in which your compiled classes are loaded, and then use reflection to call methods there. For example, in my own build I have:
val netlogoVersion = taskKey[String]("...")
netlogoVersion := {
(testLoader in Test).value
.loadClass("org.nlogo.api.Version")
.getMethod("version")
.invoke(null).asInstanceOf[String]
}
I'm not sure whether accessing testLoader in Test will actually work in your case because testLoader loads your test classes as well as your regular classes, so you might get a circular dependency between compile in Compile and compile in Test.
If you want to try to make a classloader that just has your regular classes loaded, well, hmm. You could look in the sbt source code at the implementation of createTestLoader and use it for inspiration, modifying the arguments that are passed to ClasspathUtilities.makeLoader. (You might also look at the similar code in Run.run0. It calls makeLoader as part of the implementation of the run task.)
A different path you might consider is to reuse the machinery behind the run task to run your code. You won't be able to call an arbitrary method in your compiled code this way, only a main method, but perhaps you can live with that, if you don't need a return value back.
The fullRunTask method exists for creating entire run-like tasks. See "How can I create a custom run task, in addition to run?" from http://www.scala-sbt.org/0.13.1/docs/faq.html . fullRunTask makes it very easy to create a separate task that runs something in your compiled code, but by itself it won't get you all the way to a solution because you need a way of attaching that task to the existing compile in Compile task. If you go this route, I'd suggest asking it that last piece as a separate question.
Consider bypassing fullRunTask and just assembling your own call to Run.run. They use the same machinery. In my own build, I currently use fullRunTask, but back before fullRunTask was added by sbt, here was what my equivalent Run.run-based code looked like:
(..., fullClasspath in Compile, runner, streams, ...) map {
(..., cp, runner, s, ...) =>
Run.run("name.of.my.MainClass",
cp.map(_.data), Seq(), s.log)(runner)
}
Pardon the sbt 0.12, pre-macro syntax; this would look nicer if redone with the 0.13 macros.
Anyway, hopefully something in this brain dump proves useful.

Qt Installer Framework - How to customise?

I've managed to successfully create an ‘AdminProgram’ which is used to build the installer for my main project. It creates required configs/packages in file system correctly, updates all .xml files and copies all required elements into the correct places before building the installer, which is pretty great.
However, I am now looking to customize my installer to do a little more so that it is able to install a few drivers into the windows registry and at a later date remove existing installs before proceeding with a new one. I have studied the ‘instructions’ ( http://doc-snapshot.qt-project.org/qtifw-1.4/scripting.html#predefined-variables) for some time now and have been unable to quite grasp how exactly these Custom Operations are implemented (where the example code is supposed to be written, how the overridden operations are accessed etc.).
I find that the instruction are a little ambiguous for a programmer as inexperienced as myself and would very much appreciate some help from anyone who can give it?
In order to set entries in the registry you need to add GlobalConfig operations in your component script.
Overload the method Component.prototype.createOperations and add additional commands such as:
function Component() {
'use strict';
}
Component.prototype.createOperations = function () {
'use strict';
// call default implementation
component.createOperations();
component.addOperation("GlobalConfig",
"HKEY_CURRENT_USER\\Software\\#Publisher#\\#ProductName#\\entry",
"key",
"value");
}
The list of operations available are here

How do I change Closure Compiler compile options not exported to command line?

I found that some options in CompilerOption are not exported to the command line.
For example, alias all strings is available in the Closure Compiler's Java API CompilerOption but I have no idea how set this in the command line.
I know I can create a new java class, like:
Compiler c = new Compiler();
ComppilerOptions opt = new ComppilerOptions();
opt.setAliasAllString(true);
c.compile(.....);
However I have to handle the command line args myself.
Any simple idea?
============================
In order to try the alias all string option, I write a simple command line application based on compiler.jar.
However I found that, the result I got when open the alias all string is not what I expected.
For example:
a["prototype"]["say"]=function(){
var a="something string";
}
Given the above code, the something string will be replaced by a variable like this:
var xx="something string";
....
var a=xx;
....
This is fine, but how about the string "say"? How does the closure compiler know this should be aliased(replace it use variable) or exported(export this method)?
This is the compiled code now:
a.prototype.say=function(){....}
It seems that it export it.
While I want this:
var a="prototype",b="say",c="something string";
xx[a][b]=function(){.....}
In fact, this is the google_map-like compilation.
Is this possible?
Not all options are available from the command line - this includes aliasAllStrings. For some of them you have the following options:
Build a custom version of the compiler
Use the Java API (see example).
Use plovr
Getting the same level of compression and obfuscation as the Maps API requires code written specifically for the compiler. When properly written, you'll see property and namespace collapsing, prototype aliasing and a whole host of others. For an example of the style of code that will optimize that way, take a look at the Closure Library.
Modifying http://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/javascript/jscomp/CompilationLevel.java?r=706 is usually easy enough if you just want to play with something.
Plovr (a Closure build tool) provides an option called experimental-compiler-options, which is documented as follows:
The Closure Compiler contains many options that are only available programmatically in Java. Many of these options are experimental or not finalized, so they may not be a permanent part of the API. Nevertheless, many of them will be useful to you today, so plovr attempts to expose these the experimental-compiler-options option. Under the hood, it uses reflection in Java, so it is fairly hacky, but in practice, it is a convenient way to experiment with Closure Compiler options without writing Java code.

How can I tell the Closure Compiler not to rename an inner function using SIMPLE_OPTIMIZATIONS?

How can I tell the Closure Compiler not to rename an inner function? E.g., given this code:
function aMeaninglessName() {
function someMeaningfulName() {
}
return someMeaningfulName;
}
...I'm fine with Closure renaming the outer function (I actively want it to, to save space), but I want the function name someMeaningfulName left alone (so that the name shown in call stacks for it is "someMeaningfulName", not "a" or whatever). This despite the fact that the code calling it will be doing so via the reference returned by the factory function, not by the name in the code. E.g., this is purely for debugging support.
Note that I want the function to have that actual name, not be anonymous and assigned to some property using that name, so for instance this is not a duplicate of this other question.
This somewhat obscure use case doesn't seem to be covered by either the externs or exports functionality. (I was kind of hoping there'd be some annotation I could throw at it.) But I'm no Closure Compiler guru, I'm hoping some of you are. Naturally, if there's just no way to do that, that's an acceptable answer.
(The use case is a library that creates functions in response to calls into it. I want to provide a version of the library that's been pre-compressed by Closure with SIMPLE_OPTIMIZATIONS, but if someone is using that copy of the library with their own uncompressed code and single-stepping into the function in a debugger [or other similar operations], I want them to see the meaningful name. I could get around it with eval, or manually edit the compressed result [in fact, the context is sufficiently unique I could throw a sed script at it], but that's awkward and frankly takes us into "not worth bothering" territory, hence looking for a simple, low-maintenance way.)
There is no simple way to do this. You would have to create a custom subclass of the CodingConvention class to indicate that your methods are "local" externs (support for this was added to handle the Prototype library). It is possible that InlineVariables, InlineFunctions, or RemoveUsedVariables will still try to remove the name and would also need to be fixed up.
Another approach is to use the source maps to remap the stack traces to the original source.
read the following section
https://developers.google.com/closure/compiler/docs/api-tutorial3#export
Two options basically, use object['functionName'] = obj.functionName or the better way
use exportSymbol and exportProperty both on the goog object, here is the docs link for that
http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html
-- edit
ah, i see now, my first answer is not so great for you. The compiler has some interesting flags, the one which might interest you is DEBUG, which you can pass variables into the compiler which will allow you to drop some debugging annotations in via logging or just a string which does nothing since you are using simple mode.
so if you are using closure you can debug against a development version which is just a page built with dependiencies resolved. we also the drop the following in our code
if(DEBUG){
logger.info('pack.age.info.prototype.func');
}

Resources