How does the parsing of variables in Yocto work? - parsing

There are some variables that I just use without knowing what it does. Could someone explain the logic behind all these parsing in Yocto?
What does the underscore do? What are the available arguments other than _append_pn?
PACKAGECONFIG_append_pn-packagename = " packagename"
PREFERRED_VERSION_linux-imx_mx6 = "3.10.17"
SRC_URI_append_toolchain-clang = " file://0004-Remove-clang-unsupported-compiler-flags.patch "
EXTRA_OECONF_append_arm = " --enable-fpm=arm"
How about this one? I know that adding in this way is to single out a package, but how does it work?
LICENSE_FLAGS_WHITELIST_append = " commerical_packagename"
Someone also mentioned something weird with this that worked for them: bitbake: how to add package depending on MACHINE?
IMAGE_INSTALL_append_machine1 += " package1"

The documentation covers this pretty well: https://www.yoctoproject.org/docs/latest/bitbake-user-manual/bitbake-user-manual.html#basic-syntax
The longer version is that _ introduces an override, which is a way of saying "do something special" instead of just assigning.
Some are operations such as append and prepend.
FOO = "1"
FOO_append = "2"
FOO is now "12" as 2 was appended to 1.
(_prepend does what you'd expect)
_remove can be used to remove items from a whitespace-separated list.
FOO = "1 2 3"
FOO_remove = "2"
FOO is now "1 3".
pn_[foo] is an override for a specific recipe name (historical naming, it means package name, but actually refers to the recipe). So your local.conf can do:
EXTRA_OEMAKE_pn-foo = "bar"
And you've just set EXTRA_OEMAKE for the foo recipe, and just the foo recipe.
There are other overrides. The architectures all have overrides, so _arm _x86 _mips etc specify that an assignment is specific to those architectures.

Related

Ruby - use a Constant for 'case" statements conditions

I have a Ruby case statement that looks like:
case ruby_variable
when "instagram"
# do this
when "twitter"
# do that
# and so on...
else
"theres an error"
end
I also have a constant with all the social network names (this list willl vary in time):
NETWORKS_LIST =
[ "instagram",
"twitter",
"pinterest",
.......
]
I would like to change this so that the conditon values, that is to say "pinterest", "twitter" and others, populate automatically into my case statement (but keep the last line else "error").
Something like a loop:
case ruby_variable
when NETWORKS_LIST[0]
do this
when NETWORKS_LIST[1]
do that
and so on...
else
"theres an error"
end
I'm not sure how to manage this.
Normally you use a structure like an Array to look up things and test validity, a Hash to define mappings, or a case to branch execution. It's highly unusual when more than one of these is involved at the same level of your solution, that is they're used in a way that's tightly inter-linked.
I think there's a few things that are confused here. Constants of this sort are best used for look-ups, like testing if your parameters are valid:
NETWORKS_LIST.include?(params[:network])
If you want to re-use values in that list elsewhere the Ruby convention is to prefer Symbols over Strings:
NETWORKS_LIST = [
:instagram,
:pinterest,
:weratedogs
]
Then in your case statement:
case params[:network]
when :instagram
make_instagram_post!
when :pinterest
make_pin!
when :weratedogs
bark_incessantly!
else
raise "Not a valid network."
end
You maintain these two structures independently because the case statement has additional code in it that's not encapsulated in the original structure. Now you can always merge the two:
NETWORKS = Hash.new(-> {
raise "Not a valid network."
}).merge(
instagram: -> {
make_instagram_post!
},
pinterest: -> {
make_pin!
},
weratedogs: -> {
bark_incessantly!
}
)
This has a default value that's a Proc which raises an error, so you can just call it like this:
NETWORKS[params[:network].to_sym].call
That will either do whatever's expected or error out provided params[:network] is populated.
You can evolve this further into a little Ruby DSL if you want.

lua, combining strings with variables inside tables when imported from file

I am having a problem with variables inside tables. this is essential since I use tables as configuration for my program.
so I have tested the following code that works:
> x = "X"
> t = {["ref"]="table with value: "..x}
> print(t["ref"])
table with value: X
> x = "Y"
> t = {["ref"]="table with value: "..x}
> print(t["ref"])
table with value: Y
it however doesn't work without the second > t = ["ref"]="table with value: "..x
now I went to implement this into my main program witch consists of two files, one witch returns the configuration table. And one file with all the functions and stuff. it looks as following
FILE A (main.lua):
testString = "test1"
print(testString)
local CONFIG = require'config'
print(CONIFG[1].test)
testString = "test2"
print(testString)
local CONFIG = require'config'
print(CONIFG[1].test)
FILE B (config.lua):
local CONFIG = {
{["test"]=[[this is a test: ]]..testString}
}
return CONFIG
now when i run file A (a.k.a. main.lua) i get the following output:
test1
this is a test: test1
test2
this is a test: test1
i can't figure out what i am doing wrong here.. i thought it had something to do with that it was a single string so i made testString a table but that gave me the same result...
(that title really seems scary.. sorry)
require, by design, caches the return value. So if you call require with the same string, it will not execute the script again. It will simply return the previously returned value.
require is for loading modules. And modules should not change their return values based on other global state.
The function you're probably looking for is dofile. This will always load and execute the file (but it has none of the path searching properties of require). Alternatively, you can use loadfile to load the file as a function, then execute that function to regenerate the table whenever you want.
Also:
I am having a problem with variables inside tables.
There are no "variables inside tables". Or at least not the way you mean. Expecting a change to a variable to affect some other value is like expecting this:
a = 5
b = a + 5
a = 10
assert(b == 15, "This will never be true.")
When an expression (whether a + 5 or "table with value: " .. x) is evaluated, it results in a value. The resulting value is in no way dependent on any value or variable from the expression that generated it.
That's why you had to regenerate the value; because values don't change just because some variable changes.

How do I get lua string match to parse an environment variable string?

I have a config file parser written in lua.
I'd like to detect values that are environment variables and change them with os.getenv.
It's probably a bit ambitious because I can have values like
"a string with an embedded ${VARIABLE} in here"
or
"another string with an env $VARIABLE"
And I should probably allow escaping them with double $$ to allow a literal $.
How do I do this?
This is what I have so far, but it isn't right
local envvar = string.match(value, "%$([%w_]+)")
if envvar then
print("Envvar=", envvar)
value = value:gsub("(%$[%w_]+)", os.getenv(envvar))
end
For example, I can't figure out how to use the %b balance option here to properly match { } combinations. And make them optional. How do I make this work robustly?
In fact, I realise it's probably more complicated than this. What if more than one environment variable was specified?
local text = [[
Example: ${LANG}, $TEXTDOMAINDIR, $$10.00, $$LANG, $UNDEFINED
Nested braces: {{${SHELL}}}
]]
text = text:gsub('$%$','\0')
:gsub('${([%w_]+)}', os.getenv)
:gsub('$([%w_]+)', os.getenv)
:gsub('%z','$')
print(text)
--> Example: en_US.UTF-8, /usr/share/locale/, $10.00, $LANG, $UNDEFINED
--> Nested braces: {{/bin/bash}}

Accessing Ruby Hash value using a string

I have a ruby array like below
tomcats = [
'sandbox',
'sandbox_acserver',
'sandbox_vgw'
]
I need to pass the string as a hash index like below
tomcats.each do |tomcat_name|
obi_tomcat '#{tomcat_name}' do
Chef::Log::info("Creating tomcat instance - #{tomcat_name}")
Chef::Log::info("#{node['obi']['tomcat']['sandbox'][:name]}") // works
Chef::Log::info("#{node['obi']['tomcat']['#{tomcat_name}'][:name]}") // doesn't work
end
end
The last log throws an error since the access with #{tomcat_name} is nil. I'm new to ruby. How do I access with key as the tomcat_name ?
In normal code, you'd write:
node['obi']['tomcat'][tomcat_name][:name]
In a string interpolation (useless here, because it's the only thing in the string in this case), it is completely the same:
"#{node['obi']['tomcat'][tomcat_name][:name]}"
#{} only works in double quote, as "#{tomcat_name}".
But you don't need the syntax here, just use [tomcat_name] directly.
When I saw this question, I'm thinking whether ruby placeholder could be put inside other placeholder in string interpolation. And I found that ruby actually support it, and most interesting thing is that you don't need to escape the " inside the string.
Although it is not very useful in this case, it still works if you write as below:
Chef::Log::info("#{node['obi']['tomcat']["#{tomcat_name}"][:name]}")
Below is an simple example of placeholder inside other placeholder:
tomcats = [
'sandbox',
'sandbox_acserver',
'sandbox_vgw'
]
node = {
'sandbox_name' => "sandbox name",
'sandbox_acserver_name' => "sandbox_acserver name",
'sandbox_vgw_name' => "sandbox_vgw name",
}
tomcats.each do | tomcat |
puts "This is tomcat : #{node["#{tomcat}_name"]}"
end

Translation in .yml with optional parameter

I want to make a translation my_translation with an optional parameter. For example:
> I18n.t('my_translation')
=> "This is my translation"
> I18n.t('my_translation', parameter: 1)
=> "This is my translation with an optional parameter which value is 1"
Is this possible?
Yes, definitely. You just write the translations like this:
my_translation: This is my translation with an optional parameter which value is %{parameter}
Is the parameter really optional? In above translation, you have to provide all parameters.
UPDATE: Sorry, I answered too soon. I don't think it's easy to do. Maybe the easiest way is like this:
> I18n.t('my_translation1')
=> "This is my translation"
> I18n.t('my_translation2', parameter: 1)
=> "This is my translation with an optional parameter which value is 1"
I would say it is possible, though not recommended. You have two completely separate strings, based on your comments in #Yanhao's answer, and I would say they should be two separate entries in your yaml file:
report_name: My report
report_name_with_date: My report on %{date}
Since the existence of the date determines which string to display, you could perhaps test for its existence in in the params hash in a controller method, assign the title to a variable, and then use it in a view. Perhaps something like:
report_date = params[:report_date]
if report_date && report_date.is_a?(Date)
#report_name = I18n.t('report_name_with_date', date: report_date.to_s)
else
#report_name = I18n.t('report_name')
end
If you want behaviour exactly as you have described, you'd need two yaml entries anyway, and you'd have extra convolution, and you'd be doing a I18n no-no by creating a string by concatenating two strings together, which assumes a fixed grammatical sentence structure (not to mention this drives translators up the wall):
report_name_with_date: My report%{on_date}
on_date: on %{date}
with code something like this:
report_date = params[:report_date]
if report_date && report_date.is_a?(Date)
on_date = I18n.t('on_date', date: report_date.to_s)
#report_name = I18n.t('report_name_with_date', on_date: " #{on_date}")
else
#report_name = I18n.t('report_name_with_date', on_date: nil)
end
So, in summary, I'd say go with two separate whole strings, like in the first example.
This is the way i did it!
First set my translation
I18n.t('my_translation', parameter: optional_parameter)
Check if value is nil
optional_parameter = value.nil? "" : "with an optional parameter which value is #{value}"
I18n.t('my_translation', parameter: optional_parameter)
if value is nil =>"This is my translation"
if value is 1 => "This is my translation with an optional parameter which value is 1"
If you're using a number as an optional argument, Rails provides a better way to handle it.
e.g.
invoice:
zero: "Great! You have no pending invoices."
one: "You have only 1 pending invoice."
other: "You have %{count} pending invoices."
>> t("invoice", count: 0)
=> Great! You have no pending invoices.
>> t("invoice", count: 1)
=> You have only 1 pending invoice.
>> t("invoice", count: 5)
=> You have 5 pending invoices.

Resources