Makefile compile twice different define - c

I'm trying to build two binaries with the same sources, just with a different define.
Basically what I'm doing right now is:
OBJ = $(SRC:.cpp=.o)
CPPFLAGS_S = $(INC) -Wall -Wextra -O3 -g -D SERVER
CPPFLAGS_C = $(INC) -Wall -Wextra -O3 -g -D CLIENT
server: CPPFLAGS= $(CPPFLAGS_S)
client: CPPFLAGS= $(CPPFLAGS_C)
server: $(OBJ)
g++ $(OBJ) -o $(NAME_S) $(CPPFLAGS_S) $(LIB)
client: $(OBJ)
g++ $(OBJ) -o $(NAME_C) $(CPPFLAGS_C) $(LIB)
all: server client
Obviously it's not working. What it's doing is compiling everything with the SERVER define, and because the .o files are already there, they will be used again to create the client binary, still using the SERVER define. I could use some help.

Well, it's a pretty fundamental tenet of filesystems that you can only have one file with a given name in the same directory. There's not much make can do about that!
So you have three choices: you can delete all the object files after you build each target, or you can create differently-named object files for each target, or you can build the objects into different subdirectories for each target.
Personally I prefer the latter, so you'd need to write new rules to explain to make how to create a file in a subdirectory:
SERVEROBJ = $(SRC:%.cpp=server/%.o)
CLIENTOBJ = $(SRC:%.cpp=client/%.o)
CXX = g++
CPPFLAGS = $(INC)
CXXFLAGS = -Wall -Wextra -O3 -g
server: CPPFLAGS += -DSERVER
client: CPPFLAGS += -DCLIENT
all: server client
server client:
$(CXX) $^ -o $# $(CXXFLAGS) $(LIB)
server: $(SERVEROBJ)
client: $(CLIENTOBJ)
server/%.o: %.cpp
mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
client/%.o: %.cpp
mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<

Related

How do I write a "selective" Makefile?

noob question here.
I have a directory with a lot of .c files, they're basicely libc functions that I code myself as an exercice.
I write a little main() in these files to test the functions, and I want to write a Makefile that allow me to compile only the file I want to test, for exemple:
make memset.c
And get only the executable of the code wrote in memset.c.
I tried to do something like this:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
all : %.o
$(CC) $(CFLAGS) $<
%.o : %.c
$(CC) $(CFLAGS) $< -c -o $#
But obviously it doens't work. I don't what to put in place of the "all".
I know it's very basic, but I didn't manage to do it, and I did research but didn't find an answer to this specific question.
Thanks in advance for your help.
If you do make -n -p you get a dump of all of the built-in rules in make. In GNU Make 4.1, this includes:
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
So you might just needs a % in your makefile where you currently have all.
You also might find that you don't need those rules which are already built in. Suppose you have three C files, each with a main() as you specify: abs.c, div.c and fmax.c. Your Makefile needs to be no more than two lines:
CFLAGS = -Wall -Wextra -pedantic
all: abs div fmax
which would then allow you to do make abs to make the abs executable, and make all to make them all.
You can define static pattern rules to build the object files and the executables and then invoke make with the name of the executable you want as the goal:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
EXE := $(patsubst %.c,%,$(SRC))
.PHONY: all obj
all: $(EXE)
obj: $(OBJ)
$(EXE): %: %.o
$(CC) $(LDFLAGS) $< -o $#
$(OBJ): %.o: %.c
$(CC) $(CFLAGS) $< -c -o $#
.PHONY: clean
clean:
rm -f $(OBJ) $(EXE)
Then:
$ make memset.o
builds only memset.o,
$ make memset
builds only memset (and memset.o if needed),
$ make obj
builds all object files,
$ make # or make all
builds all executables (and object files if needed), and
$ make clean
deletes all executables and object files.
With wildcard, you can achieve what you want.
Note that if each program depends on only one .c file, you don't need %.o rules:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
SRC := $(wildcard *.c)
EXEC = $(SRC:%.c=%)
all: $(EXEC)
%: %.c
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
And just invoke this way for instance:
make memset
You already have most you to compile the executable selectively:
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
%.o : %.c
$(CC) $(CFLAGS) $< -c -o $#
% : %.o
$(CC) $(LDLAGS) $< -o $#
Then you just need to call make with the target you want, the executable:
make select
If you have several sets of executable with different flags, you can use:
EX0 = drink clean
${EXE0}: % : %.o
$(CC) $(LDLAGS) -lwater $< -o $#
EX1 = burn melt
{EX1}: % : %.o
$(CC) $(LDLAGS) -lfire $< -o $#

How to compile a dll which needs other dlls

I'm trying to cross compile a piece of software I'm doing.
I'm on Linux and I'm having a pretty hard time trying to write a Makefile for compiling a DLL library using SDL2. Here is it:
#the compiler
CC = i686-w64-mingw32-gcc
#the standart ompilation flags of the project
CFLAGS = -O3 -Wall -Wno-unused-variable -Wno-unused-but-set-variable -Wno-implicit-function-declaration
#path to the folder's root, where the holy not build framework is. Relate to this Makefile
PREPATH = ..
#Path to the SDL, SDL_image and Lua includes and libs
SDL2INCLUDES = -I $(PREPATH)/SDL2/include
SDL2LIBS = $(PREPATH)/BINARIES/4windows/SDL2/64/SDL2.dll
SDLIMAGE2INCLUDES = -I $(PREPATH)/SDL2/SDL_image
SDLIMAGE2LIBS = $(PREPATH)/BINARIES/4windows/SDL2_image/64/SDL2_image.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libjpeg-9.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libpng16-16.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libtiff-5.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/libwebp-4.dll $(PREPATH)/BINARIES/4windows/SDL2_image/64/zlib1.dll
#LUAINCLUDES = -I $(PREPATH)/lua/
#LUALIB = $(PREPATH)/lua/ -llua -lm
#Where to put the compiled program
COMPILEPATH = $(PREPATH)/BINARIES/
#Build options
build: NLF.o
cp ./*.o $(COMPILEPATH)
$(CC) $(CFLAGS) -shared -o $(COMPILEPATH)libNLF.dll $(SDL2LIBS) $(SDLIMAGE2LIBS) $(COMPILEPATH)*.o
NLF.o: NLF_osservice.o NLF_error.o NLF_screen.o NLF.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.c
NLF.h.gch: NLF.h
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.h
NLF_osservice.o: NLF_osservice.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.c
NLF_osservice.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.h
NLF_error.o: NLF_error.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_error.c
NLF_error.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_error.h
NLF_screen.o: NLF_screen.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.c
NLF_screen.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.h
#cleaning options
clean-build:
rm -f -v $(COMPILEPATH)*.o
clean-all:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o $(COMPILEPATH)*.so
clean-soft:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o
When running make all, the compilation runs fine, but when it gets to the -shared part, I get this:
../BINARIES/4windows/SDL2/64/SDL2.dll: file not recognized:
I tried to add -L before the Third Party DLL, like this:
SDL2LIBS = -L $(PREPATH)/BINARIES/4windows/SDL2/64/SDL2.dll
SDLIMAGE2LIBS = -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/SDL2_image.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libjpeg-9.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libpng16-16.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libtiff-5.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/libwebp-4.dll -L $(PREPATH)/BINARIES/4windows/SDL2_image/64/zlib1.dll
And then I get undefined reference errors...
The same error if I change the line:
$(CC) $(CFLAGS) -shared -o $(COMPILEPATH)libNLF.dll $(SDL2LIBS) $(SDLIMAGE2LIBS) $(COMPILEPATH)*.o
for
$(CC) $(CFLAGS) $(SDL2LIBS) $(SDLIMAGE2LIBS) -shared -o $(COMPILEPATH)libNLF.dll $(COMPILEPATH)*.o
Does anyone know what's going on?
You should not use -L before library files. -L indicates a library path. For library files, you should use -l (lowercase L).
But, if you're indicating the path to the file, and are including the file extension, you don't need to use -l, though. So the initial Makefile was correct in that sense.
You should provide the full error that you got, not just file not recognized:. I bet this is a file format not recognized error, which probably indicates that you should not be linking against a .dll file, but .lib files. Similar problem here.
I've solved!! here is how
Putting these files within the SDL path:
libSDL2.a, libSDL2.dll.a, libSDL2main.a, libSDL2_test.a, SDL2.lib, SDL2main.lib, and SDL2test.lib
And these with the SDL_image one.:
libSDL2_image.a and libSDL2_image.dll.a
And here is the Makefile:
#the compiler
CC = i686-w64-mingw32-gcc
#the standart ompilation flags of the project
CFLAGS = -O3 -Wall -Wno-unused-variable -Wno-unused-but-set-variable -Wno-implicit-function-declaration
#path to the folder's root, where the holy not build framework is. Relate to this Makefile
PREPATH = ..
#Path to the SDL, SDL_image and Lua includes and libs
SDL2INCLUDES = -I $DS(PREPATH)/SDL2/include
SDL2LIBS = -L$(PREPATH)/SDL2/4windows/SDL2/64 -lmingw32 -lSDL2main -lSDL2
SDLIMAGE2INCLUDES = -I $(PREPATH)/SDL2/SDL_image
SDLIMAGE2LIBS = -L$(PREPATH)/SDL2/4windows/SDL2_image/64 -lSDL2_image
#LUAINCLUDES = -I $(PREPATH)/lua/
#LUALIB = -L $(PREPATH)/lua/ -llua -lm
#Where to put the compiled program
COMPILEPATH = $(PREPATH)/BINARIES/
#Build options
build: NLF.o
cp ./*.o $(COMPILEPATH)
$(CC) $(CFLAGS) -shared $(COMPILEPATH)*.o $(SDL2LIBS) $(SDLIMAGE2LIBS) -o $(COMPILEPATH)libNLF.dll
NLF.o: NLF_osservice.o NLF_error.o NLF_screen.o NLF.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.c
NLF.h.gch: NLF.h
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF.h
NLF_osservice.o: NLF_osservice.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.c
NLF_osservice.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_osservice.h
NLF_error.o: NLF_error.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) NLF_error.c
NLF_error.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) NLF_error.h
NLF_screen.o: NLF_screen.h.gch
$(CC) -c -DBUILD_DLL $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.c
NLF_screen.h.gch:
$(CC) $(CFLAGS) $(SDL2INCLUDES) $(SDLIMAGE2INCLUDES) NLF_screen.h
#cleaning options
clean-build:
rm -f -v $(COMPILEPATH)*.o
clean-all:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o $(COMPILEPATH)*.dll
clean-soft:
rm -f -v ./*.o ./*.h.gch
rm -f -v $(COMPILEPATH)*.o
Now my new problem is how to compile all this stuff to 32 bits windows. But it is an statement for another question.

makefile exit with no reason when compile .pc and .c at the same time. very strange

I am using pro*c in AIX,I want make my .pc file compile to a .so libary. And link it. This is my directory:
ls
connect.pc func.c get_log.pc main.c makefile sql_err.pc
This is my makefile:
#Makefile
CC = cc -g -brtl
CFLAGS = -g -c
ESQL = proc
RM = rm -f
MYHOME = /home/xxx
OBJ = main.o func.o
LIBOBJ = get_log.o connect.o sql_err.o
DBINC = -I$(ORACLE_HOME)/precomp/public
DBLIB = -L$(ORACLE_HOME)/lib -lclntsh
INCLUDE = -I$(MYHOME)/include
.SUFFIXES: .pc .c .o
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
clean:
rm -f *.o *.lis
when I make I get this:
.......
cc -g -brtl -o sql_err.o -g -c sql_err.c -I/home/xxx/include -I/oracle/product/10.2.0/precomp/public -L/oracle/product/10.2.0/lib -lclntsh
rm -f sql_err.c
rm -f sql_err.lis
cc -g -brtl -qmkshrobj -o libmydb.so get_log.o connect.o sql_err.o -L/oracle/product/10.2.0/lib -lclntsh
mv libmydb.so /home/xxxlib
when it done mv libmydb.so ,it exit!!!without wrong message.why?? I also need my .c to compile to .o and finally to an executable file query link libmydb.so.
when I change the squeuce like this put .c.o before .pc.o:
query:$(OBJ)
cc -o $# $(OBJ) -L$(MYHOME)/lib -lmydb
mv $# $(MYHOME)/bin
func.o:func.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
main.o:main.c
$(CC) -c $(CFLAGS) $< $(INCLUDE)
.pc.o:
$(ESQL) include=$(MYHOME)/include iname=$*.pc
$(CC) -o $*.o $(CFLAGS) $*.c $(INCLUDE) $(DBINC) $(DBLIB)
$(RM) $*.c
$(RM) $*.lis
libmydb.so:$(LIBOBJ)
$(CC) -qmkshrobj -o $# $(LIBOBJ) $(DBLIB)
mv $# $(MYHOME)/lib
it give this message,although I have libmydb.so last step:
prepaid(wmfe)/home/xxx/src>make
cc -g -brtl -c -g -c main.c -I/home/xxx/include
cc -g -brtl -c -g -c func.c -I/home/xxx/include
cc -o query main.o func.o -L/home/xxx/lib -lmydb
ld: 0706-006 Cannot find or open library file: -l mydb
ld:open(): A file or directory in the path name does not exist.
make: 1254-004 The error code from the last command is 255.
Stop.
I can't handle this ,very strange,Help!!
By default make will make the first rule in your makefile, but it must not start with a dot. So the default rule in your makefile is libmydb.so and that is being built.
That rule is only dependent on the LIBOBJ and OBJ is not a dependency so it doesn't care about those. It doesn't exit with no reason, it exits because it has done the job you defined for it. There is no error to report.
If you change the order then the default rule is changed and it tries to compile query. This has no dependencies to the library, so it doesn't try to compile that.
If you want to compile everything you should have, for example, a rule all that lists the dependencies. In this case probably libmydb.so and query at least, in correct order. If this is the first rule it will be the default and your compilation will succeed.

Makefile does not make all targets

I am trying to have the compiled obj files in two different folder
dobjects: where the objects have the debug symbol (gcc with -g option)
sobjects: where the objects are compiled without the debug symbols.
Source files are the same,
I have the following makefile.
CC = gcc
CFLAGS = -Wall
OBJS = a.o b.o
SRCS = a.c b.c
SOBJS_DIR = sobjects
DOBJS_DIR = dobjects
SOBJS = $(addprefix $(SOBJS_DIR)/, $(OBJS))
DOBJS = $(addprefix $(DOBJS_DIR)/, $(OBJS))
all: release debug
release: $(SOBJS)
debug: $(DOBJS)
$(DOBJS_DIR)/%.o: CFLAGS += -g
$(DOBJS_DIR)/%.o $(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
clean:
rm dobjects/*
rm sobjects/*
But every time I try "make" only one target is made.
$ make
gcc -Wall -c a.c -o sobjects/a.o
gcc -Wall -c b.c -o sobjects/b.o
$ make
gcc -Wall -g -c a.c -o dobjects/a.o
gcc -Wall -g -c b.c -o dobjects/b.o
any help would be greatly appreciated
This rule does not do what you think it does:
$(DOBJS_DIR)/%.o $(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
Pattern rules with multiple targets tell make that one single invocation of the recipe will build BOTH targets. So when make runs that rule to build $(DOBJS_DIR)/a.o, make believes that $(SOBJS_DIR)/a.o was also built, so it doesn't try to run the rule to build it. But your rule doesn't actually build it, so when you run make a second time it sees that object file is missing and runs the above rule again, to build the missing one.
You have to write this as two different rules:
$(DOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(SOBJS_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#

How to use makefile to compile all sources (some only to object files)?

I'm getting an "undefined reference to main" error on one of my files when trying to compile. I know this is because this file doesn't have a main method. This is just an implementation file for some helper methods, so I only want it compiled to an object file not an executable. I know how to do this if I explicitly tell the makefile what to do for each file, but I'm trying to write a makefile that will compile all of my sources at once. I tried using the -c flag, but then it compiled all of my files to only object files rather than executables. How in the world do I do this?
Here it is:
CC = gcc
CFLAGS = -g -Wall
SRCS = ./src/server.c ./src/client_slave.c ./src/sockaddrAL.c
EXECS = ./bin/server ./bin/client_slave
OBJS = $(SRCS:.c=.o)
all: clean $(SRCS) server client
server: $(OBJS)
$(CC) $(CFLAGS) ./src/server.o -o ./bin/server
client: $(OBJS)
$(CC) $(CFLAGS) ./src/client_slave.o -o ./bin/client_slave
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You should add the -c flag to the rule that builds .o files (your .c.o suffix rule) and not add it to the rule that builds the executables (the $(EXECS) rule).
CC = gcc
CFLAGS = -g -Wall
EXECS = ./bin/server ./bin/client_slave
all: $(EXECS)
./bin/%: ./src/%.o ./src/sockaddrAL.o
$(CC) $(CFLAGS) -o $# $^
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
clean:
#rm -f $(EXECS) $(OBJS)
You didn't show sockAddrAL at all in your question so I assumed it belonged in both executables. Also note that the above syntax assumes GNU make. If you want to use only features available in POSIX standard make you pretty much have to write it all out.
Let implicit rules be your friend. Your entire Makfefile should just be:
CC = clang
CFLAGS = -O0 -g -Wall
SRCS = server.c client_slave.c sockaddrAL.c
OBJS = $(SRCS:.c=.o)
EXECS = server
server: $(OBJS)
clean:
#rm -f $(EXECS) $(OBJS)
Invoke it from the src directory.

Resources