The effect of the following Makefile lines is? - linux

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.

Related

How do I correctly link a shared object (.so file) in a makefile when cross-compiling?

I have some C++ code on an openSuse platform that I need to compile to be executed on a different linux-based target. Part of the code is a dynamic library libfoo.so. I compile everything with make and then copy the compiled executable prog together with the libfoo.so to the target. When I then run the executable, I get some errors indicating the libfoo could not be initialized. I've tried everything I could find to tell the executable where it can find the libfoo.so but I still get the error.
Could anybody tell me what I am doing wrong here? I feel like it could be an error in the Makefile.
I am very new to C++ and using Makefiles in general, and on top of it all, the target runs kind of a proprietary linux version, so I cannot provide much information about it. I do have the appropriate compiler for it though.
My directory structure on the openSuse platform:
|src
|--Foolib
|----foolib.h
|----libfoo.so
|--Otherlib
|----otherlib.h
|----otherlib.hpp
|---+OtherlibSrcDirectory
|--bar.cpp
|--bar.h
|--Makefile
Directory structure on the target:
|program
|--libfoo.so
|--prog
My Makefile:
LIBS = -LFoolib -lfoo
INC = -I OtherLib -I Foolib
CXXFLAGS += -lpthread -std=c++11 -D_GLIBCXX_USE_NANOSLEEP $(INC)
LDFLAGS = '-Wl,-rpath,$$ORIGIN'
SRC_FILES = bar.cpp
OBJ = $(SRC_FILES:%.cpp=%.o)
prog: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIBS) -o $# $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(LIBS) -c $<
Basically, bar.h includes Foolib/foolib.h as well as Otherlib/OtherlibSrcDirectory and bar.cpp includes bar.h. Then some functions from foolib.h are called in bar.cpp and they return error values. If necessary I can provide some more insights into the code but I'll leave it out for now to keep it a bit shorter.
Any help would be highly appreciated!
Found my mistake.
libfoo.so was already on the target machine and it was located in the correct folder (/lib). My program had been able to find it without problems.
My mistake: I executed my program on the target machine without root permissions.
Without root permissions, I am not allowed to initialize Foolib.
sudo ./prog fixed everything.

Understand the basic concept of a Makefile

I have the following makefile which I am trying to upgrade, but there is a certain element which I am not able to understand what means:
$(OBJDIR)/%.o: %.f Makefile
#$(F90) $(FFLAGS) $(POPTIONS) -o $# $<
%.o: %.f Makefile
#make $(OBJDIR)/$#
I understand that $(OBJDIR)/%.o: is obtained by executing the f90 compiler with flags etc.
But why do I need the %.o rule, and what does #make mean. Am I missing a general understanding of how a Makefile work?
#make means invoke make but do not echo that in the output (# symbol). The correct way is #${MAKE} because make may not refer to the make being executed, whereas ${MAKE} does.
In makefiles rules must create the target file they promise to (unless the targed is marked as .PHONY). Here, that %.o rule promises to build that %.o, but what it does in fact is it builds $(OBJDIR)/%.o. This is a broken rule.

Primitive makefile failure for compiling

I am trying to learn makefile, but I fail badly.
One example (which is very primitive) but I should understand it to go ahead is this one
f90_simple: f1.o
gfortran f1.o
mv a.out f90_simple
f90_simple.o: f1.f90
gfortran -c f1.f90
it does not work, and I get this error
I get this error
make: *** No rule to make target `f1.o', needed by `f90_simple'. Stop.
could you please advise me?
thanks
Your first rule says that before f90_simple can be built, the target f1.o must be built.
But there's no rule in your makefile that tells make how to build the target f1.o, and make can't find any built-in rule that can build it (based on the source files make has available), so it prints that error.
You do have a rule that tells make how to build a target f90_simple.o... but that's not the target make is looking for. Most likely you want your makefile to either be:
f90_simple: f1.o
gfortran $^
mv a.out $#
f1.o: f1.f90
gfortran -o $# -c $<
or else:
f90_simple: f90_simple.o
gfortran $^
mv a.out $#
f90_simple.o: f1.f90
gfortran -o $# -c $<
but you can't mix and match them, or make doesn't know what to do.
I think you would really benefit from reading at least the introductory chapters in The GNU Make Manual.

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.

Makefile, executable and object files in different directories

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)

Resources