generic makefile to create multiple executable using different flags - makefile

I would like to create a generic Makefile that builds several executables using different compiler flags for each executable without using shell commands. The executable file name should be composed from the source file and a unique post fixed name. It should also produce an assembly or preprocessor file per source file if needed.
For the target BIN_BDG_FILES, the "$<" (exercise-1.1.0.c ) is always the first item from the list (exercise-1.1.0.c exercise-1.1.1.c exercise-1.2.0.c exercise-1.2.1.c) as expected. I tried without success to modify the SRC_FILES using the filter-out function. My intent was to remove the first item from the list for each Target, so that the first item corresponds to the correct target. I am not sure this is the correct approach. Your comments are welcome.
i.e.
This is my attempt at using built in make constructs.
$(BIN_DBG_FILES): $(SRC_FILES)
$(CC) $(DBG_CFLAGS) $(IFLAGS) $< -o $#
echo SRC_FILES := $(filter-out $<, $(SRC_FILES))
Makefile
SHELL = bash
SRC_FILES = $(wildcard *.c)
BIN_FILES = $(patsubst %.c,%,$(SRC_FILES))
BIN_DBG_FILES = $(patsubst %.c,%-dbg,$(SRC_FILES))
SRC_PRE = $(patsubst %.c,%-pre,$(SRC_FILES))
CC = gcc
WARNINGS := -Wall
CFLAGS = -O2 -std=c99 $(WARNINGS)
DBG_CFLAGS = -g -O -std=c99 $(WARNINGS)
PRE_FLAG = -E
IFLAGS = -I.
all: $(BIN_FILES) $(BIN_DBG_FILES) MK-BASH
$(BIN_DBG_FILES): $(SRC_FILES)
$(CC) $(DBG_CFLAGS) $(IFLAGS) $< -o $#
MK-BASH::
for src in $(SRC_FILES); do \
echo $(CC) $(DBG_CFLAGS) $(IFLAGS) $$src -o $${src%.c}-dbg; \
$(CC) $(DBG_CFLAGS) $(IFLAGS) $$src -o $${src%.c}-dbg; \
$(CC) $(DBG_CFLAGS) $(IFLAGS) $$src -o $${src%.c}-dbg; \
$(CC) $(PRE_FLAG) $$src > $${src%.c}-pre; \
done
clean:
rm -f $(BIN_FILES) *-dbg *-pre
This is the output from executing make command.
This is the output from the target BIN_FILES.
gcc -O2 -std=c99 -Wall exercise-1.1.0.c -o exercise-1.1.0
gcc -O2 -std=c99 -Wall exercise-1.1.1.c -o exercise-1.1.1
gcc -O2 -std=c99 -Wall exercise-1.2.0.c -o exercise-1.2.0
gcc -O2 -std=c99 -Wall exercise-1.2.1.c -o exercise-1.2.1
This is the output from target BIN_DBG_FILES which uses the first source file on the list to build all targets. It should use the appropriate file (exercise-1.1.1.c) to build each target file (exercise-1.1.1-dbg).
gcc -g -O -std=c99 -Wall -I. **exercise-1.1.0.c** -o exercise-1.1.0-dbg
gcc -g -O -std=c99 -Wall -I. **exercise-1.1.0.c** -o exercise-1.1.1-dbg
gcc -g -O -std=c99 -Wall -I. **exercise-1.1.0.c** -o exercise-1.2.0-dbg
gcc -g -O -std=c99 -Wall -I. **exercise-1.1.0.c** -o exercise-1.2.1-dbg
This is the output from the target MK-BASH using shell commands.
for src in exercise-1.1.0.c exercise-1.1.1.c exercise-1.2.0.c exercise-1.2.1.c; do \
echo gcc -g -O -std=c99 -Wall -I. $src -o ${src%.c}-dbg; \
gcc -g -O -std=c99 -Wall -I. $src -o ${src%.c}-dbg; \
gcc -g -O -std=c99 -Wall -I. $src -o ${src%.c}-dbg; \
gcc -E $src > ${src%.c}-pre; \
done
output:
gcc -g -O -std=c99 -Wall -I. exercise-1.1.0.c -o exercise-1.1.0-dbg
gcc -g -O -std=c99 -Wall -I. exercise-1.1.1.c -o exercise-1.1.1-dbg
gcc -g -O -std=c99 -Wall -I. exercise-1.2.0.c -o exercise-1.2.0-dbg
gcc -g -O -std=c99 -Wall -I. exercise-1.2.1.c -o exercise-1.2.1-dbg

Use a pattern rule:
DBG: $(BIN_DBG_FILES)
%-dbg: %.c
#echo $(CC) $(DBG_CFLAGS) $(IFLAGS) $< -o $#

Related

Why does ```CFLAGS:=$(CFLAGS) -O3``` not work as expected?

Makefile like this:
CFLAGS := $(CFLAGS) -O3
test: main.o
gcc $(CFLAGS) -o $# $^
clean:
rm test *.o -f
compile 1: command: make, output: gcc -O3 -o test main.c
compile 2: command: make CFLAGS="-Wall -Werror", output: gcc -Wall -Werror -o test main.c
question: why not output: gcc -Wall -Werror -O3 -o test main.c ?
use override directive:
override CFLAGS := $(CFLAGS) -O3
or
override CFLAGS += -O3

How to execute multiple programs in Makefile

Here is part of my Makefile:
FLAGS = -Wall -Werror -std=c99
DEPENDENCIES = p.h
test: s d
#./s < input.dat > output.txt
#./d < output.txt
s: s.o helper.o
gcc -Wall -o $# $^
d: d.o helper.o
gcc -Wall -o $# $^
%.o: %.c ${DEPENDENCIES}
gcc -Wall -c $<
Why is error 1 showing up whenever I call "make test". Is this the proper way of compiling two programs and then executing it through Makefile?
The output:
cc -c -o s.o s.c
cc -c -o helper.o helper.c
gcc -Wall -Werror -std=c99 -o s s.o helper.o
cc -c -o d.o d.c
gcc -Wall -Werror -std=c99 -o d d.o helper.o
make: *** [test] Error 1

Order of arguments to g++ shuffled when parsing makefile

Following makefile:
#Regular c++ rules
CXX=g++
CXXFLAGS=-Wall -march=native -ffast-math -O3
CXX_OBJECTS=AbsNode.o rle16.o rle8.o
# Link command:
test : $(CXX_OBJECTS)
$(CXX) $(CXX_OBJECTS) -o test
# Compilation commands:
$.o : %.cpp
$(CXX) -c $< $(CXXFLAGS) -o $#
Outputs
g++ -Wall -march=native -ffast-math -O3 -c -o AbsNode.o AbsNode.cpp
g++ -Wall -march=native -ffast-math -O3 -c -o rle16.o rle16.cpp
g++ -Wall -march=native -ffast-math -O3 -c -o rle8.o rle8.cpp
while I expect
g++ -c AbsNode.cpp -Wall -march=native -ffast-math -O3 -o AbsNode.o
g++ -c rle16.cpp -Wall -march=native -ffast-math -O3 -o rle16.o
g++ -c rle8.cpp -Wall -march=native -ffast-math -O3 -o rle8.o
Why is the order of arguments to g++ switched compared to the rule stated in makefile???
$.o : %.cpp
You typed $ instead of %, which turned is into a non-template rule. However make has a default rule for C++ file, which was taken instead of yours. The order of arguments match this internal rule.

Creating a simple Makefile to build a shared library

I am trying to create a very basic hand crafted Makefile to create a shared library to illustrate a point.
This is what I have so far:
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99 -Iinclude
CFLAGS = -fPIC -pedantic -Wall -Wextra -march=native -ggdb3
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(shell echo src/*.c)
HEADERS = $(shell echo include/*.h)
OBJECTS = $(SOURCES:.c=.o)
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
When I run make, it attempts to build an application - and ld fails because it can't resolve main().
Problem seems to be with CFLAGS - I have specified -fPIC but that is not working - what am I doing wrong?
Edit
I added the -shared flag as suggested, when I run make, I got this error:
gcc -std=gnu99 -Iinclude -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3 -O0 -D _DEBUG -o example.so src/example.o
/usr/bin/ld: src/example.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
src/example.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [example.so] Error 1
Which seems to be suggesting to revert back to -fPIC only.
BTW, my new CFLAGS setting is:
CFLAGS = -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3
I am running gcc v4.4.3 on Ubuntu 10.0.4.
The solution was to modify the XXFLAGS as follows:
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
Compile with -shared:
gcc -o libfoo.so module1.o module2.o -shared
(This also works on MingW under Windows to produce DLLs.)
Example for C++ files. I've also included a clean target.
.PHONY : clean
CPPFLAGS= -fPIC -g
LDFLAGS= -shared
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS=$(SOURCES:.cpp=.o)
FIKSENGINE_LIBDIR=../../../../lib
FIKSENGINE_INCDIR=../../../../include
TARGET=$(FIKSENGINE_LIBDIR)/tinyxml.so
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(TARGET)
$(TARGET) : $(OBJECTS)
$(CC) $(CPPFLAGS) $(OBJECTS) -o $# $(LDFLAGS)
Since you try to build so file, you probably need -shared.
this is my goto makefile rule for so files:
%.so: %.o ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
can be used like so
CFLAGS+=-fPIC
libmyfoo.so: # create from libmyfoo.o
# or
libmyfoo.so: myfoo.o # create from myfoo.o

Compiling error

I downloaded someone's source code for a program and i needed to make some changes.
Now i want to compile it but it doesn't seem to work.
PROGS = isotociso
COMMON = tools.o bn.o ec.o wiidisc.o rijndael.o
DEFINES = -DLARGE_FILES -D_FILE_OFFSET_BITS=64
LIBS = C:/Dev-Cpp/lib/libwsock32.a C:/Dev-Cpp/lib/libcrypto.a C:/Dev-Cpp/lib/libcomdlg32.a
CC = gcc
#CFLAGS = -Wall -W -Os -Ilibwbfs -I.
CFLAGS = -Wall -m32 -W -ggdb -Ilibwbfs -I.
LDFLAGS = -m32 -static
VPATH+=libwbfs
OBJS = $(patsubst %,%.o,$(PROGS)) $(COMMON)
all: $(PROGS)
$(PROGS): %: %.o $(COMMON) Makefile
$(CC) $(CFLAGS) $(LDFLAGS) $< $(COMMON) $(LIBS) -o $#
$(OBJS): %.o: %.c tools.h Makefile
$(CC) $(CFLAGS) $(DEFINES) -c $< -o $#
clean:
-rm -f $(OBJS) $(PROGS)
Output
C:\Users\Panda\Desktop\uloader_v4.1\src\isotociso\src>make
gcc -Wall -m32 -W -ggdb -Ilibwbfs -I. -DLARGE_FILES -D_FILE_OFFSET_BITS=64 -c i
sotociso.c -o isotociso.o
process_begin: CreateProcess((null), gcc -Wall -m32 -W -ggdb -Ilibwbfs -I. -DLAR
GE_FILES -D_FILE_OFFSET_BITS=64 -c isotociso.c -o isotociso.o, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [isotociso.o] Error 2
What would be the problem?
Looks to me as if gcc is not in your PATH.
It also looks like you need MinGW to get the libraries.
I am no expert in C(++) development under Windows, but my interpretation would be that it can't find the compiler itself. What development environment are you using?
It looks like it can't find a file. Are you sure you have all the required source files?

Resources