Writing a makefile for an project with some arranged folders - linux

I have the makefile below and a directory tree :
->project/src/main.c, func.c,
Makefile
->project/exe/
->project/inc/
->project/obj/
cc=gcc
cflags=-c
obj=../obj
exe=../exe
inc=../inc
prog.exe: main.o func.o
$(cc) main.o func.o -o $(exe)/prog.exe
main.o: main.c $(inc)/defs.h
$(cc) $(cflags) main.c
mv main.o $(obj)/
func.o: func.c $(inc)/defs.h
$(cc) $(cflags) func.c
mv func.o $(obj)/
The problem is, the second actions below main.o and func.o (those start with mv) doesn't work (i.e main.o isn't moved to the /obj directory). Is there a problem in the syntax of makefile or anything else?

One apparent problem is that the makefile doesn't build the targets it's supposed to build. I.e.:
prog.exe: main.o func.o
$(cc) main.o func.o -o $(exe)/prog.exe
Doesn't build prog.exe, rather it builds $(exe)/prog.exe, which is a different file. A fix would be:
$(exe)/prog.exe: $(obj)/main.o $(obj)/func.o
$(cc) $^ -o $#
Prefer using automatic variables for the names of input and output files to avoid duplication and silly typos.

You may take care of the indentation with make. It needs real tabs.
See https://superuser.com/questions/224434/what-is-the-character-used-to-indent-the-make-file-rule-recipe

Related

Linux GCC Makefile a shared library with multply sources and dependencies

I have a problem trying to create a Makefile that compile multiple sorces, generate only a shared library and make an exe with another file wiht the main function.
The sorces also have dependencies.
My Makefile is
CC=gcc
CFLAGS=-Wall -g
BINS=libsensorMotor.so maintarget
all: $(BINS)
libsensorMotor.o: libsensorMotor.cpp sensorMotor.h Adafruit_ADS1015.cpp Adafruit_ADS1015.h wiringPiI2C.c wiringPiI2C.h enumADCGain.h
$(CC) $(CFLAGS) -c libsensorMotor.cpp Adafruit_ADS1015.cpp wiringPiI2C.c
libsensorMotor.so: libsensorMotor.cpp sensorMotor.h
$(CC) $(CFLAGS) -fPIC -shared -o $# libsensorMotor.cpp -lc
maintarget: maintarget.c
$(CC) $(CFLAGS) -o $# $^ -L. -lsensorMotor -pthread
clean:
rm *.o $(BINS)
The script show the errors:
libsensorMotor.so Undefined reference to 'functionXXXX'
maintarget contains the main and use libsensorMotor as a shared library. libsensorMotor depends and include all the rest of the files
The error mention all the functions that libsensorMotor uses from the include sources.
I only need to generate a correct libsensorMotor.so that can use as shared library from any other main file. Internet has many tutorials but are unclear, weird and complicated, and not show how do this simple.
Is not Makefile problem, simply the line
gcc -pthread -lm -o maintarget maintarget.c libsensorMotor.cpp Adafruit_ADS1015.cpp wiringPiI2C.c
sends same error, the compiler not recongnice the function inside the pthread_create while compile C and C++ with gcc

Preprocessor directives in linux makefile

How do you use commands like #define and !include in linux makefile for the g++ compiler?
My understanding is that # creates a comment line so wont #define just be a comment?
Thanks for the help
I typically define a variable at the top of the file, and set it equal to the #define values I want like this:
DEFINES=-DSOMETHING -DSOMETHING_ELSE
For includes, g++ accepts search paths from the command line with -I.
For the makefile you can do the same thing, just make a variable and add the paths:
INCLUDES=-I/path -I/path2
The makefile then just calls the compiler as
g++ $(DEFINES) $(INCLUDES) file.cpp
Check out this example
# I am a comment, and I want to say that the variable CC will be
# the compiler to use.
CC=g++
# Hey!, I am comment number 2. I want to say that CFLAGS will be the
# options I'll pass to the compiler.
CFLAGS=-c -Wall
all: hello
hello: main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o: main.cpp
$(CC) $(CFLAGS) main.cpp
factorial.o: factorial.cpp
$(CC) $(CFLAGS) factorial.cpp
hello.o: hello.cpp
$(CC) $(CFLAGS) hello.cpp
clean:
rm *o hello
for more information check these:
http://mrbook.org/blog/tutorials/make/
http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html

Makefile uses same source for every object file

I have a makefile which is supposed to compile a large number of source files into individual object files, then link them into a shared library.
The list of source files are stored in a variable, SOURCES. During the $(OBJECTS) target, where the object files are compiled, make runs the command $(CC) $(CFLAGS) -c $< -o $#, where $< is $(addprefix $(SRCPATH),$(SOURCES)).
This makes the command use the same source file for every object file, giving me a bunch of object files made from Time.cpp and causing the linker to give me a bunch of errors of functions that are already defined in every other object file. How can I get this makefile to work?
# Variable setup
# BUILD - Either Debug or Release, specify when running make
# ARCH - Either 32 or 64, specify when running make
# CC - The compiler
# INC - The include directories
# CFLAGS - Compiler flags to use
# LDFLAGS - Linker flags to use
# OBJDIR - Directory for .o files
# BINARY - Output file path
# SOURCES - Path to each individual source file
# OBJECTS - Object files
ifeq ($(and $(ARCH),$(BUILD)),)
$(error You have either not defined an architecture or build or both, please run "make BUILD=(DEBUG/RELEASE) ARCH=(32/64)")
endif
CC = g++
INC = -I../../include -I../../extlibs/headers -I../../extlibs/headers/libfreetype/linux
LDFLAGS = -lX11 -lGL -lGLEW -lfreetype -ljpeg -lopenal -lsndfile
CFLAGS = $(INC) -std=c++0x -fPIC -pthread -m$(ARCH)
OBJDIR = ./obj/$(BUILD)/$(ARCH)-bit
BINPATH = ./bin/$(BUILD)/$(ARCH)-bit
BINARY = $(BINPATH)/libTyrant$(ARCH).so
SRCPATH = ../../src/
SOURCES = System/Time.cpp System/Mutex.cpp System/Log.cpp System/Clock.cpp System/Sleep.cpp System/Unix/ClockImpl.cpp System/Unix/MutexImpl.cpp System/Unix/SleepImpl.cpp System/Unix/ThreadImpl.cpp System/Unix/ThreadLocalImpl.cpp System/Lock.cpp System/String.cpp System/ThreadLocal.cpp System/Thread.cpp Audio/SoundRecorder.cpp Audio/SoundBuffer.cpp Audio/SoundSource.cpp Audio/AudioDevice.cpp Audio/ALCheck.cpp Audio/Sound.cpp Audio/Music.cpp Audio/SoundFile.cpp Audio/SoundStream.cpp Audio/SoundBufferRecorder.cpp Audio/Listener.cpp Graphics/RectangleShape.cpp Graphics/VertexArray.cpp Graphics/Shader.cpp Graphics/ConvexShape.cpp Graphics/ImageLoader.cpp Graphics/Sprite.cpp Graphics/RenderTexture.cpp Graphics/BlendMode.cpp Graphics/Shape.cpp Graphics/CircleShape.cpp Graphics/TextureSaver.cpp Graphics/Vertex.cpp Graphics/RenderTextureImpl.cpp Graphics/Texture.cpp Graphics/Text.cpp Graphics/GLExtensions.cpp Graphics/Image.cpp Graphics/RenderTextureImplFBO.cpp Graphics/GLCheck.cpp Graphics/RenderTextureImplDefault.cpp Graphics/Color.cpp Graphics/Transformable.cpp Graphics/RenderTarget.cpp Graphics/Transform.cpp Graphics/View.cpp Graphics/RenderStates.cpp Graphics/RenderWindow.cpp Graphics/Font.cpp Window/JoystickManager.cpp Window/Joystick.cpp Window/Window.cpp Window/Keyboard.cpp Window/GlResource.cpp Window/Unix/JoystickImpl.cpp Window/Unix/WindowImplX11.cpp Window/Unix/GlxContext.cpp Window/Unix/Display.cpp Window/Unix/VideoModeImpl.cpp Window/Unix/InputImpl.cpp Window/VideoMode.cpp Window/Mouse.cpp Window/GlContext.cpp Window/Context.cpp Window/WindowImpl.cpp Network/Ftp.cpp Network/TcpListener.cpp Network/Packet.cpp Network/IpAddress.cpp Network/TcpSocket.cpp Network/Socket.cpp Network/Unix/SocketImpl.cpp Network/UdpSocket.cpp Network/SocketSelector.cpp Network/Http.cpp
OBJECTS = $(addprefix $(OBJDIR)/,$(SOURCES:.cpp=.o))
ifeq ($(BUILD),DEBUG)
CFLAGS := $(CFLAGS) -g -pg -Og
endif
ifeq ($(BUILD),RELEASE)
CFLAGS := $(CFLAGS) -s -O3
endif
all: clean $(addprefix $(SRCPATH),$(SOURCES)) $(BINARY)
$(BINARY): $(OBJECTS) $(BINPATH)
$(CC) $(LDFLAGS) $(OBJECTS) -shared -o $#
$(OBJECTS): $(addprefix $(SRCPATH),$(SOURCES)) $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR):
mkdir ./obj
mkdir ./obj/$(BUILD)
mkdir $#
mkdir $#/Audio
mkdir $#/Graphics
mkdir $#/Network
mkdir $#/Network/Unix
mkdir $#/System
mkdir $#/System/Unix
mkdir $#/Window
mkdir $#/Window/Unix
$(BINPATH):
mkdir ./bin
mkdir ./bin/$(BUILD)
mkdir $#
clean:
rm -rf bin
rm -rf obj
You have several problems here.
Suppose all of the source files were in the working directory, and that's where the object files belonged too. Instead of trying to build all of the objects with one command, you could build each object separately, with a pattern rule to cover them all:
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $#
Then you could make the OBJECTS prerequisites of the library, and Make would handle it all:
$(BINARY): $(OBJECTS)
$(CC) $(LDFLAGS) $^ -shared -o $#
(Once you had that working, you might remember that Make already had built-in rules for things like building foo.o from foo.cpp, but never mind that for now.)
But in your build scheme you combine this with other problems: 1) you have source files in several different directories, and 2) you want to build the objects elsewhere, namely 3) in a directory tree that mirrors the source tree, 4) which you build on the fly.
Addressing all of those points would make for quite an involved answer. Which of them are you already comfortable with?
I've made it work, though it may not be optimal. My solution:
$(BINARY): $(SOURCES) $(BINPATH)
$(CC) $(LDFLAGS) $(OBJECTS) -shared -o $#
$(SOURCES): $(OBJDIR)
$(CC) $(CFLAGS) -c $(SRCPATH)$# -o $(patsubst %.cpp,%.o,$(OBJDIR)/$#)
Basically, I just switched the targets from the Object files to the source files, appended the source path to the target name for the input file, and appended the object directory to the target name while also using patsubst to change the file extension from .cpp to .o. The entire makefile is pretty hacked together, I'm aware of that, but it works and that's good enough for me for my first makefile.

a target has a dependency which that dependency itself is not a target

Here is a tutorial for make file in Linux: http://mrbook.org/tutorials/make/
Here is a make file example:
all: hello
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello
main.o: main.cpp
g++ -c main.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
hello.o: hello.cpp
g++ -c hello.cpp
clean:
rm -rf *o hello
For me this line is confusing main.o: main.cpp
What does it mean? As I understand, it means target main.o has a main.cpp dependency. But there is no target with main.cpp
It means a target (main.o) has a dependency (main.cpp) which that dependency (main.cpp) itself is not a target. So what is it (main.cpp)?
main.cpp is a file.
From the extension we expect it to be a c++ source file, and the associated rule suggest that this is the case.
The rule will be exectuted any time that main.cpp is newer than main.o (which is also a file).
main.cpp is your source code. The fact that there is no target for main.cpp just means that Make has no way to generate that file. You are expected to create it yourself.

Cannot compile with makefile - undefined reference to `boost::re_detail

I got an assignment to improve running time of some code. The only problem is, I can't even compile it to run it on my machine in the first place. Every time I try, it stops somewhere in the midst of compiling saying this:
"undefined reference to `boost::re_detail::put_mem_block(void*)'
collect2: ld returned 1 exit status make: * [cpu] Error 1"
This is how makefile looks:
SHELL = /bin/bash
OBJECTS = main.o atom.o molecule.o charges.o pdb.o asa.o amino.o chain.o addition.o string_operation.o pdb_peptide.o protein_chain.o residue_atom.o chain_residue.o residue_contact.o atom_grid.o circles.o atom_space_calculations.o
OBJDIR = obj
VPATH = src:src/ext:$(OBJDIR)
CFLAGS = -O3 -Wall -lm -lboost_regex -L/usr/local/boost/lib
HDIRS = src,src/ext,src/qt_redistributable, usr/lib, usr/local/lib, usr/local/lib/include/boost, /usr/local/lib/lib/
IOPTS = $(addprefix -I, $(HDIRS))
cpu : $(addprefix $(OBJDIR)/, $(OBJECTS) $(CPUOBJS))
g++ $(CFLAGS) -o mcpu $^
$(OBJDIR)/%.o : %.cpp
g++ $(CFLAGS) $(IOPTS) -c $< -o $#
clean :
rm obj/*.o $(PROG)
I'm using Linux Mint x64 and I have tried everything I googled out. Installed the whole boost library in usr/local/lib (for no obvious reason because it didn't help), tried to edit LD PATH (I'm very new to Linux and I have no idea if that went right) and lots of stuff, but this thing doesn't seem to go through. Any help appreciated.
One problem with your makefile happens when you link your program. As you can see in these questions with g++ the order of your arguments at link time is really important. You need to put your libraries after your object files. One easy way to solve would be separating your linker flags (LDFLAGS) from the compiler flags (CFLAGS), and then putting LDFLAGS after $^ (your object files) in the link command.
CFLAGS = -O3 -Wall
LDFLAGS = -L/usr/local/boost/lib -lm -lboost_regex
cpu : $(addprefix $(OBJDIR)/, $(OBJECTS) $(CPUOBJS))
g++ $(CFLAGS) -o mcpu $^ $(LDFLAGS)
$(OBJDIR)/%.o : %.cpp
g++ $(CFLAGS) $(IOPTS) -c $< -o $#
As can be seen in the Catalogue of Built-In Rules:
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)
and Variables Used by Implicit Rules:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker,
ld, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable
instead.
So in this case -lboost_regex should be set or added to LDLIBS, not LDFLAGS.

Resources