Reputation: 1857
I work with C and C++ and thanks to this answer I was able to compile and run my project. Now I am writing a makefile to spare time. But things are getting complicated :
Project structure
- project
- makefile
- client
- bin
- src
- c
- cc
- java
- server
- ...
# Directories
# CLIENT
CLIENT_BIN_DIR = /client/bin/
CLIENT_SRC_C_DIR = /client/src/c/
CLIENT_SRC_CC_DIR = /client/src/cc/
CLIENT_SRC_JAVA_DIR = /client/src/java/
# SECC
SERVER_BIN_DIR = /server/bin/
SERVER_SRC_C_DIR = /server/src/c/
SERVER_SRC_CC_DIR = /server/src/cc/
SERVER_SRC_JAVA_DIR = /server/src/java/
# Files
# CLIENT
CLIENT_BIN = ${CLIENT_BIN_DIR}client_app
CLIENT_SRC_C = ${wildcard ${CLIENT_SRC_C_DIR}*.c}
CLIENT_SRC_CC = ${wildcard ${CLIENT_SRC_CC_DIR}*.cc}
CLIENT_SRC_JAVA = ${wildcard ${CLIENT_SRC_JAVA_DIR}*.java}
# SERVER
SERVER_BIN = ${SERVER_BIN_DIR}server_app
SERVER_SRC_C = ${wildcard ${SERVER_SRC_C_DIR}*.c}
SERVER_SRC_CC = ${wildcard ${SERVER_SRC_CC_DIR}*.cc}
SERVER_SRC_JAVA = ${wildcard ${SERVER_SRC_JAVA_DIR}*.java}
# Flags
CFLAGS = -g -W -Wall
IFLAGS = -I${INC_DIR}
# Compilers
C = gcc
CC = g++
# Rules
all: ${CLIENT_BIN} ${SERVER_BIN}
${CLIENT_BIN}:
${SERVER_BIN}:
// NEED HELP HERE
Now that I have all the sources files, what should I write to the followings steps to every files :
gcc -c -o file.o file.c
g++ -c -o file.o file.cc -I/PATH_TO_C_HEADER
g++ -o APP_NAME C_O_FILES CC_O_FILES
Upvotes: 2
Views: 875
Reputation: 60127
If you must use make, this could help get you started (just for C files):
# CLIENT
CLIENT_BIN_DIR = client/bin/
CLIENT_SRC_C_DIR = client/src/c/
# CLIENT
CLIENT_BIN = $(CLIENT_BIN_DIR)client_app
CLIENT_SRC_C = $(wildcard $(CLIENT_SRC_C_DIR)*.c)
CLIENT_SRC_C_O = $(CLIENT_SRC_C:.c=.o)
CLIENT_SRC_C_D = $(CLIENT_SRC_C:.c=.d)
# Flags
CFLAGS = -g -W -Wall
IFLAGS = -I$(INC_DIR)
# Compilers
C = gcc
#Create header dependency files (included headers are dependencies too)
%.d: %.c
$(C) $(CFLAGS) -MM -MF $@ -MT $*.o $<
#include will remake the dependency files if they need to be
-include $(CLIENT_SRC_C_D)
#O files will be created via the implicit rule
$(CLIENT_BIN): $(CLIENT_SRC_C_O)
$(C) $(CFLAGS) $(LDFLAGS) $^ -o $(@)
all: $(CLIENT_BIN)
https://www.gnu.org/software/make/manual/make.html is really helpful.
Otherwise, if you can, I recommend tup, which is easier, more flexible, faster, and more advanced than make.
Upvotes: 0
Reputation: 426
# client binary depends on c and c++ .o's
$(CLIENT_BIN): $(CLIENT_SRC_C:.c=.o) $(CLIENT_SRC_CC:.cc=.o)
# server binary depends on c and c++ .o's
$(SERVER_BIN): $(SERVER_SRC_C:.c=.o) $(SERVER_SRC_CC:.cc=.o)
# example header dependency (file.cc depends on file.h and file1.h)
$(CLIENT_SRC_CC_DIR)file.o: $(CLIENT_SRC_CC_DIR)file.h $(CLIENT_SRC_CC_DIR)file1.h
GNU Make has implicit rules for compile C and C++ source files and generating the final binary, so there's no need to rewrite them.
Also, you might want to RTFM.
Upvotes: 0
Reputation: 81022
make has built-in rules for compiling C and C++ files into object files, you can use those instead of writing your own by using the built-in flags they expect. Similarly make has a rule for building a binary from object files (as long as the binary matches one of the source files exactly).
Compiling C programs
n.o is made automatically from n.c with a recipe of the form ‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form ‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’. We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
This rule does the right thing for a simple program with only one source file. It will also do the right thing if there are multiple object files (presumably coming from various other source files), one of which has a name matching that of the executable file. Thus,
x: y.o z.o
when x.c, y.c and z.c all exist will execute:
cc -c x.c -o x.o cc -c y.c -o y.o cc -c z.c -o z.o cc x.o y.o z.o -o x rm -f x.o rm -f y.o rm -f z.o
In more complicated cases, such as when there is no object file whose name derives from the executable file name, you must write an explicit recipe for linking.
Each kind of file automatically made into ‘.o’ object files will be automatically linked by using the compiler (‘$(CC)’, ‘$(FC)’ or ‘$(PC)’; the C compiler ‘$(CC)’ is used to assemble ‘.s’ files) without the ‘-c’ option. This could be done by using the ‘.o’ object files as intermediates, but it is faster to do the compiling and linking in one step, so that’s how it’s done.
So just set the right flags (as used in those rules) and add the right .o
file prerequisites to your binary targets and you should be done.
Upvotes: 1