Assume I have the following file structure in my home directory
.
|-- foo
| `-- lib
| |-- bar.cpp
| `-- bar.h
|-- baz
| |-- qux.cpp
| `-- qux.h
|-- projects
| `-- src
| |-- makefile
` `-- main.cpp
and that main.cpp looks something like
#include "bar.h"
#include "qux.h"
// does stuff
What should my makefile look like?
Right now, it's something like the following
CC = g++
DEBUG = -g -Wall
STD = -std=c++11
OPTIMIZE = -O0
FOO_LIB = $$HOME/foo/lib
BAZ_LIB = $$HOME/baz
INCLUDES = -I$(FOO_LIB) -I$(BAZ_LIB)
LFLAGS = $(DEBUG) $(STD) $(OPTIMIZE) $(INCLUDES)
CFLAGS = -c $(LFLAGS)
BIN = $$HOME/my-program
OBJ = main.o \
bar.o \
qux.o
all: $(OBJ)
$(CC) $(LFLAGS) $(OBJ) -o $(BIN)
main.o: main.cpp bar.h qux.h
$(CC) $(CFLAGS) main.cpp bar.h qux.h
bar.o: bar.cpp bar.h
$(CC) $(CFLAGS) bar.cpp bar.h
qux.o: qux.cpp qux.h
$(CC) $(CFLAGS) qux.cpp qux.h
clean:
\rm *.o
\rm *.gch
But when I try that, I get
make: *** No rule to make target 'bar.h', needed by 'main.o'. Stop.
How do I let make know where my header files are? Even when I change
main.o to
main.o: main.cpp $(FOO_LIB)/bar.h $(BAZ_LIB)/qux.h
$(CC) $(CFLAGS) main.cpp $(FOO_LIB)/bar.h $(BAZ_LIB)/qux.h
it doesn't seem to work (at least with my more complicated real makefile).
Even if it did work, it seems like there's way too much mental overhead in
terms of making sure all of my dependencies are properly prefixed. (I took a
look at http://mad-scientist.net/make/autodep.html, but the sed stuff in
there is pretty impenetrable, and I'd like to sort of understand what I'm doing
so I can document it.)
#Etan Reisner
Let's assume my main.cpp #includes n headers in m library directories.
Does that mean my main.o recipe looks like this
main.o: main.cpp \
/path/to/foo1/bar1.h \
...
/path/to/foo1/barI.h \
...
/path/to/fooM/baz1.h \
...
/path/to/fooM/bazJ.h
$(CC) $(CFLAGS) main.cpp
If so, that looks like a lot of repetative work. Is there a straightforward
way of simplifying that?
Related
I'm trying to create a Makefile for my C++ project, which has the following structure:
root
├── include/
| └──external
| └── stb_image.h
│ └── all .h files here
├── src/
| └── main.cpp
│ └── all .cpp files here
└── Makefile
To compile this project, I'm trying to use the Makefile proposed in this answer, which is for gcc, but I have added CC:=g++ so it should work (I think):
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
EXE := $(BIN_DIR)/color
SRC := $(wildcard $(SRC_DIR)/*.cpp)
OBJ := $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
CPPFLAGS := -Iinclude -MMD -MP
CFLAGS := -g -std=c++2a -Wall
LDFLAGS := -Llib
LDLIBS := -lpthread
CC := g++
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
But when running make I obtain a very long error which I do not understand. I do not know if this error comes from having main.cpp without a main.h.
I need this makefile because I want to separate the declarations and the implementations of my project. Before doing that, I had everything done in headers files and I could compile my project with the following command:
g++ -g -std=c++2a -Wall -Isrc/include -o bin/color.exe src/main.cc -lpthread
Any idea what am I doing wrong? I still do not know a lot about Makefiles, so maybe I'm doing something weird.
I have the following structure for a project and I am just starting to introduce a Makefile to build the software:
├── Makefile
├── README.md
├── cg
│ └── cg.c
└── utilities
├── utilities.c
└── utilities.h
I am trying to put object files in a directory called obj yet I can't seem to get it working.
My makefile looks like:
CC=mpicc
CFLAGS=-O3 -std=c99
LIBS=
MKDIR_P = mkdir -p
make_build_dir:
#mkdir -p obj/
utilities.o: utilities/utilities.c
$(CC) $(CFLAGS) -o ./obj/$# -c $<
cg.o: cg/cg.c
$(CC) $(CFLAGS) -o ./obj/$# -c $<
.PHONY: make_build_dir
cg.exe: make_build_dir utilities.o cg.o
$(CC) $(CFLAGS) -o $# $<
clean:
rm -fr obj
rm cg.exe
Yet this generates the following error:
a#a:b/b ‹master*›$ make cg.exe
mpicc -O3 -std=c99 -o ./obj/utilities.o -c utilities/utilities.c
mpicc -O3 -std=c99 -o ./obj/cg.o -c cg/cg.c
cg/cg.c:133:3: warning: implicit declaration of function 'decompose' is invalid in C99
[-Wimplicit-function-declaration]
decompose(num_chunks, chunks_per_rank,me, &settings);
^
1 warning generated.
mpicc -O3 -std=c99 -o cg.exe make_build_dir
clang: error: no such file or directory: 'make_build_dir'
make: *** [cg.exe] Error 1
How can I get it to generate the object files in the obj directory and then an executable in the top-level directory?
This linking part of the makefile
cg.exe: make_build_dir utilities.o cg.o
$(CC) $(CFLAGS) -o $# $<
has two issues. First, $< refers to the first prerequesite of the target cg.exe, and that is make_build_dir. Declaring it as .PHONY doesn't help here, it's simply passed to $(CC). Second, utilities.o cg.o both don't exist at this location. You can change the rule to
cg.exe: obj/utilities.o obj/cg.o
$(CC) $(CFLAGS) -o $# $^
Note the automatic variable $^ which refers to all prerequisites. Additionally, the object file targets should be
obj/cg.o: cg/cg.c
$(CC) $(CFLAGS) -o $# -c $<
(identical for utilities.o).
First of all, you need to make_build_dir before making any *.o or make won't have a place to put them.
And you can make the Makefile more generic.
.PHONY: all clean info
.DEFAULT_GOAL := all
SRC_DIRS = cg utilities
OBJ_DIR = obj
EXE = cg.exe
SOURCES = $(foreach path, $(SRC_DIRS), $(wildcard $(path)/*.c))
OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:%.c=%.o)))
$(OBJ_DIR)/%.o: */%.c
$(CC) $(CFLAGS) -o $# -c $<
all: make_build_dir $(EXE)
info:
$(info SOURCES=$(SOURCES))
$(info OBJECTS=$(OBJECTS))
make_build_dir:
#mkdir -p $(OBJ_DIR)
$(EXE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $^
With this Makefile, you can add more source directories to SRC_DIRS and it will automatically compile sources in them.
What does it do? Run make with the -n option to see:
$ make -n
mkdir -p obj
cc -o obj/cg.o -c cg/cg.c
cc -o obj/utilities.o -c utilities/utilities.c
cc -o cg.exe obj/cg.o obj/utilities.o
You can also display the info on the variables by:
$ make info
SOURCES= cg/cg.c utilities/utilities.c
OBJECTS=obj/cg.o obj/utilities.o
I have a project like this:
main --> main.c uses tests/test.h
|
|_ tests (main/tests) --> test.h
--> test1.c implementation of test.h
--> test2.c implementation of test.h
--> test3.c implementation of test.h
I currently have a makefile like this:
all: main.o tests/test1.o tests/test2.o tests/test3.o
gcc -o main main.o tests/test1.o tests/test2.o tests3.o
%.o: %.c test.h
gcc -c $< -o $#
But I feel that it's repetitive (say if I have multiple directories in main). Is there a better way to do this using recursive make definitions?
I'm a beginner, and I just wanted to explore different ways.
Not sure what you mean by recursive, but I'd put all testx.o and testx.c into 2 lists(actually your default rule will pick up all .c files and compile them to .o files) this will probably do the work:
OBJECTS=tests/test1.o tests/test2.o tests/test3.o ...
SOURCES=test1.c test2.c test3.c ...
all: main
main: main.o $(OBJECTS)
gcc -o $# $(OBJECTS)
%.o: %.c test.h
gcc -c $< -o $#
I have the following directory structure:
root-----Makefile
|-----src #all source files here.
|-----obj #all object files here.
|-----bin #the final target.
The contents of Makefile is given below:
TARGET = exec
CC = gcc
CFLAGS = -g -I.
LINKER = gcc -o
LFLAGS = -I. -lm -lpthread
BINDIR = bin
OBJDIR = obj
SRCDIR = src
INTERFACE = interface
STD = -std=c99
PROGRAMSOURCES := $(wildcard $(SRCDIR)/*.c)
PROGRAMINTERFACE:= $(wildcard $(INTERFACE)/*.h)
OBJECTS := $(PROGRAMSOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $(OBJECTS) $(STD)
#pull the dependencies to the .o files
-include $(OBJECTS:.o=.d)
$(OBJECTS) : $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $# $(STD)
$(CC) $(CFLAGS) -MM $< > $*.d
#mv -f $*.d $*.d.tmp
#sed -e 's|.*:|$(OBJDIR)/$*.o:|' < $*.d.tmp > $*.d
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d`
#rm -f $*.d.tmp`
.PHONY : run
run :`
./$(BINDIR)/$(TARGET) ${TYPE} ${INP_FILE}
I have used the tutorial here have been modified to suit the corresponding directory structure. But something has got wrong in the modification and I cannot understand what. The dependency list generated in the .d files is not taken into account i.e. if I change a .h the rules are not compiling.
You appear to be producing the dependency files in root/, but looking for them in obj/.
Try changing this:
-include $(OBJECTS:.o=.d)
to this:
-include *.d
There are other improvements you can make, once the makefile is working.
EDIT: further improvements
1) The choice of where to put the dependency files is mainly arbitrary, but if we put them in obj/, we can simplify the $(OBJECTS) rule quite a lot:
-include $(OBJDIR)/*.d
$(OBJECTS): $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -MMD -MP -c $< -o $# $(STD)
2) PROGRAMINTERFACE and INTERFACE aren't used, so we can remove them.
3) Putting -o in LINKER like that is dangerous. And don't forget the automatic variable $^:
LINKER = gcc
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $^ $(STD)
4) It would be wise to give run a prerequisite:
run: $(BINDIR)/$(TARGET)
./$< ${TYPE} ${INP_FILE}
This is my VERY FIRST Makefile and so I have cut and paste junk I have found all over the web. My directory structure is pretty flat and was not thought out for Makefiles. It is:
Project/
Project/Control
Project/NodeMgmt
Project/Common
Project/Interfaces
I am writing a Makefile for Control and would like it to standalone inside Control. It needs to include compile and include from Common & Interfaces. Here's my Makefile:
CC = g++
CFLAGS = -Wall -c
INCLUDES = -I/usr/local/include -I/SuperCool/Ion-1.0.0-snapshot-1/include -I/SuperCool/FastrakSDK-4.0.1-snapshot-1/include/Fastrak/Engine/Core/CoreIpc -I/Projects/Common -I/Projects/Interfaces -I/Projects/NodeMgmt -I/Projects/Controller
LFLAGS = -L/usr/local/lib -L/SuperCool/FastrakSDK-4.0.1-snapshot-1/lib
LIBS = -lCoreIpc4 -lIonOs
VPATH = ../Interfaces/
VPATH = ../Common/
VPATH = ../NodeMgmt/
SRCS = *.cc
OBJS = $(SRCS:.cc=.o)
MAIN = controller
.PHONY: clean
all: $(MAIN)
#echo Built Controller
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
clean:
$(RM) *.o $(MAIN)
It's compiling the first .cc file it finds "-c Controller.cc -o *.o" which make sense but that's all it's compiling and I get a *.o output file, not a Controller.o file. It does not compile any other files.
Here's one problem:
SRCS = *.cc
Make doesn't understand wildcards without the wildcard function:
SRCS = $(wildcard *.cc)
That should get it working; we can make minor improvements later.