Makefile shared library error - linux

I was doing makefile test for creating static library and creating dynamic library from it. I have foo.h foo.c bar.c and main.c files in my directory.
I wrote a Makefile as follows:
#This makefile demonstrate the shared and static library creation.
CFLAGS = -Wall -Werror -fPIC
CFLAGS1 = -Wall
inc = /home/betatest/Public/implicit-rule-archive
all : foo.o bar.o libfoo.a libfoo.so run
foo.o: foo.c foo.h
#echo "Making the foo.o"
$(CC) -c $(CFLAGS) $< -o $#
bar.o : bar.c foo.h
#echo "Making the bar.o"
$(CC) -c $(CFLAGS) $< -o $#
libfoo.a(foo.o bar.o) : foo.o bar.o
ar cr $# $^
libfoo.so : libfoo.a
$(CC) -shared -o $# $^
run : main.c
$(CC) -L$(inc) $(CFLAGS1) -o $# $< -lfoo
.PHONY : clean
clean :
-rm -f *.o run libfoo.*
while making it gives the following the following errors:
Making the foo.o
cc -c -Wall -Werror -fPIC foo.c -o foo.o
Making the bar.o
cc -c -Wall -Werror -fPIC bar.c -o bar.o
make: *** No rule to make target 'libfoo.a', needed by 'all'. Stop.
I have written the archive statement as :
libfoo.a(foo.o bar.o) : foo.o bar.o
ar cr $# $^
from this to:
libfoo.a(*.o) : *.o
ar cr $# $^
Can I write the statement like this because in both the cases the error is the same.
I don't understand where I am going wrong. Thanks!!!!!

Instead of libfoo.a(foo.o bar.o) you want plain libfoo.a : foo.o bar.o.
Another thing is that .a files are normally built for linking against the final executable, hence object files for .a are compiled as position-dependent code. Shared libraries, on the other hand, require code compiled as position independent.
Hence, you can:
Get rid of libfoo.a.
Produce header dependencies automatically.
Establish complete dependencies on your targets so that make -j works robustly.
Set rpath so that run always finds libfoo.so in its directory.
This way:
CFLAGS = -Wall -Werror
LDFLAGS = -L/home/betatest/Public/implicit-rule-archive -Wl,-rpath,'$$ORIGIN'
all : run
run : main.o libfoo.so
$(CC) $(LDFLAGS) -o $# $^
libfoo.so : CFLAGS += -fPIC # Build objects for .so with -fPIC.
libfoo.so : foo.o bar.o
$(CC) -shared -o $# $^
# Compile any .o from .c. Also make dependencies automatically.
%.o : %.c
$(CC) -c $(CFLAGS) -o $# -MD -MP $<
# Include dependencies on subsequent builds.
-include $(wildcard *.d)
.PHONY : all clean
clean :
-rm -f *.o *.d run libfoo.*

Related

Undefined reference error while compiling

I'm trying to compile a project that has multiple *.c files and *.h file when I type the following command:
$gcc -c -I ../hdr main.c gestic.c menu.c
the hdr folder is where the *.h files are located, the .o files are created but when I try to link them using the command:
$gcc -o main.o gestic.o menu.o
I see errors
gestic.c:(.text+0x..): undefined reference to functions that are declared in *.h files
$gcc -Wall -c -I../hdr -o main.o main.c
$gcc -Wall -c -I../hdr -o menu.o menu.c
$gcc -Wall -c -I../hdr -o gestic.o gestic.c
$gcc -Wall -o myprogram main.o menu.o gestic.o
Using a Makefile is very common for this task
example (untested) Makefile:
CC=gcc
CFLAGS=-Wall -I../hdr
all: myprogram
myprogram: main.o menu.o gestic.o
$(CC) -o $# $^
gestic.o: gestic.c
$(CC) $(CFLAGS) -c -o $# $<
main.o: main.c
$(CC) $(CFLAGS) -c -o $# $<
menu.o: menu.c
$(CC) $(CFLAGS) -c -o $# $<
Try:
$ gcc main.o gestic.o menu.o
-o filename: Place output in filename
Firstly header files are not included, secondly you might use the function that doesn't contain the definition.
The message undefined reference to 'function_name' implies that of all the object files you're giving to the linker, none of them has a definition for function_name. That means that either
You're not linking with *.o
*.c (as compiled) does not contain a definition for function_name -- by 'as compiled' I mean with all of the various preprocessor options you use on it.
here -Iinclude/
try,
gcc -c file.c -I<include_dir>
If you compile more files better to have makefile to create the objects of those files, link those objects along with header.
Sample makefile,
CC = gcc
CFLAGS = -Wall
INCLUDE = sample.h
OBJ = samople1.o sample2.o
%.o: %.c $(INCLUDE)
$(CC) $(CFLAGS) -c -o $# $<
go: $(OBJ)
gcc $(CFLAGS) -o $# $^

Very strange issue of makefile, No such file or directory

I came across a very strange issue of makefile, here it is:
System: Linux CentOS 6
In the beginning, the name of makefile is “makefile”, its sample contents:
OPTFLAGS = -Wall -g -O
CXX = g++
INC = -I/usr/local/include -I/usr/include
LIBS = -L/usr/local/lib -L/usr/lib64
CXXFLAGS = $(OPTFLAGS) $(INC)
SOURCES = file1.cpp file2.cpp file3.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = mybin
$(EXECUTABLE): $(OBJECTS)
$(CXX) $(CXXFLAGS) $(INC) $(LIBS) $(OBJECTS) -o $#
file1.o : file1.cpp
file2.o : file2.cpp
file3.o : file3.cpp
.PHONY: clean
clean:
rm -f $(EXECUTABLE) *.o core*
I got following err after I ran “make”:
g++: file3.o: No such file or directory
I have a workaround to add a dummy file after file3:
dummy.o : dummy.cpp
This way I could build successfully.
And I know that I can delete all these lines:
file1.o : file1.cpp
file2.o : file2.cpp
file3.o : file3.cpp
let make to build using default settings, I could build successfully this way.
I also tried to just rename “makefile” to “Makefile”, and with following lines without dummy line:
file1.o : file1.cpp
file2.o : file2.cpp
file3.o : file3.cpp
To my surprise, I could build successfully this way.
Could anyone explain why I got error of “No such file or directory” for the last file3 in the beginning?
Following is the error output:
g++ -g -Wall -O -I/usr/local/include -I/usr/include -c -o file1.o file1.cpp
g++ -g -Wall -O -I/usr/local/include -I/usr/include -c -o file2.o file2.cpp
g++ -g -Wall -O -I/usr/local/include -I/usr/include -I/usr/local/include -I/usr/include -L/usr/local/lib -L/usr/lib64 -lsybdb file1.o file2.o file3.o -o mybin
g++: file3.o: No such file or directory
make: *** [mybin] Error 1
Following is the output after I added dummy line:
g++ -Wall -g -O -I/usr/local/include -I/usr/include -c -o file1.o file1.cpp
g++ -Wall -g -O -I/usr/local/include -I/usr/include -c -o file2.o file2.cpp
g++ -Wall -g -O -I/usr/local/include -I/usr/include -c -o file3.o file3.cpp
g++ -Wall -g -O -I/usr/local/include -I/usr/include -I/usr/local/include -I/usr/include -L/usr/local/lib -L/usr/lib64 -lsybdb file1.o file2.o file3.o -o mybin
I tried to rename "makefile" to "Makefile" again, and it doesn't work this time.
Ufffff!! Found your problem.
When you wrote
file1.o : file1.cpp
file2.o : file2.cpp
file3.o : file3.cpp
in your makefile a deamon came and introduced a TAB after the line file3.o : file3.cpp so make instead of taking implicit rule thought you are specifying explicit rule. For file1.o and file2.o it used implicit rule but for file3.o it assumed your are specifying explicit rule because of that TAB, but you had given it a blank TAB so file3.o was never built.
Now when you added dummy.o:dummy.cpp the TAB moved below that line so file3.o was compiled. When you were experimenting around you deleted that TAB that's why renaming makefile to Makefile seemed to work.
Just FYI: there is no difference between Makefile or makefile both are treated equally by make, except when both Makefile and makefile files are there in same folder and you give make then makefile is executed instead of Makefile

I want to know about command in makefile

FC= ifort
FCFLAGS=-O2 -r8 -openmp -mcmodel=large -extend-source -shared-intel -I$(HOME)/usr/include
LDFLAGS=-L$(HOME)/usr/lib -lfftw3 -lm
TARGET=Project
Project: a.o b.o c.o d.o
#
all : $(TARGET)
%: %.o
$(FC) $(FCFLAGS) -o $# $^ $(LDFLAGS)
%.o: %.f90
$(FC) $(FCFLAGS) -c $<
all : $(TARGET)
clean :
rm *.o
when I studied makefile, there is no information for
#
all : $(TARGET)
and function of % and $^. I wanna check about these things. Thanks for your help.
all is a target (repeated twice in that makefile for no reason). So is clean. Targets are how make works. See Rule Example.
$^ is one of the Automatic Variables available for use in target recipes.
% is a wildcard used in some make functions and in Pattern Rules.

How do I create the final executable file using `make`?

I am trying to write a makefile for a small project which uses GTK libraries.
# Compiler
cc = gcc
#Options for Development
CFLAGS = `pkg-config --cflags --libs gtk+-2.0`
all: pss
pss : main.o interface.o
# $(cc) $(CFLAGS) -o pss main.o interface.o
main.o : main.c interface.h
interface.o : interface.c
pss is supposed to be the final executable file. However, the makefile does not create the executable pss. When I explicitly add the line for creating pss, then I am getting a linking error.
asheesh:~/Source$ make
gcc `pkg-config --cflags --libs gtk+-2.0` -o pss main.o interface.o
interface.o: In function `interface':
interface.c:(.text+0x1e): undefined reference to `gtk_init'
interface.c:(.text+0x28): undefined reference to `gtk_window_new'
interface.c:(.text+0x38): undefined reference to `gtk_widget_show'
interface.c:(.text+0x3d): undefined reference to `gtk_main'
collect2: ld returned 1 exit status
make: *** [pss] Error 1
How do I create the final executable file using make?
Changed the makefile to handle library dependencies properly. Still not working.
#Options for Development
CFLAGS = `pkg-config --cflags gtk+-2.0`
#Libraries
LIBS = `pkg-config --libs gtk+-2.0`
all: pss
pss : main.o interface.o
$(cc) $(LIBS) $(CFLAGS) -o pss main.o interface.o
main.o : main.c interface.h
$(cc) $(CFLAGS) -o main.o main.c interface.o
interface.o : interface.c
$(cc) $(CFLAGS) $(LIBS) -o interface.o interface.c
Looks like your compilation phase is not able to find include files. When I see how you built your .o files, there is no -I flag to indicate where to find gtk include files.
You may want to add suffix rules:
.SUFFIXES: .c .o
.c.o:
gcc -c `pkg-config --cflags gtk+-2.0` $<
I am not entirely sure what the problem was, but it got solved by manually specifying the compile commands.
# Compiler
cc = gcc
#Options for Development
CFLAGS = `pkg-config --cflags gtk+-2.0`
#Libraries
LIBS = `pkg-config --libs gtk+-2.0`
all: pss
pss : main.o interface.o
$(cc) -o pss main.o interface.o $(LIBS)
# $(cc) $(LIBS) -o pss main.o interface.o
# This line fails to link whereas the line above works.
main.o : main.c interface.h
$(cc) $(CFLAGS) -c main.c interface.c
interface.o : interface.c
$(cc) $(CFLAGS) -c interface.c
You've forgotten '-c' option while building .o files (in your first message).
You also don't need to include *.o or *.c files in compile phase:
$(cc) $(CFLAGS) -o main.o main.c interface.o // wrong
$(cc) $(CFLAGS) -c -o main.o main.c // right
and to your last code:
# Compiler
CC = gcc // Fixed: CAPSLOCK here
#Options for Development
CFLAGS = `pkg-config --cflags gtk+-2.0`
#Libraries
LIBS = `pkg-config --libs gtk+-2.0`
all: pss
pss : main.o interface.o
$(cc) -o pss main.o interface.o $(LIBS)
# $(cc) $(LIBS) -o pss main.o interface.o
# This line fails to link whereas the line above works.
main.o : main.c interface.h
$(CC) $(CFLAGS) -c main.c
interface.o : interface.c
$(CC) $(CFLAGS) -c interface.c
Also you can write 5 last lines even simpler:
main.o : main.c interface.h
interface.o : interface.c
No recipes needed because of the implicit rule for building .o from .c with recipe in a form:
$(CC) $(CPPFLAGS) $(CFLAGS) -c

Makefile export .o file to a different path than .cpp

So my task is simple, I have created the makefile (New with makefiles) and I want to keep my .o files in a different folder to have a cleaner directory and allow the usage of .o files by others.
I searched and found many solution pointing to using -o $< $#
However, it is giving me that g++: cannot specify -o with -c or -S with multiple files
This is what I want to do:
$(OBJECT_PATH)/file1.o: $(SOURCE_PATH)/file2.cpp $(SOURCE_PATH)/file1.cpp
$(CC) $(CFLAGS) $(SOURCE_PATH)/file2.cpp $(SOURCE_PATH)/file1.cpp -o $#
file1.cpp has #include "file1.h", so from what I read I should include file1.cpp in the dependencies. However, now I can't export to a different directory.
Is there a solution? Or do I have the concept wrong?
Use make -d or even better remake -x to understand what commands are invoked.
Run also make -p to understand what builtin rules are used.
We cannot help you more, because we have no idea if you redefined CFLAGS.
And C++ compilation should better be done with g++ that is CXX and CXXFLAGS, e.g. with (I am extracting this from my make -p output)
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
CXX = g++
%.o: %.cc
$(COMPILE.cc) $(OUTPUT_OPTION) $<
I strongly suggest to have CXXFLAGS= -Wall -g at least during the development phase. Learn also to use gdb and valgrind.
You could have the following in your Makefile
CXXFLAGS= -g -Wall
SOURCES=f1.cc f2.cc
SOURCE_PATH=yoursourcedir/
OBJECT_PATH=yourobjectdir/
SRCFILES=$(patsubst %.cc,$(SOURCE_PATH)/%.cc,$(SOURCES))
OBJFILES=$(patsubst %.cc,$(OBJECT_PATH)/%.o,$(SOURCES))
PROGFILE=$(OBJECT_PATH)
.PHONY: all clean
all: $(PROGFILE)
$(PROGFILE): $(OBJFILES)
$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $#
$(OBJECT_PATH)/%.o: $(SOURCE_PATH)/%.cc
$(COMPILE.cc) $(OUTPUT_OPTION) $<
clean:
$(RM) $(OBJECT_PATH)/*.o $(PROGFILE)
try
$(OBJECT_PATH)/file1.o: $(SOURCE_PATH)/file2.cpp $(SOURCE_PATH)/file1.cpp
$(CC) $(CFLAGS) $^ -c $#
and check that CFLAGS doesn't include -o -c or -s flags
also read about implicit rules. it might help you to orginzie your makefile

Resources