VPATH not wotking in a makefile - linux

I have a very small make file with content
VPATH = src
main: main.o
gcc -o main main.o
main.o: main.c
gcc -c main.c
Current directory contains a directory src which contains main.c
When I execute make, I get error
gcc -c main.c
gcc: main.c: No such file or directory
gcc: no input files
make: *** [main.o] Error 1
When I move main.c in the current directory, it works. It seems VPATH macro is not working. Please let me know the usage of VPATH.

While make locates main.c just fine, you are missing the use of the automatic variables here:
main.o : main.c
gcc -o $# -c $<
which will be expanded by make to the gcc call
gcc -o main.o -c src/main.c
Always use the automatic variables $< (first prerequisite) and $# (target) where you can, they make make both more powerful and easier to read.

Related

Link shared library from another directory

I am building foo.so and that depends on bar.so. They will both be installed in the same location /some/lib, with the RUNPATH set appropriately to /some/lib. But they are built from different directories.
I'm trying to build them like:
cd /tmp/bar
gcc -o bar.o -c bar.c
ld -Bshareable -o bar.so bar.o
cd /tmp/foo
gcc -o foo.o -c foo.c
ld -Bshareable -rpath /some/libs -o foo.so foo.o ../bar/bar.so
ldd foo.so
But the problem is that ldd shows ../bar/bar.so. I can fix it by doing:
cd /tmp/bar
gcc -o bar.o -c bar.c
ld -Bshareable -o bar.so bar.o
cd /tmp/foo
gcc -o foo.o -c foo.c
cp ../bar/bar.so .
ld -Bshareable -rpath /some/lib -o foo.so foo.o bar.so
ldd foo.so
Now the ldd just show plain bar.so, which is right. But is there a better way that doesn't require copying or symlinking bar.so just for the link step?
Solution:
ld -Bshareable -rpath /some/lib -L../bar -o foo.so foo.o -l:bar.so
works without needing to copy bar.so to the current directory.

How to make a makefile rule that stores source code in backup directory?

So I have this make file
#makefile to build a program
#program depends on components: name and main
myname: main.o name.o
g++ -c -g name.cpp
# name.cpp has it's own header file
name.o: name.cpp name.h
g++ -c -g name.cpp
# main.cpp also user the header file name.h
main.o: main.cpp name.h
g++ -c -g main.cpp
clean:
/bin/rm -f myname *.o
I need to modify the makefile to include a rule that creates a backup of the source files, makefile, and readme in an archive directory. This rule needs to create a tar.gz file containing the files I mentioned. The.tar.gz file should be placed in a directory named backup within my current working directory. This backup rule should be executed by 'make backup' and the output should be a .tar.gz file in the backup directory. This backup rule should create the directory if it does not already exist.
Any help would be greatly appreciated
EDIT: the makefile already works as intended as is, I just need to figure out how to add this rule.
PROG := myname
HDR := name.h
SRC := main.cpp name.cpp
OBJ := main.o name.o
ARCHIVE := tar.gz
TARFILES := $(SRC) $(HDR) makefile readme
# original
myname: main.o name.o
g++ -c -g name.cpp
# suggested replacement
# $(PROG): $(OBJ)
# g++ -g $(OBJ) -o $#
name.o: name.cpp name.h
g++ -c -g name.cpp
main.o: main.cpp name.h
g++ -c -g main.cpp
clean:
/bin/rm -f $(PROG) $(OBJ)
.PHONY: backup
backup:
#mkdir -p $#
tar zcvf $#/$(ARCHIVE) $(TARFILES)

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 $# $^

Makefile shared library error

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.*

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