Make two c programs in one makefile - c

Is it possible to make two files in a single makefile? Essentially a program and a programtest. I have seen other answers, but their syntax went completely over my head. Right now my Makefile only makes one of the programs, and I cant figure out how to have it make both
Would it be possible for someone to provide a template for how a Makefile would be structured to compile two programs?

all: main test
test: objects/Math.o objects/Stack.o objects/Queue.o objects/myUnitTesting.o objects/test.o
gcc objects/test.o objects/Math.o objects/Stack.o objects/Queue.o objects/myUnitTesting -o test
main: objects/Stack.o objects/Queue.o objects/Math.o objects/Point.o objects/main.o
gcc objects/main.o objects/Stack.o objects/Queue.o objects/Point.o objects/Math.o -o main
objects/test.o: test.c
gcc -g -Wall -O -c -o objects/test.o test.c
objects/main.o: main.c
gcc -g -Wall -O -c -o objects/main.o main.c
objects/myUnitTesting.o: cs/myUnitTesting.c
gcc -g -Wall -O -c -o objects/myUnitTesting cs/myUnitTesting.c
objects/Math.o: cs/Math.c
gcc -g -Wall -O -c -o objects/Math.o cs/Math.c
objects/Stack.o: cs/Stack.c
gcc -g -Wall -O -c -o objects/Stack.o cs/Stack.c
objects/Queue.o: cs/Queue.c
gcc -g -Wall -O -c -o objects/Queue.o cs/Queue.c
objects/Point.o: cs/Point.c
gcc -g -Wall -O -c -o objects/Point.o cs/Point.c
clean:
rm -f objects/*o main
Then you only need to type:
make all
and it is going to compile your main.c and test.c files

You can multiple exes in one makefile, here is sample for building 2,
you need to do make all to build
prog1: prog1.o
gcc prog1.o -o prog1 2>>compile.log 1>&2
prog2: prog2.o
gcc prog2.o -o prog2 2>>compile.log 1>&2
all: prog1 prog2
.c.o:
gcc -o $# -c $*.c 2>>compile.log 1>&2

Here is a scenario where 2 targets are main1 and main2.
TARGET1 = main1
TARGET2 = main2
$(TARGET1): main1.o
gcc main1.o -o $#
$(TARGET2): main2.o
gcc main2.o -o $#
%.o: %.c
gcc -c $< -o $#
run1: $(TARGET1)
./$(TARGET1)
run2: $(TARGET2)
./$(TARGET2)
all: $(TARGET1) $(TARGET2)
./$(TARGET1)
./$(TARGET2)
Remember that the indentation is a <tab> character, not space characters.
The following command will compile and run main1 executable.
make run1
The following command will compile and run main2 executable.
make run2
The following command will compile and run main1 executable followed by main2 executable.
make all

It is possible.
Here is a simpler version of the Makefile:
all: program programtest
program:
gcc -o program program.c
programtest:
gcc -o programtest programtest.c
Then you just have to type make:
$ make
gcc -o program program.c
gcc -o programtest programtest.c

Related

I've created a Makefile in c that should creates more than one executable, but it does not work

WHAT I NEED TO DO
I'm trying to create a Makefile in c that should create three executable from three different .c files.
I'll want to create Lez4Es1, Lez4Es1v2 and Lez4Es3 as my executable compiling and linking in two different stages.
Something as:
gcc -std=c99 -Wall -pedantic Lez4Es1.c -c
gcc -std=c99 -Wall -pedantic Lez4Es1.o -o Lez4Es1
gcc -std=c99 -Wall -pedantic Lez4Es1v2.c -c
gcc -std=c99 -Wall -pedantic Lez4Es1.v2 -o Lez4Es1v2
gcc -std=c99 -Wall -pedantic Lez4Es3.c -c
gcc -std=c99 -Wall -pedantic Lez4Es3.o -o Lez4Es3
MY SOLUTION
Assuming to have all .c files in the same directory i created this Makefile but it does not work:
CC = gcc
CFLAGS += -std=c99 -Wall -pedantic -g
TARGETS = Lez4Es1 \
Lez4Es1v2 \
Lez4Es3 \
.PHONY: all clean cleanall
% : %.o
$(CC) $(CFLAGS) $^ -o $#
%.o : %.c
$(CC) $(CFLAGS) -c $^
all : $(TARGETS)
clean :
-rm *.o *~ core
cleanall :
-rm *.o *.txt -f $(TARGETS) *~ core
PROBLEMS
When i run $ make it creates executable from .c file and not from .o, this is output of compiler:
$ make
gcc -std=c99 -Wall -pedantic -g Lez4Es1.c -o Lez4Es1
gcc -std=c99 -Wall -pedantic -g Lez4Es1v2.c -o Lez4Es1v2
gcc -std=c99 -Wall -pedantic -g Lez4Es3.c -o Lez4Es3
How to fix to let him do the things i want to do?
There is a method to give executable files a different name than .o files?
Sorry for my bad english and if i didn't explain it well i'm ready to edit it and give you more details, thank you.
Try deleting the built-in rule that creates executables from source files:
% : %.c
(a pattern rule with no recipe cancels that rule).

R_X86_64_PC32 against undefined symbol `WinMain' on cygwin

When I compile my code on the command line, there are no problems:
$ gcc -Wall -O2 -o mess main.c getmatrix.c toktoint.c prtmatrix.c getdist.c
But when I compile via make, it fails:
$ make clean
$ make
/usr/bin/gcc -O2 -Wall -c toktoint.c -o toktoint.o
/usr/bin/gcc -O2 -Wall -c getmatrix.c -o getmatrix.o
/usr/bin/gcc -O2 -Wall -c prtmatrix.c -o prtmatrix.o
/usr/bin/gcc -O2 -Wall -c getdist.c -o getdist.o
/usr/bin/gcc -O2 -Wall -c -o main.o main.c
/usr/bin/gcc -O2 -Wall -o mess toktoint.o
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: /usr/lib/gcc/x86_64-pc-cygwin/10/../../../../lib/libcygwin.a(libcmain.o): in function `main':
/usr/src/debug/cygwin-3.1.7-1/winsup/cygwin/lib/libcmain.c:37: undefined reference to `WinMain'
/usr/src/debug/cygwin-3.1.7-1/winsup/cygwin/lib/libcmain.c:37:(.text.startup+0x82): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `WinMain'
collect2: error: ld returned 1 exit status
make: *** [Makefile:44: mess] Error 1
Here is my Makefile:
CC=/usr/bin/gcc
OPTIMIZATION=2
CFLAGS=-O$(OPTIMIZATION) -Wall
LFLAGS=
TARGET=mess
OBJECTS=toktoint.o \
getmatrix.o \
prtmatrix.o \
getdist.o \
main.o
SOURCES=toktoint.c \
getmatrix.c \
prtmatrix.c \
getdist.c \
main.c
HEADERS=getmatrix.h \
toktoint.h \
prtmatrix.h \
getdist.h
all: $(TARGET)
mess: $(OBJECTS)
$(CC) $(CFLAGS) -o $# $<
%.o: %.c %.h
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(OBJECTS) $(TARGET)
I tried changing various flags, such as "-m64". And other suggestions which I found on stackoverflow, but no success.
If I compile each module on the command line, it also works:
$ make clean
$ gcc -O2 -Wall -c toktoint.c -o toktoint.o
$ gcc -O2 -Wall -c getmatrix.c -o getmatrix.o
$ gcc -O2 -Wall -c prtmatrix.c -o prtmatrix.o
$ gcc -O2 -Wall -c getdist.c -o getdist.o
$ gcc -O2 -Wall -c main.c -o main.o
$ gcc -Wall -O2 -o mess main.o getdist.o getmatrix.o prtmatrix.o toktoint.o
So it appears the problem is with make or Makefile.
Look at the output from make again, especially the linker line:
/usr/bin/gcc -O2 -Wall -o mess toktoint.o
It does not build with all the object files. Most notably, it misses main.o which I assume contains your main function.
The variable $< is only
The name of the first prerequisite
(from this make manual, emphasis mine).
To get all prerequisites (all object files) use $^:
mess: $(OBJECTS)
$(CC) $(CFLAGS) -o $# $^

What is the correct or efficient form to write a Makefile when you need two executables that use the same library?

I'm trying to write a Makefile to compile two programs that include the same .h (also mine), but with my actual Makefile if I type "make" in command line twice in a row, I don't get "bla bla is up to date", it recompile part of the stuff when it's not necessary. Any way to do this in a more efficient form?
Context
producer.c and consumer.c #include random_numbers.h in order to generate random numbers to its functions.
My Makefile
CC = gcc
FLAGS = -Wall -g
LIBS = -lrt -lpthread
HEADER_FILES_DIR = .
INCLUDES = -I $(HEADER_FILES_DIR)
SRCS = e1_producer.c e1_consumer.c $(HEADER_FILES_DIR)/random_num.c
OBJ = $(SRC:.c=.co)
DEPS = $(HEADER_FILES_DIR)/random_num.h
all: e1_producer e1_consumer
random_num.o: random_num.c random_num.h
$(CC) $(FLAGS) -c random_num.c
e1_producer: e1_producer.o random_num.o
$(CC) $(FLAGS) -o producer e1_producer.o random_num.o $(LIBS)
e1_producer.o: e1_producer.c
$(CC) $(FLAGS) -c e1_producer.c $(LIBS)
e1_consumer: e1_consumer.o random_num.o
$(CC) $(FLAGS) -o consumer e1_consumer.o random_num.o $(LIBS)
e1_consumer.o: e1_consumer.c
$(CC) $(FLAGS) -c e1_consumer.c $(LIBS)
clean:
rm producer consumer *.o
Output after two consecutive "make" in the command line
$ make
$ gcc -Wall -g -c e1_producer.c -lrt -lpthread
$ gcc -Wall -g -c random_num.c
$ gcc -Wall -g -o producer e1_producer.o random_num.o -lrt -lpthread
$ gcc -Wall -g -c e1_consumer.c -lrt -lpthread
$ gcc -Wall -g -o consumer e1_consumer.o random_num.o -lrt -lpthread
$ make
gcc -Wall -g -o producer e1_producer.o random_num.o -lrt -lpthread
gcc -Wall -g -o consumer e1_consumer.o random_num.o -lrt -lpthread
Why is this happening? When I do the same with another single program the second $ make returns me "nothing to do, bla bla is up to date"

How to clean object files without using command 'make clean' when compiling with makefile?

What I want to know is how to write a makefile that compiles a program and then removes the object files created in the process with just using command 'make' so I don't have to run command 'make clean' afterwards. Here's my current makefile:
prog: prog.o prog_func.o
gcc prog.o prog_func.o -o prog -Wall -std=c99
prog.o: prog.c prog_func.h
gcc prog.c -c -Wall -std=c99
prog_func.o: prog_func.c prog_func.h
gcc prog_func.c -c -Wall -std=c99
clean:
rm prog.o prog_func.o
EDIT:
And this is how it's done:
prog: prog.o prog_func.o
gcc prog.o prog_func.o -o prog -Wall -std=c99
rm prog.o prog_func.o
prog.o: prog.c prog_func.h
gcc prog.c -c -Wall -std=c99
prog_func.o: prog_func.c prog_func.h
gcc prog_func.c -c -Wall -std=c99
It works now. Thanks for quick responses.
After building executable, you just give the same command (rm command) after the executable command
How about compile without making f files like this
gcc -Wall -o prog prog.c
this command will not produce o files.
I have just taken a sample example.
makebuild: clean prog
prog:
gcc a.c -o a.o
clean:
rm a.o
Running 'make' from command line will first 'rm' a.o file and then run 'gcc a.c -o a.o'. The only problem here is that it will not work for first time as makebuild is calling clean first and it will throw an error as it will not find a.o file. You have to put check that 'rm' only when a.o file is present.
something like this:
clean:
if a.o exist
rm a.o

GNU Makefile, c programming

my current makefile looks likes this
all: hello
hello: hello.o
clang -o hello hello.o
hello.o: hello.c
clang -Wall -std=c99 -c -o hello.o hello.c -lpthread
clean:
rm -f *.o *exe hello
How can I modify it to compile with the following:
clang -std=gnu99 -Wall -o hello hello.c -lpthread
Use
hello: hello.c
clang -std=gnu99 -Wall -o hello hello.c -lpthread
instead of the two rules you have for hello and hello.o now.
When your program gets bigger, however, the separation of compilation to object files and linking may at some point be faster than compiling and linking everything in one go. With separated compilation and linking compilation units that are unmodified do not need to be recompiled every time.
Try this - usually best to do the compiling is a few steps.
all: hello
hello: hello.o
clang -o hello hello.o -lpthread
hello.o: hello.c
clang -Wall -std=c99 -c -o hello.o hello.c
clean:
rm -f *.o hello
Your modification requires just changing a single line; but instead, you should use some variables to make it cleaner:
# C compiler
CC = clang
# Additional libraries
LIBS = -lpthread
# Compiler flags
CCFLAGS = -std=gnu99 -Wall $(LIBS)
# Output executable
OUT = hello
all: hello
hello: hello.o
$(CC) $(CCFLAGS) -o $(OUT) hello.o
hello.o: hello.c
clang $(CCFLAGS) -c -o hello.o hello.c
clean:
rm -f *.o $(OUT)

Resources