Can you use make to process command line specified files? - shell

This is exactly what I want to do: I wonder if I can define a rule in make, such that I can provide make a .o file through the command line, and then that command line will be processed with the command
arm-none-eabi-objdump -D <object file>
The idea is to simplify debugging by not having to do that command by hand but rather do something like:
debug file.o
If make can't do this is there any way to do this?

Sort of. You can create a rule like:
%.dump : %.o; arm-none-eabi-objdump -D $^
then do:
$ make file.dump
hth

Related

Rewrite rule printout in make file

I am currently using a makefile for cocotb, similar to this.
That consists of a bunch of variable definitions followed by and
include $(shell cocotb-config --makefiles)/Makefile.sim
Where the final commands will be executed.
I run it in Visual studio code, the simulator output message format is (%file,%line|%column). I want them to be shown as (%file:%line:%col). I can easily do it piping the output to sed.
make MODULE=x TESTCASE=y | sed -e 's/,\([0-9]\+\)|\([0-9]\+\)):/:\1:\2):/g'
I was expecting to be able to change the make file so that the output will be edited before shown
Something like
...
.DEFAULT:
make -C $PWD -f $(shell cocotb-config --makefiles)/Makefile.sim \
(all variables/environment) (rule) \
| sed -e 's/,\([0-9]\+\)|\([0-9]\+\)):/:\1:\2):/g
Where "magic rule" would apply the specified rule and pipe its output to sed.
How can I achieve this?
Thank you.
Given your example, it seems like the .DEFAULT target would do what you want:
.DEFAULT:
$(MAKE) -f $$(cocotb-config --makefiles)/Makefile.sim $# \
| sed -e 's/,\([0-9]\+\)|\([0-9]\+\)):/:\1:\2):/g
Edit (from the OP)
The default works when the rule is given, e.g. if I invoke make sim instead of make. For this I can create a default-delegate rule.
More importantly, I have to pass all the variables to the sub make, that can be achieved by using export by itself.
Then, replacing the include command but the following snippets, works for the more common cases.
export
default-delegate: sim
.DEFAULT:
$(MAKE) -f $$(cocotb-config --makefiles)/Makefile.sim $# \
| sed -e 's/,\([0-9]\+\)|\([0-9]\+\)):/:\1:\2):/g'

Print the prerequisites to a target

This is easily a duplicate of this question, but it has not been answered, for what I can see.
Here is my goal: to be able to print the prerequisites to a target.
I have some kind of a solution but it feels like a hack to me.
Say the target is all, and it only has prerequisites, in a file named makefile-1:
all: foo
all: bar baz
I can use another makefile named makefile-2:
all:
ifeq ($(SHOW),yes)
echo $^
else
cat $^
endif
This kind of gives me what I need, when invoked properly:
$ make -f makefile-1 -f makefile-2
cat foo bar baz
$ make -s SHOW=yes -f makefile-1 -f makefile-2
foo bar baz
But I am not sure what to do if the prerequisite actually has a recipe in the original makefile, or if there is a better/cleaner way.
An easier way to show the prerequisites to a target without building the target would probably be to use the -p option (as suggested here) and -q options together, as suggested on the GNU-Make manual page (long name for the option is --print-data-base):
make -qp | grep '^all:'
This will print the database and select only the line which has the target all and its prerequisites. If there is a rule for that target, it would be at the end of the same paragraph (if I am understanding the format of the output correctly).
If multiple makefiles are used, one can specify all of them with the -f option:
make -f makefile-1 -f makefile-2 -qp
This will of course collect prerequisites for the same target from all makefiles, but the target cannot have a rule specified in more than one file.

Bash: replace part of filename

I have a command I want to run on all of the files of a folder, and the command's syntax looks like this:
tophat -o <output_file> <input_file>
What I would like to do is a script that loops over all the files in an arbitrary folder and also uses the input file names to create similar, but different, output file names. The file names looks like this:
input name desired output name
path/to/sample1.fastq path/to/sample1.bam
path/to/sample2.fastq path/to/sample2.bam
Getting the input to work seems simple enough:
for f in *.fastq
do
tophat -o <output_file> $f
done
I tried using output=${f,.fastq,.bam} and using that as the output parameter, but that doesn't work. All I get is an error: line 3: ${f,.fastq,.bam}: bad substitution. Is this the way to do what I want, or should I do something else? If it's the correct way, what am I doing wrong?
[EDIT]:
Thanks for all the answers! A bonus question, though... What if I have files named like this, instead:
path/to/sample1_1.fastq
path/to/sample1_2.fastq
path/to/sample2_1.fastq
path/to/sample2_2.fastq
...
... where I can have an arbitrary number of samples (sampleX), but all of them have two files associated with them (_1 and _2). The command now looks like this:
tophat -o <output_file> <input_1> <input_2>
So, there's still just the one output, for which I could do something like "${f/_[1-2].fastq/.bam}", but I'm unsure how to get a loop that only iterates once over every sampleX at the same time as taking both the associated files... Ideas?
[EDIT #2]:
So, this is the final script that did the trick!
for f in *_1.fastq
do
tophat -o "${f/_1.fastq/.bam}" $f "${f/_1.fastq/_2.fasq}"
done
You can use:
tophat -o "${f/.fastq/.bam}" "$f"
Testing:
f='path/to/sample1.fastq'
echo "${f/.fastq/.bam}"
path/to/sample1.bam
Not an answer but a suggestion: as a bioinformatician, you shoud use GNU make and its option -j (number of parallel jobs). The Makefile would be:
.PHONY:all
FASTQS=$(shell ls *.fastq)
%.bam: %.fastq
tophat -o $# $<
all: $(FASTQS:.bam=.fastq)
Alternative to anubhava's concise solution,
d=$(dirname path/to/sample1.fastq)
b=$(basename path/to/sample1.fastq .fastq)
echo $d/$b.fastq
path/to/sample1.fastq
tophat -o "$d/$b.fastq" "$f"

How to add dependencies to my makefile?

Hi say I have a program called "myProg", it doesn't take any argument but
I would like to add the dependancy to run ONLY when file1 is newer than the
outfile1 (outfile1 is produced the myProg)
The makefile I have is like the following
out : file1 outfile1
myProg
But it seems it always runs myProg to generate a new outfile1 no matter what.
Where am I missing? Do I have to involve the $< and $# in the command line in order
to make the dependency to work? Thanks
Ok, I figured out. its just that the outfile1 needs to be the "out" then it will just work.

How to write a (GNU)makefile with output different than the target?

I have script that takes in a filename and generates multiple files with same name but different extension. I want to write a makefile that depends on files generated with different extension but only specify the filename. I have a dummy example to explain it below.
test_output:test_input
genereate.py -i $^ -o $#
The above makefile dependency generates multiple files with same filename but different extension, but won't generate the actual target. For example, it generates
test_output.a test_output.b test_output.c
The way its written above is not the efficient way as there no actual target, so it runs this even though the output is already there.
How would i specify the makefile so that it reads in the target(test_output) but actually depends on the output file it generates like test_output.a or any of the other files.
If you use GNU make (you didn't say) you can use pattern rules to tell make about a rule that generates multiple outputs based on a single stem. So for example you can write:
%.a %.b %.c : test_input
genereate.py -i $^ -o $*
(it would work a lot better if the input filename was related to the output filenames with the same stem, but the above will work although you'll have to write a different one for each input file).
Typically that's what you want, so that other targets that need these outputs can depend on them.
If you really want to have a target without any extension as well, just create it:
test_output : test_output.a test_output.b test_output.c
%.a %.b %.c : test_input
genereate.py -i $^ -o $*

Resources