86

This is an incredibly simple question, but I'm new to makefiles. I am trying to make a makefile that will compile two independent programs:

program1:
    gcc -o prog1 program1.c

program2:
    gcc -o prog2 program2.c

All the examples online go into way more details than I need and are confusing! All I really want it to do is to run the two gcc lines. What am I doing wrong?

Rodrigo de Azevedo
  • 1,097
  • 9
  • 17
Sarah
  • 861
  • 1
  • 7
  • 3
  • 6
    The answers bellow are very clear, but you can also just run the command line: `make program1 program2` that will invoke both targets in the very example you gave yourself. If you just want `program1`, you can run just `make` (it will run the first target). If you just want `program2`, run `make program2`. You have more control. And of course, a target `all: program1 program2` will do just that (being it the first, running your 2 other targets). Done. – DrBeco Jun 16 '16 at 05:31
  • 12 years and still not a fulfilling answer? I'm also new to `make` and learned a lot from the answers below. – ranemirusG May 28 '23 at 16:47

8 Answers8

99

Do it like so

all: program1 program2

program1: program1.c
    gcc -o program1 program1.c

program2: program2.c
    gcc -o program2 program2.c

You said you don't want advanced stuff, but you could also shorten it like this based on some default rules.

all: program1 program2

program1: program1.c
program2: program2.c
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 7
    Note that if you want both programs to be built automatically, the `all` target must appear before the individual programs in the makefile, and be the first target in the makefile. – Randall Cook Jan 08 '14 at 02:15
  • 3
    You can put `all` or any other target wherever you want and make it the default for target-less (what you called "automatic") runs of `make` using `.DEFAULT_GOAL:=all`. – underscore_d Sep 19 '15 at 21:08
40

Pattern rules let you compile multiple c files which require the same compilation commands using make as follows:

objects = program1 program2
all: $(objects)

$(objects): %: %.c
        $(CC) $(CFLAGS) -o $@ $<
hmofrad
  • 1,784
  • 2
  • 22
  • 28
  • Instead of program1 and program2, what if you have thousands of ".c" files in various directories, sub-directories. How can we automate the same using above logic? – SH' Jan 22 '21 at 16:19
  • 2
    @SH' Use Make `shell` command to populate `objects` using the output of `find`. E.g., `objects := $(shell find . -type f -iname "*.c" -print | tr -d ".c" | sed 's/\///') ` – hmofrad Jan 22 '21 at 18:33
  • 2
    @hmofrad answer with 'tr' will remove all matching characters ['.', 'c'], not a substring. Fix: `find tests/ -type f -iname '*.cpp' | sed 's/.cpp//g'` – Ben Crowhurst Jul 01 '21 at 03:47
  • I'm using this for learning c++. To quickly compile and test little scripts. What other use cases may be that require this config? – ranemirusG May 28 '23 at 16:51
28
############################################################################
# 'A Generic Makefile for Building Multiple main() Targets in $PWD'
# Author:  Robert A. Nader (2012)
# Email: naderra at some g
# Web: xiberix
############################################################################
#  The purpose of this makefile is to compile to executable all C source
#  files in CWD, where each .c file has a main() function, and each object
#  links with a common LDFLAG.
#
#  This makefile should suffice for simple projects that require building
#  similar executable targets.  For example, if your CWD build requires
#  exclusively this pattern:
#
#  cc -c $(CFLAGS) main_01.c
#  cc main_01.o $(LDFLAGS) -o main_01
#
#  cc -c $(CFLAGS) main_2..c
#  cc main_02.o $(LDFLAGS) -o main_02
#
#  etc, ... a common case when compiling the programs of some chapter,
#  then you may be interested in using this makefile.
#
#  What YOU do:
#
#  Set PRG_SUFFIX_FLAG below to either 0 or 1 to enable or disable
#  the generation of a .exe suffix on executables
#
#  Set CFLAGS and LDFLAGS according to your needs.
#
#  What this makefile does automagically:
#
#  Sets SRC to a list of *.c files in PWD using wildcard.
#  Sets PRGS BINS and OBJS using pattern substitution.
#  Compiles each individual .c to .o object file.
#  Links each individual .o to its corresponding executable.
#
###########################################################################
#
PRG_SUFFIX_FLAG := 0
#
LDFLAGS := 
CFLAGS_INC := 
CFLAGS := -g -Wall $(CFLAGS_INC)
#
## ==================- NOTHING TO CHANGE BELOW THIS LINE ===================
##
SRCS := $(wildcard *.c)
PRGS := $(patsubst %.c,%,$(SRCS))
PRG_SUFFIX=.exe
BINS := $(patsubst %,%$(PRG_SUFFIX),$(PRGS))
## OBJS are automagically compiled by make.
OBJS := $(patsubst %,%.o,$(PRGS))
##
all : $(BINS)
##
## For clarity sake we make use of:
.SECONDEXPANSION:
OBJ = $(patsubst %$(PRG_SUFFIX),%.o,$@)
ifeq ($(PRG_SUFFIX_FLAG),0)
        BIN = $(patsubst %$(PRG_SUFFIX),%,$@)
else
        BIN = $@
endif
## Compile the executables
%$(PRG_SUFFIX) : $(OBJS)
    $(CC) $(OBJ)  $(LDFLAGS) -o $(BIN)
##
## $(OBJS) should be automagically removed right after linking.
##
veryclean:
ifeq ($(PRG_SUFFIX_FLAG),0)
    $(RM) $(PRGS)
else
    $(RM) $(BINS)
endif
##
rebuild: veryclean all
##
## eof Generic_Multi_Main_PWD.makefile
Robert
  • 491
  • 5
  • 9
  • 1
    Thanks for the above code. I use it to compile my .c files. But if i change any of my myHeader.h files, then i need to re-save an the .c file before using 'make' or else it shows "make: Nothing to be done for `all'." whereas actually changes have been made in the .h file. Can we modify the make file to compile after any changes in .h files without re-saving the .c file? and thanks for the above code!!! – jatin3893 Feb 03 '13 at 15:09
  • 4
    "$(OBJS) should be automagically removed right after linking." Doesn't that lead to unnecessary recompilation and, thus, mostly defeat the point of `make`? – underscore_d Sep 19 '15 at 21:07
  • Why do you nee `.SECONDEXPANSION`? – crisron Jul 16 '16 at 10:19
  • In Linux, macOS there is no need to `PRG_SUFFIX`. If you don't want suffix, set `PRG_SUFFIX=""`. Else if you set `PRG_SUFFIX=` or remove that line like `#PRG_SUFFIX=.exe`, you will get the `error: no such file or directory: 'all.o'` error. – Hamid Rouhani Mar 06 '18 at 17:14
10
all: program1 program2

program1:
    gcc -Wall -o prog1 program1.c

program2:
    gcc -Wall -o prog2 program2.c
Erik
  • 88,732
  • 13
  • 198
  • 189
3
all: program1 program2

program1:
    gcc -Wall -ansi -pedantic -o prog1 program1.c

program2:
    gcc -Wall -ansi -pedantic -o prog2 program2.c

I rather the ansi and pedantic, a better control for your program. It wont let you compile while you still have warnings !!

Master C
  • 1,536
  • 4
  • 14
  • 19
1
SRC = a.cpp b.cpp
BIN = $(patsubst %.cpp,%,$(SRC))

all: $(BIN)

clean:
    rm -f $(BIN)

.PHONY: all clean

make all will do:

c++     a.cpp   -o a
c++     b.cpp   -o b

If you set CXX and CXXFLAGS variables make will use them.

1

A simple program's compilation workflow is simple, I can draw it as a small graph: source -> [compilation] -> object [linking] -> executable. There are files (source, object, executable) in this graph, and rules (make's terminology). That graph is definied in the Makefile.

When you launch make, it reads Makefile, and checks for changed files. If there's any, it triggers the rule, which depends on it. The rule may produce/update further files, which may trigger other rules and so on. If you create a good makefile, only the necessary rules (compiler/link commands) will run, which stands "to next" from the modified file in the dependency path.

Pick an example Makefile, read the manual for syntax (anyway, it's clear for first sight, w/o manual), and draw the graph. You have to understand compiler options in order to find out the names of the result files.

The make graph should be as complex just as you want. You can even do infinite loops (don't do)! You can tell make, which rule is your target, so only the left-standing files will be used as triggers.

Again: draw the graph!.

ern0
  • 3,074
  • 25
  • 40
1

This will compile all *.c files upon make to executables without the .c extension as in gcc program.c -o program.

make will automatically add any flags you add to CFLAGS like CFLAGS = -g Wall.

If you don't need any flags CFLAGS can be left blank (as below) or omitted completely.

SOURCES = $(wildcard *.c)
EXECS = $(SOURCES:%.c=%)
CFLAGS = 

all: $(EXECS)
M3RS
  • 6,720
  • 6
  • 37
  • 47