How to get fully expanded variables out of configure? - variables

I created a configure.ac file like this:
AC_INIT()
set
the purpose of this is to print every available environment variable the configure script creates using set, so I do this:
user#host:~$ autoconf
user#host:~$ ./configure
which prints a bunch of variables like
build=
cache_file=/dev/null
IFS='
'
LANG=C
LANGUAGE=C
datarootdir='${prefix}/share'
mandir='${datarootdir}/man'
no_create=
So far so good.
The problem is:
I want to expand the variables like ${prefix}/share - but piping
everything to a file example.sh and executing it using bash doesn't work, because bash complains about modifying read-only variables like UID and expansion itself doesn't seem to work either.
I tried using a makefile for this where expansion works, but it complains about newlines in strings, like in the above output the line IFS=' causes an error message Makefile:24: *** missing separator. Stop.
Does anyone have an idea how to get a fully expanded version of configure's output?

The Autoconf manual (I cannot recall or find exactly where) recommends to "manually" do such a kind of variable substitution from within a Makefile.in (or .am if you happen to use Automake):
Makefile.in
[...]
foo.sh: foo.sh.in
$(SED) \
-e 's|[#]prefix#|$(prefix)|g' \
-e 's|[#]exec_prefix#|$(exec_prefix)|g' \
-e 's|[#]bindir#|$(bindir)|g' \
-e 's|[#]datarootdir#|$(datarootdir)|g' \
< "$<" > "$#"
[...]
foo.sh.in
#!/bin/sh
datarootdir=#datarootdir#
du "$datarootdir"

Related

can gcc make test if a defined symbol exists in a source file

Is it possible for gcc make to test if a define exists in one of the source files ie.
ifeq (DEFINED_BLAH_BLAH,3)
#echo is equal to 3
else
#echo is not equal to 3
endif
I've looked at this and to expend on the suggestion from the comment, you could do the following. Not elegant, probably not the best available solution, but it works:
echo -ne "#if 1==MYVAL\n0\n#else\n1\n#endif\n" | cpp -P -imacros test.h
Or to call it through gcc or g++:
echo -ne "#if 1==MYVAL\n0\n#else\n1\n#endif\n" | \
gcc -Xpreprocessor -P -E -imacros test.h -
These would return shell style 0 (true for MYVAL defined in test.h and being 1) or 1 on stdout which you could test for in make / shell.
You may also want to strip all blank lines appending | grep -v '^$'.
To elaborate a bit more on the above. I create (echo) as simple file that I run through the preprocessor which check for equality on given macro and results in 0 or 1 being in the output. -P for cpp, because it's not really a C file and we do not need any of the extra bits in the output. -imacros means retain the macros defined in that file, but discard any output generated by processing it.
It should also be noted, if you'd have any conditional definitions needed to consider any defines passed to the compiler, you would need to pass them to this cpp run as well.
Also note whether you test.h being your header file you know should include the macro defintion. Or main.c being a source file including that (and other) headers doesn't really matter / yields the same result (whatver the value was when cpp was done with the file read and (pre)processed for -imacros.

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.

Why is my Makefile's target specific variable getting set for all targets?

I have a Makefile similar to the following:
target1: DEFAULT_VALUE ?= $(shell bash -c 'read -p "Enter DEFAULT_VALUE to set: " value && echo $$value')
target2:
echo "Hello"
target1:
echo "World"
I expect that the code to set DEFAULT_VALUE will only execute if I run make target1, however I find that it runs even if I run make target2
Does anyone know why this happens?
Your "similar" makefile is not similar enough. Your example above works fine for me: if I run make target2 then the shell command is not executed. If I run make target1, then it is.
Please check your example before posting it here and provide one that really fails.
My suspicion is that in your real environment, whatever is represented by target2 is a prerequisite of whatever is represented by target1, which means that target2 will inherit all of target1's target-specific variable assignments.
With the above Makefile, the shell command will never run, for any target. That's because that style of variable is a recursively expanding variable, so it will be expanded (and the shell command run) every time the variable is used.
If you change the last action in the Makefile to
target1:
echo $(DEFAULT_VALUE)
echo $(DEFAULT_VALUE)
then it will run TWICE when you make target1, echoing potentially two different things
If you want the shell command to run only once, you need to use := to set it. But if you do that, it will be run when the Makefile is read (before its even considering which targets to build), so it will run regardless of which target you eventually specify.
If you want something that will only run when a given target is built, you need to put it in the actions for that target. The easiest way to do that is with a recursive make call
target1:
read -p "Enter DEFAULT_VALUE to set: " value && \
$(MAKE) real_target1 DEFAULT_VALUE=$$value

make targets depend on variables

I want (GNU) make to rebuild when variables change. How can I achieve this?
For example,
$ make project
[...]
$ make project
make: `project' is up to date.
...like it should, but then I'd prefer
$ make project IMPORTANTVARIABLE=foobar
make: `project' is up to date.
to rebuild some or all of project.
Make wasn't designed to refer to variable content but Reinier's approach shows us the workaround. Unfortunately, using variable value as a file name is both insecure and error-prone. Hopefully, Unix tools can help us to properly encode the value. So
IMPORTANTVARIABLE = a trouble
# GUARD is a function which calculates md5 sum for its
# argument variable name. Note, that both cut and md5sum are
# members of coreutils package so they should be available on
# nearly all systems.
GUARD = $(1)_GUARD_$(shell echo $($(1)) | md5sum | cut -d ' ' -f 1)
foo: bar $(call GUARD,IMPORTANTVARIABLE)
#echo "Rebuilding foo with $(IMPORTANTVARIABLE)"
#touch $#
$(call GUARD,IMPORTANTVARIABLE):
rm -rf IMPORTANTVARIABLE*
touch $#
Here you virtually depend your target on a special file named $(NAME)_GUARD_$(VALUEMD5) which is safe to refer to and has (almost) 1-to-1 correspondence with variable's value. Note that call and shell are GNU Make extensions.
You could use empty files to record the last value of your variable by using something like this:
someTarget: IMPORTANTVARIABLE.$(IMPORTANTVARIABLE)
#echo Remaking $# because IMPORTANTVARIABLE has changed
touch $#
IMPORTANTVARIABLE.$(IMPORTANTVARIABLE):
#rm -f IMPORTANTVARIABLE.*
touch $#
After your make run, there will be an empty file in your directory whose name starts with IMPORTANTVARIABLE. and has the value of your variable appended. This basically contains the information about what the last value of the variable IMPORTANTVARIABLE was.
You can add more variables with this approach and make it more sophisticated using pattern rules -- but this example gives you the gist of it.
You probably want to use ifdef or ifeq depending on what the final goal is. See the manual here for examples.
I might be late with an answer, but here is another way of doing such a dependency with Make conditional syntax (works on GNU Make 4.1, GNU bash, Bash on Ubuntu on Windows version 4.3.48(1)-release (x86_64-pc-linux-gnu)):
1 ifneq ($(shell cat config.sig 2>/dev/null),prefix $(CONFIG))
2 .PHONY: config.sig
3 config.sig:
4 #(echo 'prefix $(CONFIG)' >config.sig &)
5 endif
In the above sample we track the $(CONFIG) variable, writing it's value down to a signature file, by means of the self-titled target which is generated under condition when the signature file's record value is different with that of $(CONFIG) variable. Please, note the prefix on lines 1 and 4: it is needed to distinct the case, when signature file doesn't exist yet.
Of course, consumer targets specify config.sig as a prerequisite.

Is there a cmake function to update .pot files?

I am migrating a project from autotools to cmake. I have a question about gettext support.
There is an existing FindGettext.cmake modules that provides a nice function :
GETTEXT_CREATE_TRANSLATIONS(foo.pot ALL fr.po de.po)
where you provide a pot file and translated po fil ; the function takes care of turning the po files into gmo files, and add the proper installation targets to make sure the files can be found at runtime. All good and well.
Now comes the question : how do you update your pot files and you po files when you add new messages ?
For this, autotools would generate a "update-po" target, that (from what I understand), reads a POTFILES.in with the lists of all files containing translated strings, mixes it with other info, and ends up calling xgetext to generate the po. I think the coresponding Makefile task is the one that contains something like :
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \
--files-from=$(srcdir)/POTFILES.in \
--copyright-holder='$(COPYRIGHT_HOLDER)' \
--msgid-bugs-address="$$msgid_bugs_address" \
;; \
*) \
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \
--files-from=$(srcdir)/POTFILES.in \
--copyright-holder='$(COPYRIGHT_HOLDER)' \
--package-name="$${package_gnu}ube" \
--package-version='0.4.0-dev' \
--msgid-bugs-address="$$msgid_bugs_address" \
;; \
esac
So, before I reinvent the wheel, is there an existing cmake function to do the same thing ?
Or do I have to find the xgettext executable, lists the files, and do this by hand ? THe makefile version seems quite complicated (although it seems to handle lots of cases) ; I would not mind not having to write the cmake equivalent ;)
Thanks
PH
Don't let the autotool bloat scare you. :-)
You can use the following code:
SET(_potFile ${PROJECT_NAME}.pot)
ADD_CUSTOM_COMMAND(OUTPUT ${_potFile}
COMMAND ${XGETTEXT_CMD} ${_xgettext_option_list} -o ${_potFile} ${_src_list}
DEPENDS ${_src_list}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Extract translatable messages to ${_potFile}"
)
ADD_CUSTOM_TARGET(pot_file ${_all}
DEPENDS ${_potFile}
)
For C programs, I am using following as _xgettext_option_list
--language=C --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 -s
--package-name=${PROJECT_NAME} --package-version=${PRJ_VER}
I did reinvented the wheel when the FindGettext did not have the option ALL (when it was cmake-2.4) :-)
According to this kde wiki page, using cmake for editing sources is not a good idea. Better use standalone script for updating translations.
In fact, the extraction and merging of messages does not map well onto the CMake concept of out-of-source builds, and CMake can't
provide too much help for this step, either.
Hence, in this tutorial, we will handle the first step with a
standalone shell script, and only the second step will be handled by
CMake.