Makefile is not able to find *.o files to make the .exe - c++

This is my directory structure:
$ ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
.
|-Build
|---Bin
|-Include
|-Lib
|-Source
This is my makefile:
Gaurav#Gaurav-PC /cygdrive/d/Pizza/Build
$ pwd
/cygdrive/d/Pizza/Build
Gaurav#Gaurav-PC /cygdrive/d/Pizza/Build
$ ls
Bin Makefile
Gaurav#Gaurav-PC /cygdrive/d/Pizza/Build
$vim Makefile
INCLUDES= ./../Include
OBJDIR= ./Bin
SRCDIR= ./../Source
vpath %.h $(INCLUDES)
vpath %.cpp $(SRCDIR)
vpath %.o $(OBJDIR)
CXX= g++
CXXFLAGS= -Wall -c -I$(INCLUDES)
OBJECTS= Pizza.o PizzaClassMain.o
Pizza: $(OBJECTS)
$(CXX) -Wall $^ -o $(OBJDIR)/$#
PizzaClassMain.o:PizzaClassMain.cpp Pizza.h
$(CXX) $(CXXFLAGS) $< -o $(OBJDIR)/$#
Pizza.o: Pizza.cpp Pizza.h
$(CXX) $(CXXFLAGS) $< -o $(OBJDIR)/$#
.PHONY: clean
clean:
rm -f $(OBJDIR)/*.o $(OBJDIR)/*.exe *~ .Makefile.un~
I am getting below error:
$ make
g++ -Wall -c -I./../Include ./../Source/Pizza.cpp -o ./Bin/Pizza.o
g++ -Wall -c -I./../Include ./../Source/PizzaClassMain.cpp -o ./Bin/PizzaClassMain.o
g++ -Wall Pizza.o PizzaClassMain.o -o ./Bin/Pizza
g++: error: Pizza.o: No such file or directory
g++: error: PizzaClassMain.o: No such file or directory
g++: fatal error: no input files
compilation terminated.
Makefile:18: recipe for target 'Pizza' failed
make: *** [Pizza] Error 1
I have put vpath %.o $(OBJDIR) in my Makefile but still rule: Pizza is not able to find Pizza.o & PizzaClassMain.o though they are being created correctly in directory ./Bin by the rules Pizza.o & PizzaClassMain.o
If I manually run g++ -Wall g++ -Wall Pizza.o PizzaClassMain.o -o Pizza from directory ./Bin then it works fine.
I am not able to figure out why the rule Pizza is not able to find input files?
Can anyone please help?
PS: This Makefile did compile successfully once or twice out of say 40 times. Are there some issues with cygwin package make?

Your objects should be:
OBJECTS= ./Bin/Pizza.o ./Bin/PizzaClassMain.o
These objects are compiled successfully as the rule PIZZA: $(OBJECTS) finds correct rules named "Pizza.o" and "PizzaClassMain.o". These are only names of rules, not actual filenames. When Make utility looks for ./Build/Pizza.o, this file does not exist and is not found. It was created in the ./Build/Bin directory.

Below changes in rule resolved the issue:
Pizza: $(OBJECTS)
$(CXX) -Wall $(addprefix $(OBJDIR)/,$^) -o $(OBJDIR)/$#
Very nice article http://mad-scientist.net/make/vpath.html as pointed by OliCharlesworth.

Related

Makefile not giving the expected compilation results

I am quite new to Make. I am attempting to write a Makefile to build a medium-sized Linux C/C++ application as below.
Making a simple Makefile by having all source files in one location and explicitly listing the source files works ok for me but I would like it to be more generic.
I have all my source files (C and C++) in the src folder in different subdirectories. I have header files inside an inc and inc/common folder, and then libs inside a lib folder.
The Makefile is run on the same level :
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
CXX := /bin/arm-linux-gnueabi-g++
EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))
CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c++11 -Wall
LDFLAGS := -Llib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
I get lots of errors such as below when I run it, including problems opening dependency files. I think i'm almost there, but can't see my error exactly :
compilation terminated.
/bin/arm-linux-gnueabi-g++ -Iinc -Iinc/common -MMD -MP -std=c++11 -Wall -c -o obj/main.d.o
cc -Llib obj/main.d.o -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
I don't see how the output you show can be generated from the makefile you show here but anyway.
This is not right:
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
A pattern rule is a template that tells make "if you want to build a target that matches this pattern, then you can build it from the prerequisites that match this pattern".
Here you are listing ALL your source files as a prerequisite for EVERY object file. Suppose SRC is set to foo.c bar.c biz.c baz.c, then this expands to:
obj/%.o : foo.c bar.c biz.c baz.c | obj
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
You're telling make that every single .o target depends on ALL the source files, not just the one for that object file. Further, the automatic variable $< always expands to the first prerequisite, which here will always be foo.c. So, you're compiling foo.c four times, creating each of the object files.
The very first important rule when debugging makefiles is to look carefully at the output (command lines) that make prints. If they are not right, then your makefile is not right. If you do that you'll see all the compile lines are compiling the same source, like:
g++ -c foo.c -o obj/foo.o
g++ -c foo.c -o obj/bar.o
g++ -c foo.c -o obj/biz.o
g++ -c foo.c -o obj/baz.o
That clearly cannot work and it's why you get link errors trying to link together all these object files: they all have the same content.
You need this:
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
which tells make how to build an object file from a single source file.
You also need to create the actual output directory that the object file will go into. Just creating $(OBJ_DIR) is not enough, if the object file appears in a subdirectory.

I get a "attempted static link of dynamic object `/usr/lib/x86_64-linux-gnu/libc++abi.a'" error when I try to statically link libc++abi.a

environment
ubuntu 18.04 (a virtual environment created by vagrant)
gcc5.5.0
I'm trying to build my own little OS.
I'm writing the kernel in C++/NASM.
I'm going to compile each of the several C++ files that make up the kernel and then link them together to create an executable file. (This is because the entry point of my own kernel is not "main", so I dare not link at the same time as compiling)
Error
The compilation of each C++ file will run without any problems and each object file will be created.
However, I get the following error in linking the object files.
But I understand that a ".a" file is a static object, not a dynamic object, so I can not understand why I'm getting this error.
I'd appreciate it if you could let me know.
ld: attempted static link of dynamic object `/usr/lib/x86_64-linux-gnu/libc++abi.a'
Here's the full text of the log
mkdir -p ./obj
g++ -O2 -g -MMD -Wall -I./include -o obj/hoge.o -c src/hoge.cpp
mkdir -p ./obj
g++ -O2 -g -MMD -Wall -I./include -o obj/huga.o -c src/huga.cpp
mkdir -p ./obj
g++ -O2 -g -MMD -Wall -I./include -o obj/piyo.o -c src/piyo.cpp
mkdir -p ./obj
nasm -f elf64 -o obj/assm.o src/assm.asm
ld --entry <ENTRY_POINT> --static -o ./ELF/kernel.elf ./obj/hoge.o ./obj/huga.o ./obj/piyo.o ./obj/assm.o -lc -lc++ -lc++abi -L/usr/lib/x86_64-linux-gnu
ld: attempted static link of dynamic object `/usr/lib/x86_64-linux-gnu/libc++abi.a'
Makefile:12: recipe for target 'ELF/kernel.elf' failed
make: *** [ELF/kernel.elf] Error 1
Makefile
COMPILER = g++
CFLAGS = -O2 -g -MMD -Wall
INCLUDE = -I./include
TARGET = ./ELF/kernel.elf
SRCDIR = ./src
SOURCES := $(shell find $(SRCDIR) -name *.cpp -or -name *.c -or -name *.asm)
OBJDIR = ./obj
OBJECTS = $(OBJDIR)/hoge.o $(OBJDIR)/huga.o $(OBJDIR)/piyo.o $(OBJDIR)/assm.o
DEPENDS = $(OBJECTS:.o=.d)
LDFLAGS = --entry <ENTRY_POINT> --static
$(TARGET): $(OBJECTS)
ld $(LDFLAGS) -o $(TARGET) $(OBJECTS) -lc -lc++ -lc++abi -L/usr/lib/x86_64-linux-gnu
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
-mkdir -p $(OBJDIR)
$(COMPILER) $(CFLAGS) $(INCLUDE) -o $# -c $<
$(OBJDIR)/%.o: $(SRCDIR)/%.asm
-mkdir -p $(OBJDIR)
nasm -f elf64 -o $# $<
all: clean $(TARGET)
clean:
rm -rf $(OBJECTS) $(DEPENDS) $(TARGET)
-include $(DEPENDS)

Makefile how to specify the include directory

I am trying to write a make file for the following program
MY file/folder structure is as follows
Folder/File structure
./demo/utilities.c
./demo/utilities.h
./demo/makefile
./include/GeographicLib/UTMUPS.h
./include/GeographicLib/Constant.h
./include/GeographicLib/xxxxxxx
in the file utilities.h
#include <GeographicLib/UTMUPS.h>
in the file UTMUPS.h
#include <GeographicLib/Constant.h>
in the makefile
# preprocessor
PREPROC_FLAGS += -DEIGEN_DONT_ALIGN_STATICALLY
INC_XTRA_DIR = ../include
CC=g++
CPPFLAGS= $(PREPROC_FLAGS)
CFLAGS=-O2 -g -Wall -W -I$(INC_XTRA_DIR)
CXXFLAGS=-O2 -g -Wall -W -fpic -std=c++11
# short hand
OBJDIR=obj
Utilities_h = utilities.h GeographicLib/UTMUPS.hpp
utilities.o: utilities.c $(Utilities_h)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
all: $(FINAL_TARGET)
$(FINAL_TARGET): $(OBJ)
$(CC) -g -o $# $^ $(LDFLAGS)
ifneq ($(wildcard ../databases/.),)
cp $# ../
endif
TargetList = $(FINAL_TARGET)
clean:
rm -f $(TargetList) *.o *~
echo Clean done.
The question I want to ask is
When I compile the following project, it say it can't find "#include 'GeographicLib/UTMUPS.h'". in the utilities.h. what should the naming be in this case. My thought is that by adding -I$(INC_XTRA_DIR), or ../include ... it should search for GeographicLib/UTMUPS.h
what about the file that UTMUPS.h is dependent on(in this case Constant.h), what should be the addressing
Edit: I run make at the root directory... maybe that's the reason for the error.
THanks

Building shared libraries with Makefile

I have a project that I want to build a shared library for it. The following Makefile works:
libfastpd.so: fastpd.cpp
$(CXX) -std=c++11 -fPIC -c fastpd.cpp -o fastpd.o
$(CXX) -std=c++11 -fPIC -c graph.cpp -o graph.o
$(CXX) -std=c++11 -fPIC -c LinkedBlockList.cpp -o LinkedBlockList.o
$(CXX) -std=c++11 -fPIC -c maxflow.cpp -o maxflow.o
$(CXX) -std=c++11 -shared -Wl,-soname,libfastpd.so -o libfastpd.so fastpd.o graph.o LinkedBlockList.o maxflow.o
clean:
rm *.o *.so
Then I came across this recipe in Cogswell et al.'s C++ Cookbook: https://www.oreilly.com/library/view/c-cookbook/0596007612/ch01s18.html
and decided to improve my Makefile based on that:
# Specify extensions of files to delete when cleaning
CLEANEXTS = o so
# Specify the source files, the target files,
# and the install directory
SOURCES = fastpd.cpp graph.cpp LinkedBlockList.cpp maxflow.cpp
OUTPUTFILE = libfastpd.so
INSTALLDIR = ./
.PHONY: all
all: $(OUTPUTFILE)
# Build lib*.so from all the *.o;
# subst is the search-and-replace
# function demonstrated in Recipe 1.16
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
$(CXX) -shared -fPIC $(LDFLAGS) -o $# $^
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Generate dependencies of .ccp files on .hpp files
include $(subst .cpp,.d,$(SOURCES))
%.d: %.cpp
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
Running this file I obtained the following error:
/usr/bin/ld: fastpd.o: relocation R_X86_64_32 against `.rodata' can
not be used when making a shared object; recompile with -fPIC
fastpd.o: error adding symbols: Bad value
Checking the terminal output, I observed that the following commands were executed:
g++ -c -o fastpd.o fastpd.cpp
g++ -c -o graph.o graph.cpp
g++ -c -o LinkedBlockList.o LinkedBlockList.cpp
g++ -c -o maxflow.o maxflow.cpp
No -fPIC!
My question is: Which lines of the Makefile execute these commands and how to add -fPIC to them?
Any references to good ressources to understand the entire Makefile above would be very much appreciated as well!
Thank you very much in advance for your help!
Which lines of the Makefile execute these commands... ?
The short answer is none. The rule...
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
$(CXX) -shared -fPIC $(LDFLAGS) -o $# $^
only specifies the link time dependencies and command. The -fPIC option needs to be specified when you compile the source file but you haven't provided any rule to build a .o from a .cpp so make falls back on its implicit rule which (for the purposes of this example) is essentially...
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
So the obvious solution is to add -fPIC to CXXFLAGS...
CXXFLAGS += -fPIC

"make" fails when using pattern matching

I'm trying to create a generic make file so that I can compile my project independently of how many files I add to it and where I decide to put them in the project tree.
In my step by step approach I cam to this makefile which works fine.
CC=g++
OBJECTS=main.o board.o
VPATH=src:\
src/board:\
include/board:\
build:\
bin
boardG : main.o board.o
$(CC) -o bin/boardG build/main.o build/board.o
main.o : main.cpp board.hpp
$(CC) -c -I include $< -o build/$#
board.o : board.cpp board.hpp
$(CC) -c -I include $< -o build/$#
This version will do the job just fine. See output below:
me#01:~/code/projects/boardG$ make
g++ -c -I include src/main.cpp -o build/main.o
g++ -c -I include src/board/board.cpp -o build/board.o
g++ -o bin/boardG build/main.o build/board.o
The problem here is that I will have to create one rule for each .cpp file. Which is precisely what I try to avoid. Hence I tried to adapt the version above using matching patterns like this:
CC=g++
OBJECTS=main.o board.o
VPATH=src:\
src/board:\
include/board:\
build:\
bin
boardG : main.o board.o
$(CC) -o bin/boardG build/main.o build/board.o
%.o : %.cpp %.hpp
$(CC) -c -I include $< -o build/$#
When I run make now I get the follwing output:
me#01:~/code/projects/boardG$ make
g++ -c -o main.o src/main.cpp
src/main.cpp:2:27: fatal error: board/board.hpp: No such file or directory
compilation terminated.
<builtin>: recipe for target 'main.o' failed
make: *** [main.o] Error 1
My project has the follwing structure/files in it.
./bin/
./build/
./include/board/board.hpp
./src/main.cpp
./src/board/board.cpp
./makefile
I'm wondering why make would change the command when using pattern matching? Or, and probably more accurately, what am I doing wrong that makes make fail?
Just avoid using VPATH when it comes to object files. What's happening is that make is actually using the built-in rule for %.o and not using your rule at all.
If you prefix all your objects with the directory, this should work:
CC=g++
OBJDIR = build
OBJECTS = $(OBJDIR)/main.o $(OBJDIR)/board.o
VPATH = src:\
src/board:\
include/board:\
bin/boardG : $(OBJECTS)
$(CC) -o $# $^
$(OBJDIR)/%.o : %.cpp %.hpp
$(CC) -c -I include $< -o $#
Here is a helpful resource, which more or less exactly describes the problem you've run into.