I'm making images. My steps are:
- create PGM files using a C program
- convert/resize PGM to PNG using Image Magic
- remove (big) PGM files
To do it I use Make and a Bash script.
The Makefile is very simple:
all:
chmod +x d.sh
./d.sh
Most things are done by the script:
#!/bin/bash
# script file for BASH
# which bash
# save this file as d.sh
# chmod +x d.sh
# ./d.sh
# checked in https://www.shellcheck.net/
printf "make pgm files \n"
gcc f.c -lm -Wall -march=native -fopenmp
if [ $? -ne 0 ]
then
echo ERROR: compilation failed !!!!!!
exit 1
fi
export OMP_DISPLAY_ENV="TRUE"
printf "display OMP info \n"
printf "run the compiled program\n"
time ./a.out > a.txt
export OMP_DISPLAY_ENV="FALSE"
printf "change Image Magic settings\n"
export MAGICK_WIDTH_LIMIT=100MP
export MAGICK_HEIGHT_LIMIT=100MP
printf "convert all pgm files to png using Image Magic v 6 convert \n"
# for all pgm files in this directory
for file in *.pgm ; do
# b is name of file without extension
b=$(basename "$file" .pgm)
# convert using ImageMagic
convert "${b}".pgm -resize 2000x2000 "${b}".png
echo "$file"
done
printf "delete all pgm files \n"
rm ./*.pgm
echo OK
printf "info about software \n"
bash --version
make -v
gcc --version
convert -version
convert -list resource
# end
I do not know Make well so I used Bash which I know better. It works well for me, but I read about Make and CMake. Should I change it?
naive explanation:
- My program is small (one file).
- The dependency tree is very simple (2 libraries which I do not have to recompile).
- Compilation time is very short, so I do not need a staged compilation
- Usually, I create a directory with a descriptive name for the program so the files (now 3) do not need descriptive names and I use short names with an extension that explains the function of the file.
I like that I can run all the tasks with one command (with the easy name make
) and go away.
1 Answer 1
- Your
chmod
needs to go away;d.sh
should already have the correct permissions, including when extracted from a source archive - You should probably delete all of your output diagnostic fluff.
f.c
andd.sh
are very bad filenames. The former should probably be renamed tofractal.c
or somesuch.- You've mis-used make. The whole point of make is to express a dependency tree, and to be able to ask for anything in that tree to be generated, in turn generating any missing or out-of-date dependencies on the filesystem. You need to re-think output files (e.g.
png
) to be make targets, input files (.pgm
,.c
) to be inputs to recipes, and programsgcc
andconvert
to be the commands within those recipes. Once done, your bash script can go away entirely. - Don't use
a.out
. Give your binary a meaningful name. - A side-effect of the above is that checking like this:
if [ $? -ne 0 ]
then
echo ERROR: compilation failed !!!!!!
exit 1
fi
can be deleted; make
is smart enough to understand when commands fail.
Re. image filenames such as 1_4000_Fatou_abi_LSCM_zp_cr
: you ask
do I have to list manually all the files or can I use wildcards like *.pgm ?
It depends on the desired invocation of your makefile. If you want to start with an empty directory and magically make
and have all of your images generate and convert, then you have to manually list all of the file stems in your makefile. If instead you're comfortable with an invocation that looks like
make 1_4000_Fatou_abi_LSCM_zp_cr.png
then you do not have to list out all of your stems. Either you would have your current program just generate all of them (as it would happen now), or (probably better) rework your program so that it accepts a command-line argument and generates a single image on demand. The latter would be much easier to code a meaningful makefile for.
If I were to take a guess, your dependency tree basically looks like this. Beware that it's half untested, and in particular $(IMAGES)
will change based on a few factors including whether you know your image file stems.
#!/usr/bin/make -f
export
CFLAGS=-O3 -lm -Wall -march=native -fopenmp --std=c17
OMP_DISPLAY_ENV=FALSE
MAGICK_WIDTH_LIMIT=100MP
MAGICK_HEIGHT_LIMIT=100MP
IMAGES=image1 image2
PGMS=$(IMAGES:=.pgm)
PNGS=$(IMAGES:=.png)
all: $(PNGS)
%.png: %.pgm
convert $^ -resize 2000x2000 $@
$(PGMS): fractal
./$^
fractal: fractal.o
gcc $$CFLAGS -o $@ $^
%.o: %.c
gcc $$CFLAGS -o $@ $^ -c
clean:
rm -f fractal *.o *.pgm *.png
Output:
$ make
gcc $CFLAGS -o fractal.o fractal.c -c
gcc $CFLAGS -o fractal fractal.o
./fractal
convert image1.pgm -resize 2000x2000 image1.png
(convert
then fails for me due to it being fed a dummy image but the concept is there.)
-
\$\begingroup\$ Thx for the answer . In "IMAGES=image1 image2" do I have to list manually all the files or can I use wildcards like *.pgm ? \$\endgroup\$Adam– Adam2021年07月15日 14:46:35 +00:00Commented Jul 15, 2021 at 14:46
-
\$\begingroup\$ Depends. What are the image names? How many are there? \$\endgroup\$Reinderien– Reinderien2021年07月15日 14:47:07 +00:00Commented Jul 15, 2021 at 14:47
-
\$\begingroup\$ How many : my record is 39 . github.com/adammaj1/implodedcauliflower \$\endgroup\$Adam– Adam2021年07月15日 14:51:24 +00:00Commented Jul 15, 2021 at 14:51
-
\$\begingroup\$ Names are descriptive, like 1_4000_Fatou_abi_LSCM_zp_cr.pgm \$\endgroup\$Adam– Adam2021年07月15日 14:52:36 +00:00Commented Jul 15, 2021 at 14:52
-
\$\begingroup\$ @Adam See edit; there are a few ways you can go but none of them involve wildcards \$\endgroup\$Reinderien– Reinderien2021年07月15日 15:29:31 +00:00Commented Jul 15, 2021 at 15:29