Make object file not being created - makefile

I am trying to write a Makefile since it's a good skill to have and all the times I've worked with them it all just seems like black magic to me.
The Makefile is shall mix C source and unit test in C++. I've looked at some examples and tried reading some guides but I am not getting it to work properly and most examples seems quite simple and doesn't really do what I would like to do.
This is the folder structure:
project
src
inc
unit_test
out
Here is my Makefile so far.
CXX = g++
CXXFLAGS = -g -c -I$(INC_DIR)
CC = gcc
CFLAGS = -g -c -Wall -Wextra -Wpedantic -I$(INC_DIR)
LIBS = -lcppunit
OUT_DIR = out
INC_DIR = inc
CPP_SRCS = $(wildcard unit_test/*.cpp)
CPP_OBJS = $(CPP_SRCS:unit_test/%.cpp=$(OUT_DIR)/%.o)
C_SRCS = $(wildcard src/*.c)
C_OBJS = $(C_SRCS:src/%.c=$(OUTDIR)/%.o)
BIN = $(OUT_DIR)/a.out
.PHONY: all run build clean
test:
#echo C_SRCS $(C_SRCS)
#echo C_OBJS $(C_OBJS)
#echo CPP_SRCS $(CPP_SRCS)
#echo CPP_OBJS $(CPP_OBJS)
all: run
run: build
./$(BIN)
build: $(BIN)
clean:
rm -f $(CPP_OBJS)
rm -f $(C_OBJS)
rm -f $(BIN)
$(BIN): $(C_OBJS) $(CPP_OBJS)
$(CXX) $(C_OBJS) $(CPP_OBJS) -o $# $(LIBS)
#echo "Build successful!"
$(CPP_OBJS): $(OUT_DIR)/%.o: unit_test/%.cpp
mkdir -p $(OUT_DIR)
#echo Compiling $<
$(CXX) $< $(CXXFLAGS) -o $#
$(C_OBJS): $(OUT_DIR)/%.o: src/%.c
#echo Compiling $<
$(CC) $< $(CFLAGS) -o $#
Here is the output of 'make test' which will describe my problem at this point in time.
C_SRCS src/add.c
C_OBJS /add.o
CPP_SRCS unit_test/Main.cpp unit_test/Tester.cpp
CPP_OBJS out/Main.o out/Tester.o
Why am I not getting the object file out/add.o when I am doing exactly the same for the the src folder as for the unit_test folder? What am I missing? It's not that obvious to me.

Related

Why Make doesn't recognize my variable?

I have a short Make script, which works if I put the Build directory in as a string manually myself instead of as a variable:
CC = gcc
CFLAGS = -O2 -g -Wall -fmessage-length=0
LDFLAGS =
SRCDIR = Src
BUILDDIR = Build
SRCS = $(SRCDIR)/Main.c
OBJS = $(SRCS:.c=.o)
LIBS =
TARGET = HelloWorld
all: dir $(SRC) Build/$(TARGET)
dir:
mkdir -p $(BUILDDIR)
Build/$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o $#
$(SRCDIR).c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -f $(OBJS) $(TARGET)
It stops working with the error message:
make: *** No rule to make target `/HelloWorld', needed by `all'. Stop.
when I replace the line:
all: dir $(SRC) Build/$(TARGET)
with:
all: dir $(SRC) $(BUILDDIR)/$(TARGET)
Why is Make not substituting the $(BUILDDIR) clause with Build?
In your code there is a space after Build
BUILDDIR = Build

clever linker dependncies

My project is compiled with make and have recently added the boost library for unit testing.
The directory structure is as follows:
Project/
main.cpp
main.hpp
Makefile
sources/
classA.cpp
includes/
classA.hpp
objects/
test/
Makefile
unit_test_classA.cpp
In the folder Project directory I run:
$ make test
Everything works fine except that I don't know how to tell to make to run test/Makefile and look for dependencies in ../object dir automatically.
I'm trying to keep the makefile generic because I build many objects and want to separate my development and testing.
the question is: I need a makefile rule for looking automatically .o files into a especific dir
The Makefiles
# Project/Makefile
BUILD = snake
LDFLAGS =
LDLIBS = -lsfml-graphics -lsfml-window -lsfml-audio -lsfml-system
CXXFLAGS = -Wall -I./includes
RM = rm -rf
OBJ_DIR = objects/
SRC_DIR = sources/
OBJS = $(patsubst $(SRC_DIR)%, \
$(OBJ_DIR)%, \
$(patsubst %.cpp,%.o,$(wildcard $(SRC_DIR)*.cpp)))
OBJECTS = main.o $(OBJS)
all: $(BUILD)
test:
cd test; $(MAKE)
$(BUILD): $(OBJECTS)
$(CXX) $(LDFLAGS) $(LDLIBS) $(OBJECTS) -o $#
$(OBJ_DIR)%.o: $(SRC_DIR)%.cpp $(OBJ_DIR)
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
$(RM) $(OBJECTS) $(OBJ_DIR)
mkdir $(OBJ_DIR)
.PHONY: test
# Project/test/Makefile
BUILD = boost_test
LDFLAGS =
LDLIBS = -lboost_unit_test_framework
CXXFLAGS = -Wall -I./../includes
RM = rm -rf
OBJS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
OBJECTS = $(OBJS)
all: clean $(BUILD)
./$(BUILD)
$(BUILD): $(OBJECTS)
$(CXX) $(LDFLAGS) $(LDLIBS) $(OBJECTS) -o $#
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
$(RM) $(OBJECTS)
.PHONY: $(BUILD)

Generate object files in subdirectory using a Makefile

I am trying to create a Makefile in order to generate object files in a subdirectory rather than let them in the src/ folder.
Here is the structure of the project:
Trunk
- Server
- src/
- include/
- Common
- src/
- include/
The Makefile is located in Trunk/Server. Source files are located both in Server/src and Common/src, so the Makefile currently has something like this:
SRC = src/main.cpp \
src/Network.cpp \
../Common/src/SQLManager.cpp \
../Common/src/Utils.cpp
I woud like to put generated object files in respective obj folders, so Trunk/Server/obj and Trunk/Common/obj. How can I achieve this? I've found many ways to generate object files in subdirectories (vpath, patsubst and many more) but I can't make any of them work for this folder organization.
Edit: If there is a way to put all object files in Server/obj/, that would be ok too.
Here's the complete Makefile (minus some source files and linked libraries):
Edit2: Updated with Didier Trosset's changes
CXX = g++
RM = rm -vf
NAME = Server
SRC = src/main.cpp \
src/Network.cpp \
../Common/src/SQLManager.cpp \
../Common/src/Utils.cpp
OBJ = $(subst src/,obj/, $(subst .cpp,.o, $(SRC)))
LDFLAGS = -lpthread -lm
CPPFLAGS = -std=c++0x -pedantic -Wextra -Wall -Wconversion -Iinclude -I../Common/include
all: Server
%.o: %.cpp
$(CXX) $< -o $#
Server: $(OBJ)
$(CXX) -o $(NAME) $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) *~
fclean: clean
$(RM) $(NAME)
re: fclean Server
.PHONY: all clean fclean Server
Given these definitions, subst should be used to substitute the src part of the directory, and the file extension.
OBJ = $(subst src/,bin/,$(subst .cpp,.o,$(SRC)))
Then, you have to add new pattern rules to compile your source files. (You have to write one pattern rule per directory where your source files are.)
obj/%.o: src/%.cpp
$(CXX) -c $< -o $#
../Common/obj/%.o: ../Common/src/%.cpp
$(CXX) -c $< -o $#
I'm not sure that this will work, but I would try something like:
OBJ := $(join $(addsuffix ../obj/,$(dir $(SRC))),$(notdir $(SRC))
# or, as Didier suggested:
# OBJ := $(subst src/,obj/,$(SRC))
%.o: ../src/%.cpp
$(CXX) $< -o $#
It's not clear exactly what you're trying to do, but this should come close:
OBJ = $(subst src/,obj/,$(SRC:.cpp=.o))
obj/%.o : src/%.cpp
$(CXX) $< -o $#
../Common/obj/%.o : ../Common/src/%.cpp
$(CXX) $< -o $#

How to remove Makefile Dependency on C file

I have the below Makefile and for some reason it's dependent on a file, ewapi.c. This file executes some SWIG commands and uses the ewapi.i file. I've clear out all the contents of ewapi.c and the Makefile successfully runs. If I remove the ewapi.c file the make file will not complete. The exception stack is below if that helps. Any ideas on how to change the Makefile so its not dependent on ewapi.c?
# BUILD_DIR and DIST_DIR are exported by build.xml
#
CMODE=
SWIG = swig
CC = $(PREFIX)gcc
LD = $(CC)
OBJ_DIR = $(BUILD_DIR)/obj
AUTOGEN_DIR = $(BUILD_DIR)/auto-generated
PACKAGE_DIR = $(AUTOGEN_DIR)/com/sample/jni
PACKAGE = com.sample.jni
INCLUDES = -I$(JAVA_INCLUDE) \
-I$(SAMPLE_SDK_DIR)/include \
-I$(JDK_HOME)/include
LIB_INCLUDES = -L$(SAMPLE_SDK_DIR)/lib
LIBS = /lib/libssl.so.4 \
/lib/libcrypto.so.4 \
-lSampleApi \
-lm
DIRS = $(PACKAGE_DIR) $(DIST_DIR) $(OBJ_DIR) $(AUTOGEN_DIR)
CFLAGS = $(CMODE) -Wall -fpic $(INCLUDES) -O0 -g3
SFLAGS = -java $(INCLUDES) -package $(PACKAGE) -outdir $(PACKAGE_DIR)
LDFLAGS = -shared $(LIB_INCLUDES) $(LIBS)
OBJECTS = $(OBJ_DIR)/ewapi_wrap.o $(OBJ_DIR)/ewapi.o
TARGET = $(DIST_DIR)/libSample.so
all: $(DIRS) $(TARGET)
%_wrap.c: %.i
$(SWIG) $(SFLAGS) $<
$(OBJ_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(TARGET): $(OBJECTS)
$(LD) $(OBJECTS) $(LDFLAGS) -o $#
$(DIRS):
mkdir -p $#
clean:
rm -rf $(TARGET) $(PACKAGE_DIR)/* $(TARGET) $(AUTOGEN_DIR) $(OBJ_DIR)
Exception Stack (when I remove ewapi.c):
[exec] rm ewapi_wrap.c
[exec] make-3.79.1-p7: *** No rule to make target `/test/build/obj/ewapi.o', needed by `/test/dist/libSample.so'. Stop.
The macros OBJECTS includes $(OBJ_DIR)/ewapi.o; the rule for $(TARGET) says it depends on $(OBJECTS); and the rule for all says it depends on $(TARGET). So, there needs to be a way to create ewapi.o from something - and in the absence of ewapi.c, there is no way to build ewapi.o, hence the complaint you get.
Possible fixes:
Replace ewapi.c.
Remove ewapi.o from the macro $(OBJECTS).
Remove $(OBJ_DIR)/ewapi.o from OBJECTS.

Makefile problems with gcc flags (file not recognized; shared libraries)

I'm a little confused now. I'm trying to get the Makefile work but it breaks. I Hope someone can help me with this bad and frustrating time-killer.
I've written a small and lightweight part of a Compiler.
The project has the following structure:
/Compiler.cpp
/Makefile
/Buffer/
/Buffer/Makefile
/Scanner/
/Scanner/Makefile
/SymTable/
/SymTable/Makefile
When I'm compiling Buffer, Scanner and SymTable manual (changing the directory and typing 'make mode=release' it's no problem and each shared-library is compiled). But when I run the Makefile from within where the 'Master Makefile' /Makefile is, it fails and the terminal prints something like:
Buffer/libBuffer.so: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: \*** [Compiler] Error 1
Here is the listing of the Makefile of /Buffer/Makefile (the same for Scanner and SymTable):
CXX = g++
ifeq ($(mode),release)
CXXFLAGS = -g -fPIC -O3 -ffunction-sections -march=native
else
mode = debug
CXXFLAGS = -g3
endif
MODUL = Buffer
COMPONENTS = Buffer.h
MK_LIBRARY = lib$(MODUL).so
all: $(MK_LIBRARY)
$(MK_LIBRARY): $(COMPONENTS)
$(CXX) $(CXXFLAGS) -shared -o $# $^
clean:
rm -f $(MK_LIBRARY)
.PHONY: all
.PHONY: clean
The 'Master Makefile' looks like:
CXX = g++
ifeq ($(mode),release)
CXXFLAGS = -g -O3 -ffunction-sections -fwhole-program -march=native
else
mode = debug
CXXFLAGS = -g3
endif
TARGET = Compiler
COMPONENTS = $(TARGET)
DIRS = Buffer Scanner SymTable
MAKE = make
MFLAGS = mode=$(mode)
all: $(COMPONENTS)
$(TARGET): Compiler.cpp libBuffer.so libScanner.so libSymTable.so
$(CXX) $(CXXFLAGS) -IBuffer -IScanner -ISymTable \
-LBuffer -LScanner -LSymTable \
-lBuffer -lScanner -lSymTable -o $# Compiler.cpp
libBuffer.so: force_look
cd Buffer; $(MAKE) $(MFLAGS)
libScanner.so: force_look
cd Scanner; $(MAKE) $(MFLAGS)
libSymTable.so: force_look
cd SymTable; $(MAKE) $(MFLAGS)
clean:
rm -f $(COMPONENTS)
#for d in $(DIRS); do (cd $$d; $(MAKE) clean ); done
check:
#for d in $(DIRS); do (cd $$d; $(MAKE) check ); done
force_look:
true
.PHONY: all
.PHONY: clean
.PHONY: check
I hope some has an answer for me! Thanks!
There's something very weird about this part:
MODUL = Buffer
COMPONENTS = Buffer.h
MK_LIBRARY = lib$(MODUL).so
$(MK_LIBRARY): $(COMPONENTS)
$(CXX) $(CXXFLAGS) -shared -o $# $^
This rule tries to build libBuffer.so out of Buffer.h, the header file. How can this possibly work, without the definitions of the things in Buffer.cc? I would do it this way:
lib%.so: %.o
$(CXX) $(CXXFLAGS) -shared -o $# $^
EDIT:
You have the definitions of Buffer in Buffer.h? All right, you have more than one problem, and the only way to solve them is to do what almost always works: retreat to a simpler problem and solve that first. Can you make Buffer.o? And can you then link that into your executable (bypassing libBuffer.so)? And if not, can you write a "HelloWorld" in Buffer/, and link Buffer.o into that?

Resources