Run a .tcl command from a makefile - linux

I am new to writing a makefile which will be executed on a linux machine.
I have the following tasks to do in a makefile:
1)check if the files in the path/directory are exists and modified recently
2)run a .tcl file
I have written the following piece of code..can you please help me.
PATH =/work/source/
task1:
ifeq (,$(PATH))
#echo "error file does not exist!"
endif
#check for files modified
#run the .tcl command
run evaltest.tcl
reports :#echo "reports tbd"
.PHONY : all
all: task1 reports
Please let me know what changes are required for it to run as expected.

You seem to be planning to do way too much work yourself. Your task #1 is typically what make does. So that only leaves task #2. If a Tcl script has the excutable permission and starts with a valid hashbang, you can just execute it. Otherwise invoke tclsh to run it.
Another problem could be that you redefined the PATH variable. On linux, the PATH variable normally contains a list of directories where executable commands can be found. To point to your sources, better use a different variable name, like SRCPATH or so. By redefining PATH, the tclsh command can not be found, unless it is in /work/source.
So the task1 rule of your Makefile could be reduced to:
task1: sourcefile1 sourcefile2
tclsh evaltest.tcl
# Or ./evaltest.tcl
This will execute evaltest.tcl if either sourcefile1 or sourcefile2 is newer than a file called task1. It is assumed that evaltest.tcl will create the task1 file. If either sourcefile doesn't exist and there is no rule to create it, make will tell you about that.

Related

How to execute a program as variable in bash script?

I am writing a program with two inputs prog1 and prog2 which are both files. I save these two variables as program1 and program2 first and then execute these two files in my program using ./"$program1" and ./"program2", but the output is "No such file or directory" when i used ls to check the files are in the same directory as the script. Can anyone tell me how to execute it? thanks!
First, it seems like your brackets are out of place - ./"$program1" is not a valid expression, either loose the brackets or put it like this: "./$program1".
Then to elaborate a bit on David's comment:
There are two ways you can run another script from your script. One is to make them executable like David said.
However, you can also use the 'source' command to read and execute the content of files, even if they are not executable. So the following command would work in any case:
source "./$program1"
Instead of executing it as ./$prog1 execute it as below.
bash $prog1
bash $prog2
where $prog1 and $prog2 are variables which have the path of the bash scripts.

How bash and other smart shells can find executable files?

They handle executable elfs, scripts and symbolic links from PATH, however what the algorithm of this doing? I'm afraid of I cannot find a source code of this part of a shell.
UDP: Oh, I'm stupid. It looks for EACH executable file in PATH, either directory or ordinary file.
Well, the actual search is performed by find_user_command_in_path() in findcmd.c:553.
The algorithm to search for a command ${foo} is basically:
check if ${foo} is absolute: if it is return this path and stop searching
iterate over all elements in PATH: for p in ${PATH}
construct a path ${p}/${foo} and see if it exists
if it exists and is executable return this path and stop searching
I'm no expert in this area, but I'm almost perfectly sure that on Linux the executable bit in file permissions is all that matters. No sophisticated algorithm needed.
Let's say that we have a file called hello in the current directory, and that the file contains just one line: echo "hello"
If you ran chmod 755 on the file and and you subsequently execute the file, then the bash shell will look through every path that you have listed in the PATH variable of say .bashrc, starting with the first path, until it locates the first path that contains your hello executable. Think of PATH as a linked list and think of the bash shell as going through the linked list of paths, path by path. If the bash shell is not running the hello executable that you want it to run, you have one option: put your hello executable in any one of the preceeding paths.
I am lazy. I don't bother to turn hello into an executable i.e. I am not running the chmod command and I just run
bash hello
where the bash shell is going to look for the hello file in the current directory, fork a bash process and the forked bash process is going to run the hello file before the forked bash process dies.
I am using the bash shell as an example but any other shell will behave the same way.

shell script run when I am root but I get a permission denied when it is invoked from a Makefile (still as root)

I need to run a Make script that invokes a shell script.
I can run the shell script directly as root but when running make on the makefile (still as root) make is denied permission to run the same shell script?
The offending line in the Makefile is that one:
PLATFORM=$(shell $(ROOT)/systype.sh)
I could go in and hardcode the value of every PLATFORM variable of every Makefile scrip on the system but that would be pointless fix, I'd like to understand why there is that Permission Denied error:
make[1]: execvp: ../systype.sh: Permission denied
PS: The content of the shell script is not the issue even if the shell script only contain ls or echo linux the Permission is Denied to the Make utility to run the shell script.
PS: I am not a make expert by an mean so if the explanation is related to Make please be as specific as you can.
In your comments above you say when you "run it manually" you use . scriptname.sh, is that correct? You use . followed by scriptname.sh?
That does not run the script, that sources the script. Your statement that scriptname.sh will execute with and without the x permission since it is a shell script is wrong. You can source the script if you have read permissions. But you cannot execute the script unless you have execute permissions.
"Sourcing" means that a new shell is not started: instead your current shell (where you type that command) reads the contents of the script and runs them just as if you'd typed them in by hand, in the current shell. At the end all the side-effects (directory changes, variable assignments, etc.) that were performed in that script are still available in your current script.
"Executing" means that the script is treated like a program, but the program is a new shell that's started, which then reads the contents of the script and executes it. Once the script ends the shell exits and all side-effects are lost.
The $(shell ...) function in make will not source your script (unless you also use . there, which you did not). It will try to run your script. The error you show implies that either systype.sh did not have the execution bit set, or else that it had an invalid #! line. There's no other explanation I can think of.
If sourcing the file really does what you want then why not just use the same method in $(shell ...) that you use in your own personal use:
PLATFORM=$(shell . $(ROOT)/systype.sh)
If changing the user permission didn't work, are you sure that whatever user owns the script is the same user you're using to invoke make? You say you're "running as root"; is the script owned by root? Or is it owned by you and you're running sudo make or similar?
I don't know why you don't just use:
chmod +x systype.sh
and call it a day.
Adding execution permission to the file Group rather that the file User fixed the issue.
PS: I wonder why? It seems the Make utility run shell scripts not with the same user that started Make...

call a shell script(command line tool) inside another shell script

I am using a tool called Droidbox for experiment.
The tool has a shell script droidbox.sh which I can invoke through terminal.
droidbox.sh takes one argument i.e path of the apk
Usage: ./droidbox.sh APK
I want to call the droidbox.sh through a shell script.
I wrote a shell script like
#!/bin/bash
ARG1="/home/xxx/a.apk"
/home/xxx/DroidBox_4.1.1/droidbox.sh "$ARG1"
I am getting error which says
python: can't open file 'scripts/droidbox.py': [Errno 2] No such file or directory
Can anybody point out what am I doing wrong?
Your error message does not come from your script, but from the called one.
It sounds like the droidbox.sh script is not very smart and requires you to set the current working directory before you can call it.
I would typically use also some more variables, so you better see what belongs together:
#!/bin/sh
set -e
BASEDIR="/home/xxx"
DROIDDIR="$BASEDIR/DrroidBox_4.1.1"
APKFILE="$BASEDIR/a.apk"
cd "$DROIDDIR"
"$DROIDDIR/droidbox.sh" "$APKFILE"
If you dont use set -e you better combine commands which need to succeed together:
cd "$DROIDDIR" && "$DROIDDIR/droidbox.sh" "$APKFILE"
Otherwise the cd might fail when the directory is missing and all following commands execute in the wrong directory.
This error is because you're running the script in a different folder than the folder that houses your "scripts/droidbox.py" file. You can fix this in the following way(s):
Move the "scripts/" folder to the directory that you're running this script out of using "mv /path/to/scripts/ ."
Move your customer script to the folder that contains scripts/droidbox.py and run the script from there

Run a command in SCons without dependencies

I want to run a command in SCons which doesn't have any input/output files (actually the input and output are the same file). At the moment I am just manually running it with subprocess.Popen but is there a more SConsy way of doing it?
You can use the Command function to run whatever external command you run via Popen, and you can use the AlwaysBuild function to ensure your command is always run even if the target file exists. Scons doesn't like dependency cycles, so leave the source list empty.
myfile = env.Command('myfile.out', [], 'echo Hello world > $TARGETS')
env.AlwaysBuild(myfile)
The scons wiki also has a recipe for PhonyTargets which makes it easy to set up a lot of simple commands.

Resources