Makefile, executable and object files in different directories - linux

I'm trying to get the object files and the executable file in different directories. In the root folder there is a obj and exe folder for this, but i have no idea how to get make to run it.
I have tried stuff like:
$(EXEDIR)/sfml-app: $(OBJ)
and
$(OBJDIR)/%.o: %.cpp
but it gives me errors. Can anybody explain me how I can get this to run?

If you want your output to go to another directory, you have to tell make (and the compiler) about it. They won't just guess because you have a variable named OBJDIR! You have to actually make use of it.
Make sure your target names have the directory prefix so make knows where you expect the object files to end up:
OBJ = $(patsubst %.cpp, $(OBJDIR)/%.o, $(SRC))
and make sure you tell the compiler where you want the object files to end up by using the -o flag:
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
Similarly, if you want the final output to to into EXEDIR you have to use it both in the makefile and send that value to the linker, again via -o:
all: $(EXEDIR)/sfml-app
$(EXEDIR)/sfml-app: $(OBJ)
$(CXX) -o $# $(OBJ) $(LIBS)

Related

Getting dependencies of a shared library that could be located at any folder

I'm creating a Rules.make file, similar to Linux's 2.0 version, which contains all kinds of targets - including .so files. My goal is to then only need to make minimalistic Makefiles like so:
include $(DIR_TOP)/Rules.make
in the directories that contain any source files I need compiled. The rules also enable me to create targets like so in the "main" Makefile:
something: something_else lib.so
, so that something_else is done first, and then lib.so is built.
Everything has been going smoothly, until I decided to add dependencies to the aforementioned shared library target. I figured something like the following would do the trick:
${DIR_OUT}/%.so: $(shell find $(dir $#) -name *.o)
$(CC) $(CFLAGS) -o $# $(CLIBS) -shared $^
However, to my demise, $(dir $#) apparently expands to $(dir ${DIR_OUT}/%.so), which then results in simply ${DIR_OUT}, which is exactly not what I need. DIR_OUT is simply the top-level directory string, but the target may be invoked from any sub-directories, or simply like target: $(DIR_OUT)/path/to/lib.so. I was hoping that % could match not only file names, but also any directories (which it does), and then have that expanded to $# once it's already decided what the full path is. Doesn't work like that. With this solution, not only the object files I need are included in the building process, but also any other object files that are there in the output folder, and that then produces errors of kind multiple definition of x y z etc.
Is there any other way to get the list of dependencies for the shared library I want to build? Ideally a purely Makefile based solution, but if there isn't one, I'm fond of some bash scripting too.
The solution turns out to be secondary expansion:
.SECONDEXPANSION:
${DIR_OUT}/%.so: $$(shell find $$(dir $$#) -name *.o)
$(CC) $(CFLAGS) -o $# $(CLIBS) -shared $^

Struggling with a GCC Makefile

I am trying to write what I thought would be quite a simple Makefile and I'm just baffled! I'm not a makefile writer, but I thought I understood them enough to be able to get a simple one working.
Okay, I have a small project in a directory and also in this directory is a libs directory containing many .c files. What I'm trying to do is write a makefile that will build the contents of the /libs directory into a static lib file in the /libs directory and then compile a few source files in the / directory and link it against the built .a file.
I'm sure someone's going to suggest "why not use cmake", but that's not answer I'm looking for (waves hand like a Jedi.. ehehehehe)
CC = gcc
CFLAGS = -Wall
SOURCES = lzx.c csum.c dirs.c listner.c tree.c
OBJECTS = $(SOURCES:.c=.o)
TARGETLIB = libs/mylib.a
TARGET = TestApp
libs/%.o : libs/%.c
$(CC) $CFLAGS -c $<
$(TARGETLIB) : $(OBJECTS)
ar rcs $# $^
$(TARGET) :
$(CC) $CFLAGS Source1.cpp Source2.cpp -llibs/mylib.a -o $#
My understanding was that the first recipe, would compile all the .c files into objects, but it seems to compile the first .c file and then stop.
Any help anyone could give me would be appreciated.
Since Your final app is TARGET, You should make it first Makefile rule. And since it also depends on TARGETLIB it should be given as dependency, like so:
$(TARGET): $(TARGETLIB)
$(CC) $(CFLAGS) Source1.cpp Source2.cpp -Lmylib -o $#
next I assume that *.c files You mentioned are lib files. Thus You will need a prefix to them, since You want to specify them by hand, not via wildcard or rule.
OBJECTS = $(addprefix(libs, $(SOURCES)):.c=.o)
and last thing that comes to my mind is library name, which supposed to be libSOMENAME.a (well, linker searches for this name in path and -Lotherpaths). So we have:
TARGETLIB = libs/libmylib.a
summing it all up:
CC = gcc
CFLAGS = -Wall
SOURCES = lzx.c csum.c dirs.c listner.c tree.c
OBJECTS = $(addprefix(libs, $(SOURCES)):.c=.o)
TARGETLIB = libs/libmylib.a
TARGET = TestApp
$(TARGET) : $(TARGETLIB)
$(CC) $(CFLAGS) Source1.cpp Source2.cpp -static -L./libs -lmylib -o $#
$(TARGETLIB) : $(OBJECTS)
ar rcs $# $^
And yes, this could be written much better, but I assume if You wanted to learn more about Makefiles or linker, and not just shown where You made mistakes, You'd know how to find manual pages.

The effect of the following Makefile lines is?

Can somebody explain the effect of the following MACRO command please?
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
When make is called with the target that equals what is contained in the variable $(EXECUTABLE) (only you can say what that might be), then execute the c compiler with the defined linker flags and compile the objects into the outfile which is named like the target.
So a call to make myprog would result in the c compiler creating the executable myprog.

How to ouput the static library into other directory than current?

Following is my directory structure
calculator
|
|---src
(multiply.cpp sum.cpp)
|---lib
I am building a static library calc.a using following
ar -rcs calc.a multiply.o sum.o
calc.a is builded in current directory.
I trying calc.a to be put into lib folder not in current directory (i.e. src)
I searched in internet and man page but couldn't find anything.
Any idea?
Since you are using the command line, the easiest way to write the library into the lib directory is to do it explicitly:
ar -rcs lib/libcalc.a multiply.o sum.o
Using a Makefile you can do more sophisticated things, but even then, it boils down to the same thing, e.g. adding the path to the front of the library name.
Since you asked for additional info on your comment, I add here a simple Makefile, which may be helpful to get you started:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=src/main.cpp src/sum.cpp src/multiply.cpp
OBJECTS=$(SOURCES:.cpp=.o)
LIBRARY=lib/libcalc.a
EXECUTABLE=main
all: $(SOURCES) $(LIBRARY) $(EXECUTABLE)
$(LIBRARY): $(OBJECTS)
<tab>mkdir -p lib
<tab>ar -rcs $# $<
$(EXECUTABLE): $(OBJECTS)
<tab>$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
<tab>$(CC) $(CFLAGS) $< -o $#
clean:
<tab>rm -rf main lib/ src/*.o
Important: All <tab>s must be replaced with real tabs, as required by the Makefile syntax!
Makefiles are very very flexible, so they can be very simple and specific to your problem, or as general and/or complex to build many libraries and binaries, based on millions and millions of source code. I suggest you to search for Makefile documentation for more information.
As a final note, I also suggest you to rename your library as 'libcalc.a', since the 'lib' prefix is standard in Unix. Other similar standards apply for other environments.

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.

Resources