Makefile string variable - variables

I need to create a variable with spaces in my Makefile:
CC=$(LFS_TGT)-gcc -B$(TOOLS)/release/lib/
What is a right way to do that?
UPDATE:
My code does not work, I have an error, something like bash cannot find command -B$(TOOLS)/release/lib/.

If I've guessed correctly as to what you mean, including extra quoting in the variable definition should work, i.e.:
TOOLS = 'dir with spaces'
CC = $(LFS_TGT)-gcc -B$(TOOLS)/release/lib/

Related

How to launch make while appending a list of values to a variable?

In my Makefile I have defined a variable
VAR = -Ddef1 -Ddef2 -Ddef3
I'd like to launch make like this
make VAR+=-Ddef4 -Ddef5
But the space messes things up. How can I set VAR to a list of values, like it's possible to do inside the Makefile? Thanks for tips.
In your Makefile:
VAR = -Ddef1 -Ddef2 -Ddef3 $(EXTRAVAR)
On the command line:
make EXTRAVAR="-Ddef4 -Ddef5"
As frequently with the shell, tokens with spaces must be quoted. On the command line make FOO+= does the same as make FOO=. It does not append, it overwrites (in your case). Thus the trick with a second variable EXTRAVAR.

How do I escape a "$" in bitbake/yocto?

One of my recipes in Yocto need to create a file containing a very specific line, something like:
${libdir}/something
To do this, I have the recipe task:
do_install() {
echo '${libdir}/something' >/path/to/my/file
}
Keeping in mind that I want that string exactly as shown, I can't figure out how to escape it to prevent bitbake from substituting in its own value of libdir.
I originally thought the echo command with single quotes would do the trick (as it does in the bash shell) but bitbake must be interpreting the line before passing it to the shell. I've also tried escaping it both with $$ and \$ to no avail.
I can find nothing in the bitbake doco about preventing variable expansion, just stuff to do with immediate, deferred and Python expansions.
What do I need to do to get that string into the file as is?
Bitbake seems to have particular issues in preventing expansion from taking place. Regardless of whether you use single or double quotes, it appears that the variables will be expanded before being passed to the shell.
Hence, if you want them to not be expanded, you need to effectively hide them from BitBake, and this can be done with something like:
echo -e '\x24{libdir}/something' >/path/to/my/file
This uses the hexadecimal version of $ so that BitBake does not recognise it as a variable to be expanded.
You do need to ensure you're running the correct echo command however. Under some distros (like Ubuntu), it might run the sh-internal echo which does not recognise the -e option. In order to get around that, you may have to run the variant of echo that lives on the file system (and that does recognise that option):
/bin/echo -e '\x24{libdir}/something' >/path/to/my/file
By default this task will be executed as shell function via /bin/sh, but it depends on your system what it will be as you can have a symlink named /bin/sh pointing to bash. The BitBake's manual prevents from using bashism syntax though.
You can consider just adding this task in your recipe as python function:
python do_install () {
with open('/path/to/your/file', 'a') as file:
file.write('${libdir}/something')
}
'a' stands for append.
This should eliminate the problem with variable expansion.
There is no standard way to escape these sorts of expressions that I am aware of, other than to try to break up the expression - accordingly this should work:
do_install() {
echo '$''{libdir}/something' >/path/to/my/file
}
The best solution is simply this:
bitbake_function() {
command $libdir/whatever
}
Bitbake will only expand ${libdir}; $libdir is passed through verbatim.
We don't have to worry about dollar signs that are not followed by {, and in this case, there is no need for libdir to be wrapped in braces.
The only time we run into a problem with just $foo is if we have something like ${foo}bar where the braces are required as delimiters so that bar isn't included into the variable name. In that situation, there are other solutions, such as for instance generating the shell syntax "$foo"bar. This is less cryptic than resorting to \x24.
If you need to use $ in variable assignment, remember that bitbake won't evaluate $whatever so you have to escape it for the underlying shell.
For instance I set gcc/ld Rpath option to use $ORIGIN keyword this way:
TARGET_LDFLAGS_append = " -Wl,-rpath-link=\\$$ORIGIN"
https://lists.yoctoproject.org/pipermail/yocto/2017-September/037820.html
You can define a variable to be a literal dollar sign.
DOLLAR = "$"
do_install() {
echo '${DOLLAR}{libdir}/something' >/path/to/my/file
}
no extra quoting required.

preserve whitespace in preprocessor macro value taken from environment variable

In an Objective-C project I am attempting to take a file path from an environment variable and set it as a location to write generated files. This is used to run test code using xcodebuild in an automated testing environment where the file path is not determined until xcodebuild is called.
In attempt to do this I am entering a preprocessor macro in the Build Settings that references the variable:
BUILDSERVER_WORKSPACE=\#\"$(WORKSPACE)\"
and then setting the value of a string using that macro
NSString *workspaceLocation = BUILDSERVER_WORKSPACE;
in cases where the (string value of) the path for $WORKSPACE does not contain spaces it works fine but in cases where the path has spaces, the macro preprocessor sees the whitespaces as a macro separator and attempts to process them as separate macro definitions.
for example:
$WORKSPACE=/foo/bar/thudblat
will set the value of workspacelocation as #"/foo/bar/thudblat"
but
$WORKSPACE="/foo/bar/thud blat"
ends up creating multiple preprocessor definitions:
#define BUILDSERVER_WORKSPACE #"/foo/bar/thud
#define blat"
I have attempted to stringify the path, but since the presence or absence of whitespace only happens when i call xcodebuild to build and then run and so I cannot get that to work.
In the end, what I want is to simply take the path at $WORKSPACE and set its value to the NSString *workspaceLocation
so that workspaceLocation could potentially be "\foo\bar\thud blat"
I thought I had tried every scheme of quoting and escaping but, the one thing I had not tried was quoting the entire thing as suggested by #nielsbot
BUILDSERVER_WORKSPACE="\#\"$(WORKSPACE)\""
with an unescaped quote at the beginning and end of the entire value statement. Thad did the trick and gave me the string: #"/foo/bar/thud blat" when calling xcodebuild.
You can achieve that with double stringize trick:
#define STRINGIZE_NX(A) #A
#define STRINGIZE(A) STRINGIZE_NX(A)
static NSString *kWorkspace = #( STRINGIZE(BUILDSERVER_WORKSPACE) );
The way it works is very well explained in here: https://stackoverflow.com/a/2751891/351305
If you wish to really read the environment variable at runtime then you can simply obtain it from NSProcessInfo:
NSString *workspaceLocation = NSProcessInfo.processInfo.environment[#"WORKSPACE"];
That will give you the current value of the environment variables, spaces and all.
HTH

Using an environment variable in a PSQL script

Is it possible to use a Linux environment variable inside a .sql file? I'm using the copy/select query to write to an output file, and I'll like to put that directory in a variable. So I want to do something like:
COPY (SELECT * FROM a)
TO $outputdir/a.csv
Outputdir would be set in my environment. Is this possible?
You can store the result of a shell command inside a psql variable like this:
\set afile `echo "$outputdir/a.csv"`
COPY (SELECT * FROM a) TO :'afile';
Another (better in my opinion) solution is to use only psql variables, see this answer of mine about psql variables, which is similar to your example. A example for your case would be:
\set outputdir '/path/to/output'
\set afile :outputdir '/a.csv'
COPY (SELECT * FROM a) TO :'afile';
Note that, in the example, you need to set the variable inside the script file, but you can skip the first line if you set it when you call psql:
psql --set=outputdir="$outputdir" <conn parameters> -f /path/to/yourscript.sql
This appears to work for your use case, provided you single quote the output file name as I mentioned. It will escape any double quotes as well contained within the SQL.
psql -c "$(eval echo '"' $(<envvars.sql | sed 's/"/\\"/g') '"')"
Of course, note that if your file contains any dollar quoted variables, the shell is going to try to interpret as a variable, and your script will break, so you will need to escape any dollar signs you need preserved literally with a backslash.
See also the second snippet in the accepted answer to this question for a possibly more robust answer.
The accepted answer is correct for PostgreSQL running on Unix. Under Windows a different incantation is required for obtaining the value of the environment variable from the CMD shell and for avoiding the carriage return returned by the echo command.
\set afile `set /p=%outputdir%/a.csv`
COPY (SELECT * FROM a) TO :'afile';

Space in path in a shell script

I have a variable
android="/media/New Volume_/android-sdk-linux_86"
I get an error saying that it cannot find the directory
I changed it to android="/media/New\ Volume_/android-sdk-linux_86"
I still get the same error. I even tried
android="/media/'New Volume_'/android-sdk-linux_86"
and I am using "$android" everywhere ...
I am not able to find the error, can someone help me..
Thanks
Take it this is bash? You assign variables with spaces like this:
android="/media/New Volume_/android-sdk-linux_86"
(Note you don't use the $ notation when setting a value.)
And reference them like this:
cd "$android"