I'm struggling to create a working make file.
My structure
root/Makefile
root/src/main.cpp
root/include/
My code
# Define compiler
CC = g++
# Compiler flags
CFLAGS = -g -Wall
# Build target executable
DIR = /src
INCLUDES = ../include
TARGET = main
all: $(TARGET)
$(TARGET): $(TARGET).cpp
cd $(DIR) &
$(CC) $(CFLAGS) -I $(INCLUDES) -o $(TARGET) $(TARGET).cpp
clean:
cd $(DIR) &
$(RM) $(TARGET)
My Error
make: *** No rule to make target main.cpp', needed bymain'. Stop.
EDIT
Inside my main.cpp I have this line at the top which is meant to be found by my Makefile: #include "pugixml.hpp"
I think this should work for you.
All paths are given relative to the folder the Makefile is in. That means the source folder needs to be specified for the source dependencies.
# Define compiler
CC = g++
# Compiler flags
CFLAGS = -g -Wall
# Build target executable
SRC = src
INCLUDES = include
TARGET = main
all: $(TARGET)
$(TARGET): $(SRC)/$(TARGET).cpp
$(CC) $(CFLAGS) -I $(INCLUDES) -o $# $^
clean:
$(RM) $(TARGET)
Use tabs (not spaces) for the commands.
$# resolves to the target (main in this case).
$^ resolves to all of the dependencies (src/main.cpp in this case).
No need to cd into the source folder.
Related
I have a simple project, whose folder structure is something like:
ls -R
.:
build include makefile src
./build:
./include:
myfunc.h
./src:
main.cpp myfunc.cpp
I want to compile the .cpp sources into .o object files, which should end into ./build folder. Using the GNUmake documentation and other sources (e.g. Proper method for wildcard targets in GNU Make), I wrote this makefile:
CXX := g++
CXXFLAGS += -I./include
CXXFLAGS += -Wall
OBJDIR := ./build
SRCDIR := ./src
PROGRAM = release
DEPS = myfunc.h
SRC = $(wildcard $(SRCDIR)/*.cpp)
OBJ = $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRC))
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJ)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm $(PROGRAM) $(OBJ)
But I get the error message: make: *** No rule to make target 'build/main.o', needed by 'release'. Stop.. I tried a lot of different ways but I cannot manage to have my .o files end up in the ./build directory. Instead, everything works if I put them in the root directory of the project. I can also make it work by specifying a rule for each object file, but I'd like to avoid that. What am I missing?
(I am using GNUmake version 4.3)
The problem is here:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
See the $(DEPS)? That expands to myfunc.h. The compiler knows where to find that file (or would if this recipe were executed), because you've given it -I./include, but Make doesn't know where to find it (so it passes over this rule).
Add this line:
vpath %.h include
P.S. If you want to be really clean, you can add a variable:
INCDIR := ./include
CXXFLAGS += -I$(INCDIR)
vpath %.h $(INCDIR)
I am trying to create a makefile for my project, but i seem to run into some errors, as I am testing new things. My file structure is as such:
~/main #root project folder
~/main/include #header files (mostly class headers)
~/main/src #source files
~/main/src/obj #object files
Makefile
(Makefile is in the root project folder)
Makefile:
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
CFLAGS=-Wall -std=c++11 -I$(IDIR)
$(OBJS): $(SRCS) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJS)
gcc -o run $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(OBJS)
For testing purposes I have a single main.cpp in src folder and a random header file in include folder. The error I am getting when running the simple make command is the following:
make: *** No rule to make target `src/obj/%.o', needed by `all'. Stop.
EDIT : With the help of the guys below i came up with the solution
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
CFLAGS=-Wall -std=c++11 -I$(IDIR)
_DEPS = yo.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_SRC = main.cpp
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
$(ODIR)/%.o: $(SRC) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJ)
$(CC) -o run $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJS)
There is a difference in using % in your two cases. When you write:
$(ODIR)/%.o : $(SDIR)/%.cpp $(IDIR)/%.h
that will do pattern substitution, and create a bunch of rules like:
$(ODIR)/foo.o : $(SDIR)/foo.cpp $(SDIR)/foo.h
So it's fine there, although you should use the % explicitly there so it's clear to see what the rule is doing.
But when you use it here:
all : $(ODIR)/%.o
That is literally looking for the target $(ODIR)/%.o for which you don't have a rule. There's no substitution. And you don't have a rule to make that target - hence the error. What you meant to do was have all depend on all the actual objects, for which you'll want to use the wildcard function:
SOURCES = $(wildcard $(SDIR)/*.cpp)
OBJECTS = $(SOURCES:$(SDIR)/%.cpp=$(ODIR)/%.o)
all : $(OBJECTS)
gcc -o run $^ $(CFLAGS)
When you use
OBJS=$(ODIR)/%.o
The %.o part does not expand to anything meaningful. It just remains as the literal value %.o. Same problem exists for DEPS and SRCS as well.
You need to use the wildcard and patsub functions. Instead of
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
use
DEPS=$(wildcard $(IDIR)/*.h)
SRCS=$(wildcard $(SDIR)/*.cpp)
OBJS=$(patsub %.cpp,%.o,$(SRCS))
Im using this code in the makefile, all is going good but the last line.
My code folder looks like this:
Project/bin -> For executable files
Project/build -> For .o files
Project/include -> For .hpp files
Project/src -> For .cpp files
Makefile path: Project/Makefile
# Compiler #
CC = g++
DEBUG = -g
LFLAGS =
CFLAGS = -Wall
# Directories #
SRCDIR = src/
INCDIR = include/
BUILDDIR = build/
BINDIR = bin/
# Objects #
OBJ_NAMES = main.o dfa.o dfaException.o state.o
OBJS = $(addprefix $(BUILDDIR), $(OBJ_NAMES))
# Output #
TARGET = $(BINDIR)pract3
$(TARGET): $(OBJS)
$(CC) $(CCFLAGS) $(LFLAGS) $(OBJS) -o $(TARGET)
$(BUILDDIR)%.o: $(SRCDIR)%.cpp
$(CC) $(CCFLAGS) $(LFLAGS) -c $< -o $(BUILDDIR)$($(notdir $<):.cpp=.o)
The problem is in "$(BUILDDIR)$($(notdir $<):.cpp=.o)". What Im trying to do here is:
$< contains "src/mysrc.cpp" so with $(notdir $<) I get
"mysrc.cpp"
Now, I want to change the file extension to .o, so I use $($(notdir $<):.cpp=.o) And I should get "mysrc.o". But this part is not working:
g++ -c src/main.cpp -o build/
Assembler messages:
Fatal error: can't create build/: Permission denied
Makefile:25: recipe for target 'build/main.o' failed
make: *** [build/main.o] Error 1
I use $(BUILDDIR) To get "build/mysrc.o"
Why does $($(notdir $<):.cpp=.o) somehow delete the file name ?
And now that Im here. I've learned to use make some days ago. Is there something that I should improve here ?
$(notdir) operates on strings.
$(X:Y=Z) operates on the value of the X variable.
So follow your expansions when $< is src/mysrc.cpp
$($(notdir $<):.cpp=.o)
becomes
$(mysrc.cpp:.cpp=.o)
Is that how you would write that?
No, you would write $(<:.cpp=.o).
So invert your operations.
$(notdir $(<:.cpp=.o))
Or, even better and simpler than that just use $# since that's the target you are building and what you want to create.
$(CC) $(CCFLAGS) $(LFLAGS) -c $< -o $#
I have been asked to port our product into another application.(our s/w is running on linux virtualbox)
I have got a directory of their interface files and also a example code on trying to configure their software/hardware. I see their interface files under the s/w directory. In the reference code directory, I see a makefile with the reference to their reference code.
Trying to run their reference code makefile. getting error that
make: *** No rule to make target `../ main.o" :(
Btw donot understand why SIMUDIR = -I\..\custom_simcode\ this is done in the makefile ?
Also not much familiar with crosscompiler syntax !
ifndef CROSS_CC_PREFIX
CROSS_CC_PREFIX=$(CROSS_COMPILE)
endif
PROGRAM = customer_sim
CC=$(CROSS_CC_PREFIX)gcc
LD=$(CROSS_CC_PREFIX)ld
RANLIB=$(CROSS_CC_PREFIX)corelib
CFLAGS= -g
all: $(PROGRAM)
## Include path
SIMUDIR = -I\..\custom_simcode\
CUST_INT_INC = -I./../cust_Intf/DecHandler/inc \
-I./../CCPU
LIBDIR = -L./../cust_Intf \
-L./../cust_IntfApi
LIBS = -lpthread -customercif -customerapi
LDFLAGS= $(LIBDIR) $(LIBS)
SOURCE = ./../custom_simcode/main.c \
./../custom_simcode/custcode_primitives_init.c \
./../custom_simcode/custccp_primitives_init.c
CFLAGS += $(SIMUDIR) $(CUST_INT_INC) -DPRINT_IO_CONSOLE -UADAPT_CCPU_CUSTIF
OBJS = $(SOURCE:.c=.o)
$(PROGRAM): $(OBJS)
$(CC) -o $# $(OBJS) $(LDFLAGS)
main.o: $(SIMUDIR)/main.c $(SIMUDIR) $(CUST_INT_INC)
$(CC) -c -o /main.o $(SIMUDIR)/main.c
clean:
-rm -f $(OBJS) $(OBJS) $(PROGRAM)
Your $(OBJS) list dependencies for $(PROGRAMs) with directories included but your rule for main.o doesn't have same path.
It would be better to have a generic rule to compile C files like
%.o: %.c
$(CC) -c -o $# $<
Then simply assign extra dependencies for each file like:
$(OBJS): $(SIMUDIR) $(CUST_INT_INC)
I'm still quite new to make. I am trying to compile a project in which maketest.cpp and maketest.hpp rests on Users/wen/Projects/maketest with the Makefile itself. Problem is, I want to also compile and link the source files (.cc and .hh) in Users/wen/Projects/include/bigint.
# Macros
INCLUDE = -I/Users/wen/Projects/include/bigint
LIBS =
CC = g++
override FLAGS += -O2
HEADERS= $(wildcard *.hpp) $(wildcard Users/wen/Projects/include/bigint/*.hh)
# EXE Name
INSTALL = maketest
CC_FILES = %.cpp Users/wen/Projects/include/bigint/%.cc
OBJ_FILES = maketest.o $(wildcard Users/wen/Projects/include/bigint/*.o)
# Rules
$(INSTALL): $(OBJ_FILES)
$(CC) $(FLAGS) $^ -o $# $(LIBS)
%.o: $(CC_FILES) $(HEADERS)
$(CC) $(FLAGS) $(INCLUDE) -c $< -o $#
# Installation types
install: $(INSTALL)
release:
#echo "Re-run with parameter:"
#echo "FLAGS=-D_RELEASE"
debug:
#echo "Re-run with parameter:"
#echo "FLAGS=-D_DEBUG"
# Cleaning up
clean:
rm -f $(OBJ_FILES) $(INSTALL)
The code compiles maketest.cpp and links it, but not bigint.
What will be the right way to build and link the files from Users/wen/Projects/include/bigint? Many thanks!
I figured it out at the end, thank you Jay. The problem was I forgot a slash at the front of Users/wen/Projects/include/bigint, so it was not searching from root but instead the project folder. Now it works!
Try explicitly specifying one of the files from bigint in OBJ_FILES (perhaps "bigint.o" ?). I don't think your wildcard is getting what you want.