Makefile: two different executables taking two overlapping subsets of code - c

This is my situation, I am trying to write a Makefile for my c program, it has these components --
2 Headers:
src/header1.h
src/header2.h
N Sources:
src/src1.c
src/src2.c
src/src3.c ...
src/srcn.c
2 Mains:
src/main1.c
src/main2.c
main1.c and main2.c takes all the same src*.c and header*.h files, but in a different way. It would be really nice if I could write my Makefile in this way --
CC := gcc
INCLUDES := $(wildcard src/*.h)
SRC1 := all src*.c sources and main1.c (not main2.c)
SRC2 := all src*.c sources and main2.c (not main1.c)
IFLAGS := $(addprefix -I/,$(INCLUDES))
CFLAGS := -g -Wall -pedantic -std=gnu99 $(IFLAGS)
LDFLAGS := -lm
OBJS1 := all objects from src*.c (i.e. src*.o) and main1.o
OBJS1 := all objects from src*.c (i.e. src*.o) and main2.o
APP1 := app1
APP2 := app2
all: $(APP1) $(APP2)
$(APP1): $(OBJS1)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(APP2): $(OBJS2)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(OBJS1): $(SRC1)
$(CC) $(CFLAGS) -o $# -c $<
$(OBJS2): $(SRC2)
$(CC) $(CFLAGS) -o $# -c $<
clean:
rm $(OBJS1)
rm $(OBJS2)
rm $(APP1)
rm $(APP2)
How do I write the target/prerequisites rule for $SRC1, $SRC2, $OBJS1 and $OBJS2 above ?

COMMON = \
src1.c \
src2.c \
... \
srcn.c
MAIN1 = main1.c
MAIN2 = main2.c
COMOBJ = ${COMMON:.c=.o}
OBJS1 = ${MAIN1:.c=.o} ${COMOBJ}
OBJS2 = ${MAIN2:.c=.o} ${COMOBJ}
I often write macros such as MAIN1.c = main1.c as POSIX requires make to support that notation (and all the variants I've encountered do support it). But beware the vim doesn't think the macro names like that are kosher (which is a bug in vim's recognition of make macros). Then I'd write:
COMMON.c = ...
MAIN1.c = main1.c
...
FILES1.o = ${MAIN1.c:.c=.o} ${COMMON.c:.c=.o}
etc. Not everyone likes this notation.

You should be fine with just a list of objects
OBJS = src1.o src2.o #... etc
main1: main1.o $(OBJS)
main2: main2.o $(OBJS)
and let make use your provided CC, CFLAGS, and LDFLAGS to figure out the rest

Related

Makefile - Compile object with different library

I´m trying to create a Makefile that build a lib and compile the file. My problem is that depending on the %.c file I need to compile with different lib.
The SRC_MLX need the $(LFLAGS) and the SRC don´t. So the gcc compiler don´t allow me to compile the SRC with the LFLAGS. That´s the reason I need to separate.
I´ve tried this way:
SRCS = $(DIR_SRC)/ft_utils.c \
$(DIR_SRC)/ft_adt.c \
$(DIR_SRC)/ft_circle.c \
$(DIR_SRC)/ft_line.c \
$(DIR_SRC)/ft_trgb.c \
$(DIR_SRC)/ft_quadrilateral.c \
$(DIR_SRC)/ft_player.c \
$(DIR_SRC)/ft_color.c
SRCS_MLX = $(DIR_SRC)/win_update.c \
$(DIR_SRC)/ft_vars.c \
$(DIR_SRC)/ft_image.c \
$(DIR_SRC)/ft_map.c
$(NAME): $(LIB_NAME)
$(CC) $(CFLAGS) main.c -I. -I$(DIR_MLX) -L$(DIR_MLX) -L. $(LFLAGS) $(LIB_FLAG) -o $# -g
$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) -c $< -I. -I$(DIR_MLX) -o $#
$(DIR_OBJ)/$(OBJ_MLX).o: $(DIR_SRC)/$(SRCS_MLX).c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) -c $< -I. -I$(DIR_MLX) -L$(DIR_MLX) $(LFLAGS) -o $#
$(LIB_NAME): $(OBJ_MLX) LIB_OBJ
$(AR) $(LIB_NAME) $(OBJ)
ranlib $(LIB_NAME)
LIB_OBJ: $(OBJ)
$(AR) $(LIB_NAME) $(OBJ)
In the example above I´ve tried to create a lib with one kind of files and after that create a lib with the first lib with the others files. But I keep getting this error:
Makefile:41: warning: overriding recipe for target '.objs/'
Makefile:37: warning: ignoring old recipe for target '.objs/'
make: Warning: File 'Makefile' has modification time 454 s in the future
rm -f .objs/ft_utils.o .objs/ft_adt.o .objs/ft_circle.o .objs/ft_line.o .objs/ft_trgb.o .objs/ft_quadrilateral.o .objs/ft_player.o .objs/ft_color.o
rm -f libcub3d.a
rm -f main
make: *** No rule to make target 'src/src/win_update.c', needed by '.objs/win_update.o'. Stop.
How can I compile this objects with different lib?
P.S. Those are my variables:
DIR_OBJ = .objs
DIR_SRC = src
DIR_LIB = lib
DIR_MLX = ./minilibx-linux
NAME = main
LIB_NAME = libcub3d.a
OBJ = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
OBJ_MLX = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS_MLX))
CC = clang
CFLAGS = -Wall -Werror -Wextra
LFLAGS = -lmlx -lm -lX11 -lXext -lbsd
LIB_FLAG = -lcub3d
AR = ar -rc
RM = rm -f
These lines are definitely not right:
$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c
...
$(DIR_OBJ)/$(OBJ_MLX).o: $(DIR_SRC)/$(SRCS_MLX).c
along with the way you've defined SRCS and SRCS_MLX and these:
OBJ = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
OBJ_MLX = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS_MLX))
Just expand the variables in the rule in your head, or else ask make to expand it for you with the info function, and you'll see it's definitely not right:
$(info output is '$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c')

Makefile - Only Makes One of Two Libs

I am new to makefile and am trying to compile several files.
First is called s-chat and the others are RWT (reader-writer) and DP (dining philosopher). They both use my list library, but s-chat needs it to compile with the -m32 flags.
This is what I tried to do: I called one libMonitor.a using lib-adders.o, lib_movers.o, lib_removers.o. The other one is liblist_32 using lib_adders_32.o, lib_removers_32.o, lib_movers_32.o. For some reason, only the first of these two libraries is made, and the other says it cannot find its first dependency.
PTHREADS = /student/cmpt332/pthreads
RTT = /student/cmpt332/rtt
CC = gcc
CFLAGS = -g
CPPFLAGS = -std=c90 -Wall -pedantic
.PHONEY: all clean
ARCH = $(shell uname -sm | tr -d ' ')
ifeq ($(ARCH),SunOS)
ARCH = $(PLATFORM)
PROCESSOR = "$(shell uname -p)"
ifeq ($(PROCESSOR),i386)
ARCH = i86pc
endif
endif
all: s-chat reader-writer-test dining-philosophers-test
RWT_OBJS = reader-writer_$(ARCH).o reader-writer-monitor_$(ARCH).o Monitor_$(ARCH).o libMonitor_$(ARCH).a
reader-writer-test: CPPFLAGS += -I$(PTHREADS)
reader-writer-test: LDFLAGS += -L$(PTHREADS)/lib/$(ARCH)
reader-writer-test: LDLIBS += -lpthreads
reader-writer-test: $(RWT_OBJS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
reader-writer_$(ARCH).o: reader-writer.c reader_writer_monitor.h Monitor.h
reader-writer-monitor_$(ARCH).o: reader-writer-monitor.c reader_writer_monitor.h Monitor.h
DP_OBJS = dining-philosophers_$(ARCH).o dining-philosophers-monitor_$(ARCH).o Monitor_$(ARCH).o libMonitor_$(ARCH).a
dining-philosophers-test: CPPFLAGS += -I$(PTHREADS)
dining-philosophers-test: LDFLAGS += -L$(PTHREADS)/lib/$(ARCH)
dining-philosophers-test: LDLIBS += -lpthreads
dining-philosophers-test: $(DP_OBJS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
dining-philosophers_$(ARCH).o: dining-philosophers.c dining_philosophers_monitor.h Monitor.h
dining-philosophers-monitor_$(ARCH).o: dining-philosophers-monitor.c dining_philosophers_monitor.h Monitor.h
Monitor_$(ARCH).o: Monitor.c Monitor.h
list_adders.o: list_adders.c list.h
list_movers.o: list_movers.c list.h
list_removers.o: list_removers.c list.h
libMonitor_$(ARCH).a: list_adders.o list_movers.o list_removers.o
ar rcs $# $^
list_adders_32.o: CFLAGS += -m32
list_adders_32.o: LDFLAGS += -m32
list_adders_32.o: list_adders.c list.h
list_movers_32.o: CFLAGS += -m32
list_movers_32.o: LDFLAGS += -m32
list_movers_32.o: list_movers.c list.h
list_removers_32.o: CFLAGS += -m32
list_removers_32.o: LDFLAGS += -m32
list_removers_32.o: list_removers.c list.h
liblist_32_$(ARCH).a: list_adders_32.o list_movers_32.o list_removers_32.o
ar rcs $# $^
s-chat: CPPFLAGS += -I$(RTT)/include
s-chat: CFLAGS += -m32
s-chat: LDFLAGS += -L$(RTT)/lib/$(ARCH) -m32
s-chat: LDLIBS += -lRtt -lRttUtils
s-chat: s-chat.o liblist_32_$(ARCH).a
s-chat.o: s-chat.c
%_$(ARCH).o %_32_$(ARCH).o %.o %_32.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
%: %.o
$(CC) $(LDFLAGS) $(LDLIBS) $^ -o $#
clean:
rm -rf *.o *.a reader-writer-test dining-philosophers-test s-chat
This is the error I get:
ar rcs libMonitor_Linuxx86_64.a list_adders.o list_movers.o list_removers.o
ar: list_adders.o: No such file or directory
Makefile:66: recipe for target 'libMonitor_Linuxx86_64.a' failed
make: *** [libMonitor_Linuxx86_64.a] Error 1
And if I make s-chat last, libMonitor is made, but I get the exact same error with liblist_32 and it says it can't find list_adders_32.o
Anyone know what's going on and how to fix this?
Thanks in advance!!
https://www.gnu.org/software/make/manual/make.html#Pattern-Intro
If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets.
%_$(ARCH).o %_32_$(ARCH).o %.o %_32.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
Should be something like
%_$(ARCH).o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
%_32_$(ARCH).o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
%_32.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
But since it seems like all of your sources are in the same directory anyway, you could just delete these rules completely because make already has a built-in rule for %.o: %.c.

GCC symbol lookup error

I try to launch my executable but i got this error:
.dudac/stage/monkey/lib/hello.duda: undefined symbol: DDS_sequence_BoardGlobalParameters_BoardGPSoftState__alloc
Whereas link and compile work fine
Here is my makefile:
# ====================================
# Date : Tue 21, Feb 2017 at 10:15
NAME = hello
CC = /opt/windriver/wrlinux-small/7.0-xxxxxx-3543dr/sysroots/x86_64-wrlinuxsdk-linux/usr/bin/arm-wrs-linux-gnueabi/arm-wrs-linux-gnueabi-gcc
CFLAGS = -g -Wall -DDEBUG -L/opt/PrismTech/Vortex_v2/Device/VortexOpenSpliceRTE/6.7.1p2/RTS/armv7at2_vfp_neon.WRlinux7_gcc/lib -ldcpssac -ldcpsisocpp2
#-g -Wall -DDEBUG -fPIC
LDFLAGS =
DEFS =
INCDIR = -I/home/T0181049/.dudac/stage/monkey//include/ -I/home/T0181049/.dudac/stage/monkey//src/include -I/home/T0181049/.dudac/stage/monkey//plugins/duda/src -I/home/T0181049/.dudac/stage/monkey//plugins/duda/ -I/opt/PrismTech/Vortex_v2/Device/VortexOpenSpliceRTE/6.7.1p2/HDE/armv7at2_vfp_neon.WRlinux7_gcc/include -I/opt/PrismTech/Vortex_v2/Device/VortexOpenSpliceRTE/6.7.1p2/HDE/armv7at2_vfp_neon.WRlinux7_gcc/include/dcps/C/SAC -I/opt/PrismTech/Vortex_v2/Device/VortexOpenSpliceRTE/6.7.1p2/HDE/armv7at2_vfp_neon.WRlinux7_gcc/include/sys -I/opt/PrismTech/Vortex_v2/Device/VortexOpenSplice/6.7.1p1/HDE/x86_64.linux/include -I/opt/PrismTech/Vortex_v2/Device/VortexOpenSplice/6.7.1p1/HDE/x86_64.linux/include/sys -I/opt/windriver/wrlinux-small/7.0-xxxxx-3543dr/sysroots/armv7at2-vfp-neon-wrs-linux-gnueabi/usr/include -I/opt/windriver/wrlinux-small/7.0-xxxxx-3543dr/sysroots/armv7at2-vfp-neon-wrs-linux-gnueabi/usr/include/c++ -I/opt/windriver/wrlinux-small/7.0-xxxxxx-3543dr/sysroots/armv7at2-vfp-neon-wrs-linux-gnueabi/usr/include/c++/4.9.1 -I/opt/windriver/wrlinux-small/7.0-xxxxxx-3543dr/sysroots/armv7at2-vfp-neon-wrs-linux-gnueabi/usr/include/c++/4.9.1/arm-windriverv7atneon-linux-gnueabi -I/opt/windriver/wrlinux-small/7.0-xxxxx-3543dr/sysroots/armv7at2-vfp-neon-wrs-linux-gnueabi/usr/include/c++/4.9.1/backward -I/opt/windriver/wrlinux-small/7.0-xxxxx-3543dr/sysroots/armv7at2-vfp-neon-wrs-linux-gnueabi/usr/include/dtc -I/opt/windriver/wrlinux-small/7.0-xxxxxx-3543dr/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/arm-wrs-linux-gnueabi/gcc/arm-wrs-linux-gnueabi/4.9.1/include -I/opt/windriver/wrlinux-small/7.0-xxxxx-3543dr/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/arm-wrs-linux-gnueabi/gcc/arm-wrs-linux-gnueabi/4.9.1/include-fixed
OBJECTS = main.o
_PATH = $(patsubst /%, %, $(CURDIR))
_CC = #/bin/echo -e " [\033[33mCC\033[0m] $#"; $(CC)
_DD = #/bin/echo -e " [\033[32mDD\033[0m] $#"; $(CC)
_CC_QUIET = #/bin/echo -n; $(CC)
all: $(NAME).duda
$(NAME).duda: $(OBJECTS)
$(_DD) $(CFLAGS) $(DEFS) -shared -o $# $^ -lc $(LDFLAGS)
.c.o:
$(_CC) -c $(CFLAGS) $(DEFS) $(INCDIR) -fPIC $<
$(_CC_QUIET) -MM -MP $(CFLAGS) $(DEFS) $(INCDIR) $*.c -o $*.d > /dev/null &2>&1
clean:
rm -rf *.o *.d *~ $(NAME).duda
How do i resolve that ?
Thanks
During linking you have specified libraries that are not in the standard path
Solutions
link statically
Use LD_LIBRARY_PATH
Use LD_PRELOAD
Use rpath
I try to use rpath just like this but got the same error:
CFLAGS = -g -Wall -DDEBUG -L/opt/PrismTech/Vortex_v2/Device/VortexOpenSpliceRTE/6.7.1p2/HDE/armv7at2_vfp_neon.WRlinux7_gcc/lib -Wl,-rpath,/opt/PrismTech/Vortex_v2/Device/VortexOpenSpliceRTE/6.7.1p2/HDE/armv7at2_vfp_neon.WRlinux7_gcc/lib -ldcpssac -ldcpsisocpp2

Makefile for static library with self-test capability

I want to have Makefile for my static library where I can conditionally build it as program to perform simple self-test. My current Makefille looks like follows:
OBJECTS = sm3.o ./core/sm3_internal.o
INCLUDES = -I. -I./core
CFLAGS = -g -Wall -O3
CC = c99
OUT = libsm3.a
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS) $(INCLUDES)
$(OUT): $(OBJECTS)
ar rcs $(OUT) $(OBJECTS)
At my main library file I have:
#ifdef TEST
main(int argc, int* argv[])
{
//my self-test logic here
}
#endif
Where should I add -DTEST flag? If I add it to CFLAGS and then add line:
test: $(OBJECTS)
library also would be build with main, which obviously is not something I want.
I would suggest that you compile main.c conditionally instead:
$(TESTOUT): $(OBJECTS) $(TESTOBJ)
$(CC) -o $# $<

Creating Makefile that compiles multiple C files for use in Minix

I am trying to create a Makefile that compiles multiple C files for use in Minix. How would I change the Makefile so that it compiles multiple files at the same time? Below is the current state of my Makefile.
CFLAGS = -D_POSIX_SOURCE
LDFLAGS =
CC = cc
LD = cc
PROG = test
OBJS = test.o
$(PROG): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROG)
clean:
rm -rf $(PROG) $(OBJS)
I thought I could just list the other programs after PROG and OBJS such as
PROG = test test2
OBJS = test.o test2.o
but that didn't work. Any ideas? Thanks in advance.
Split it up this way:
PROG1 = test
PROG2 = test2
OBJ1 = test.o
OBJ2 = test2.o
$(PROG1): $(OBJ1)
$(LD) $(LDFLAGS) $(OBJ1) -o $(PROG1)
$(PROG2): $(OBJ2)
$(LD) $(LDFLAGS) $(OBJ2) -o $(PROG2)
etc

Resources