What does "CC=/path/to/directory ./configure" do? - bash

What does CC=/path/to/afl/afl-gcc ./configure do? (see. AFL's Readme)
Is it telling GCC to look into that directory for files?
(Maybe something like a path-variable, because of the =-character?)
Strange thing also: there is no configure-exe. in that directory.

When you write
A=B C
The shell runs the command C with the environment variable A set to B.
The CC environment variable is commonly used to tell configure scripts where a C compiler is located.

This is a combination of two actions:
Set the environment variable CC to /path/to/afl/afl-gcc
Execute ./configure (with that environment variable)
If both actions are on one line, the environent variable is only passed to this command and is not stored in the environment of the current shell.
The CC can be used to tell the configure script which c comiler to use.

Related

Local variables not working in a gnu Makefile?

I am running make on macOS and it is not pleased with any local variables . Take this snippet intended to get the full path to the directory of the Makefile script
setup_for_run:
mkfile_path=$(abspath $(lastword $(MAKEFILE_LIST)))
mkfile_dir=$(dir $(mkfile_path))
echo "scriptdir=$(SCRIPT_DIR)"
export PATH=$($(SCRIPT_DIR)/.venv/bin:$(PATH))
The result of make setup_for_run is:
$make setup_for_run
mkfile_path=/Users/steve/git/hercl/Makefile
mkfile_dir=
echo "scriptdir="
scriptdir=
export PATH=
So we see that none of the local variables are operational. What is the way to get them activated in the gnu make installed by default on macOS ?
Make runs each command in a recipe in its own shell (unless declaring .ONESHELL). Any modified state such as variables is cleared for each command. And, any variables set are never communicated outside make. For this purpose you're more likely to want to source a bash script.
Make are for making files from other files.
There are several alternatives to set the variables:
# Global scope
VARIABLE := myglobal
# Target specific
mytarget: VARIABLE := targetspecific
# Prefix the command
myprefix:
VARIABLE=prefix env

Changing the stack size and LD_LIBRARY_PATH using a Makefile

I would like to be able to have a rule inside my makefile that a changes the stack size and that appends to LD_LIBRARY_FILE the current directory.
In the shell I can just do:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)
ulimit -s SOME_NUMBER
Is there way to make a rule inside a makefile that is equivalent to running this two commands and will update the environment variables after the makefile is run?
You can link the executables with -z stack-size=VALUE or -rpath, which might have a similar effect.
You could push the command characters to the TTY layer and hope that the shell will execute them, but that is a bit nasty. The makefile could also compile a program which does the job using ptrace, but that would be very ugly as well.
No
A child process in bash cannot effect the environment of the calling shell (as #mpez pointed out). This is done on purpose to avoid some security holes. It's possible to export the commands to change the environment variable to a script, and run that script after you run make (which can be automated through another script), but make itself cannot effect the environment of the calling shell.

shellscripts in Makefiles do not work as expected

I found many answers here and elsewhere on the topic, but none that worked. Please help me out here.
I need to set some environment variables, which is partly done in some scripts, called from a master script, partly directly. Here is a minimal Makefile that shows the unwanted behaviour:
FC := ifort
SHELL := /bin/bash
some_target: load_ifort
$(FC) file.f
load_ifort:
source /usr/local2/bin/ifort-compilervars.sh ia32
export LM_LICENSE_FILE=/usr/local2/misc/intel2013/flexlm/server.lic
if I call make, I get an "ifort: command not found" error. If I execute the two comamnds by hand on the command line before calling make, ifort is found and everything is good.
What am I missing???
Each line in a recipe gets executed in a separate subshell. So you create one shell which sources the .sh file, then exits and forgets everything, then another shell which starts with a clean slate.
The straightforward solution in your case would be to collect all these commands in a single variable. I have factored out the LM_LICENSE_FILE assignment because that can be done in Make directly, but you could include that in the FC variable as well.
LM_LICENSE_FILE := /usr/local2/misc/intel2013/flexlm/server.lic
export LM_LICENSE_FILE
FC := source /usr/local2/bin/ifort-compilervars.sh ia32; \
ifort
some_target:
$(FC) file.f
If the shell commands can be straightforwardly run by Make as well, you could include them, or perhaps translate the sh file into Make commands by a simple script.
Another option would be to create a simple wrapper in your PATH; maybe call it fc:
#!/bin/sh
. /usr/local2/bin/ifort-compilervars.sh ia32
ifort "$#"
then just use fc where you currently have $(FC). (If the ifort-compilervars.sh file contains Bash constructs, in spite of the name, you should change the shebang to #!/bin/bash.)
As a rule, only one-liner shell commands "work". From the comment about "bash", it seems likely you are using GNU make. In your example, the word "source" is not found in the GNU make manual's index. (If you found this in a working example, it would be helpful to start from that). There are two types of variables of interest:
makefile variables, which live in the make program
environment variables, which are "exported"
The latter would include $PATH, which is used to find programs. For updating that, you do need shell commands. But (lacking some special provision in the make program), exported variables from a shell script are not passed up into the make program and made available for the next line of the makefile.
You could reorganize the makefile to provide a rule which combines the source command and other initialization into a shell command which then recurs (carrying those variables along) into a subprocess which would then do the compiles. Something like
build:
sh -c "source /usr/local2/bin/ifort-compilervars.sh ia32; \
export LM_LICENSE_FILE=/usr/local2/misc/intel2013/flexlm/server.lic; \
$(MAKE) some_target"
some_target: load_ifort
$(FC) file.f

How to check all variables are being used in a bash script?

Is there are way to check that all variables declared in a bash script are being used? Something analogous to -Wall in c++?
Cheers
There's no built-in way to do this, no, and it can never be done perfectly, because of situations like these:
Suppose the user's Bash profile exports CLASSPATH as an environment variable. Then a Bash script might include a statement like CLASSPATH=... but never refer to CLASSPATH, if its only purpose in assigning to CLASSPATH is to modify the behavior of some program that uses the environment variable (such as java).
Suppose that I create variables a and b, and a variable c whose value is obtained from the user and can be either a or b. I can then use ${!c} to obtain the value of the user-specified variable; a given run of the script might never refer to b (because c is set to 'a'), but a different run of the script might do differently.
That said, you might be interested in the -u option to the set builtin. If your script contains this command:
set -u
then from that point on, it will be an error to refer to a variable or parameter that has not been set. This can help detect typos in variable-names and whatnot. This is obviously much less than what gcc -Wall does (since gcc always gives an error-message when you refer to an undeclared variable), but you may find it beneficial in the same way.

How to handle setting up environment in makefile?

So, to compile my executable, I need to have the library locations set up correctly. The problem is, the setup comes from a bunch of scripts that do the env variable exporting, and what needs to be set up may change (beyond my control) so I need to use those scripts instead of copying their functionality. To compile in regular command line, I need to do something like:
setup library1
setup library2
source some_other_setup_script.bash
g++ blah.c
# setup is a executable on my system that run some scripts
How would I write a makefile that accomplishes that? As far as I tried, the env variable exporting does not carry over (i.e. "export VAR=remember; echo $VAR" won't work)
You can also add environment variables properly with the machinery of GNU make, like so:
export TEST:="Something Good!"
test:
echo $$TEST
This (I think) has different semantics from:
TEST2:="Something not quite so useful?"
test2:
echo ${TEST2}
Which (again, I think) does the substitution within make before passing along to the shell. Note that the export command doesn't work within a target block, just unindented as an immediately executed command.
If variable exporting is not working the way it does on your command line, that suggests that Make is choosing a shell different from the one you're using, with different syntax for handling variables (export VAR=remember; echo $VAR works fine for me). Make uses /bin/sh by default, but you can override this with the SHELL variable, which Make does not import from the environment. I suggest setting SHELL (in the Makefile) to whatever you're using in your environment and trying the export VAR=remember experiment again.
Ultimately you will need to define the variable and execute the compiler in a shell list or even a script, rather than in separate make commands. There are a couple of refinements you could add, however. You could tell make about the script:
maintarget: script.sh blah.c
source script.sh; g++ blah.c
script.sh:
setup include script here
Another thing would be to just execute all that stuff in the same shell
maintarget: blah.c
run this; run that; run the other thing; g++ blah.c
I believe all make versions will run a ; list in the same shell, but you can always force a subshell with (list) or by calling specifically a shell script as a compiler command wrapper.
Don't forget to have the appropriate targets depend on your scripts themselves. BTW, some make versions (pmake aka bsd make) can execute a command when defining a make variable, and all versions of make then exports those. But I don't think gmake can do that.
You could write another shell script that executes all those commands, then prints out variable assignments that make can use. Run the script, pipe its output to a file, then include that file from your Makefile. For example:
Makefile:
all:
echo $(FOO)
test.mk: test.sh
./$< > $#
include test.mk
test.sh
echo "FOO=1"
Running "make" in the directory containing this Makefile produces:
make: Entering directory `/home/luser/build/mktest'
Makefile:7: test.mk: No such file or directory
./test.sh > test.mk
make: Leaving directory `/home/luser/build/mktest'
make: Entering directory `/home/luser/build/mktest'
echo 1
1
make: Leaving directory `/home/luser/build/mktest'
make creates test.mk by running the shell script, then includes it. test.mk contains the output of test.sh, and is parsed as a Makefile. See http://www.gnu.org/software/make/manual/make.html#Include for more details.
We use a variant of this in Mozilla's client.mk to let you define options in a "mozconfig" file:
http://mxr.mozilla.org/mozilla-central/source/client.mk#138
Restatement: How do I get a shell variable into a make file?
Something like:
MYVAR := $(shell echo $(MYVAR)) <any_makefile_additions_here>
So, this defines MYVAR inside a MAKEFILE when an environment variable named MYVAR is also set.
It might be of interest, that, in order to override an option that is already defined in a makefile, make supports (I am referring to GNU Make 3.82, but other version probably too) the option -e.
Example:
Makefile:
CC=gcc
...
Run make:
CC=gcc-4.7
make -e
will use gcc-4.7 instead of gcc.

Resources