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:

    chmod +x d.sh

Most things are done by the script:

# 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 ]
    echo ERROR: compilation failed !!!!!!
    exit 1

printf "display OMP info \n"

printf "run the compiled program\n"
time ./a.out > a.txt


printf "change Image Magic settings\n"

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"

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 and d.sh are very bad filenames. The former should probably be renamed to fractal.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 programs gcc and convert 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 ]
    echo ERROR: compilation failed !!!!!!
    exit 1

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


CFLAGS=-O3 -lm -Wall -march=native -fopenmp --std=c17

IMAGES=image1 image2

all: $(PNGS)

%.png: %.pgm
    convert $^ -resize 2000x2000 $@

$(PGMS): fractal

fractal: fractal.o
    gcc $$CFLAGS -o $@ $^

%.o: %.c
    gcc $$CFLAGS -o $@ $^ -c

    rm -f fractal *.o *.pgm *.png


$ make
gcc $CFLAGS -o fractal.o fractal.c -c
gcc $CFLAGS -o fractal fractal.o
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
    Jul 15, 2021 at 14:46
  • \$\begingroup\$ Depends. What are the image names? How many are there? \$\endgroup\$
    – Reinderien
    Jul 15, 2021 at 14:47
  • \$\begingroup\$ How many : my record is 39 . github.com/adammaj1/implodedcauliflower \$\endgroup\$
    – Adam
    Jul 15, 2021 at 14:51
  • \$\begingroup\$ Names are descriptive, like 1_4000_Fatou_abi_LSCM_zp_cr.pgm \$\endgroup\$
    – Adam
    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
    Jul 15, 2021 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.