Using gfortran with libraries - makefile

I have a legacy code written using fortran 77. I'm trying to build it with gfortran. But I seem to be failing at the stage where I include the libraries in the build. The dozens of *.f source files compile fine, but when they are being linked, I get a bunch of "undefined reference" errors all relating to subroutines and functions that are defined in my libraries. I already ran the makefile for the libraries first, so the variables I need should all be exported. I'm playing with the "-L" option, but can't get it to work as desired.
First, here's my syntax of the linking line in my makefile:
29 $(PROGRAM): $(SRCS) $(LIBS)
30 $(FC) $(FLFLAGS) -o $# $+ -L$(DIRLIB)
PROGRAM is the program name, SRCS are all the compiled source files, LIBS is set to two different files - an archive file (file.a) and a file.o file.
FC is gfortran, I don't have any specific linking flags for FLFLAGS as of now, and DIRLIB is the main directory of the libraries.
The thing is that my *.o files that resulted from building my librarires don't reside in just the main directory, DIRLIB. DIRLIB contains several directories, all with their own *.o files that are needed by my code.
I tried adding each individual directory after the -L option (e.g. DIRLIB/DIR1/*.o DIRLIB/DIR2/*.o DIRLIB/DIR3/*.o), but I eventually start getting errors that some subroutines are multiply defined.
All this business of user-defined libraries and archive files just confuses me and I'm pretty new to making makefiles in the first place, so I'm just taking a shot in the dark here that somebody might be able to help me shed some light on this.

Libraries need to come after the .o files that reference them in the linking command.
I'm guessing the object file in LIBS comes after the library, but needs some of the procedures from it. Can you show the command that is actually run (with all variables expanded), to confirm this?

I tried to build this code again using the library. It worked this time. I'm pretty sure I'm doing the same thing in my makefile as I did before, so it must be related to the library I had. Maybe somebody altered it along the way and inadvertently broke it. But I got a fresh clean copy of the library. My steps are to:
1) run the makefile for the library source files; it creates a library.a archive file
2) run my code makefile:
it has a line to specify the location of this archive file and assign it to "DIRLIB"
DIRLIB := ../library
then the linking command of the makefile becomes
$(FC) $(FLFLAGS) -o $# $+ -L$(DIRLIB) -lskit
FC is my compiler, FLFLAGS are my linking flags, -L is the option specifying the location of libraries to be included and -lskit is a crucial option which appears to allow the use of F77 libraries... without the -lskit option, I get many undefined reference errors. It may have been that last time I was not including this -lskit option at the end.

Related

GCC creating dependencies for generated header files in proper directory

I use GCC to create dependency files, from header files stored in a
certain directory. Here is my recipe:
gcc -MM -MG -MT obj/$*.o -MP -MF dep/$*.Td -I include $<
One of these header files is generated (with Bison 3.0.5), so it may not
exist. I therefore use the -MG option as shown above, but it generates
a dependency without the directory. How can I tweak make or GCC to
prepend the include directory to the generated header?
Thanks in advance
dordow
Typically, the search path has many entries, and if the header file does not exist, it is unclear which prefix to pick.
The cook build tool comes with a program, c_incl, which scans C source files for #include directives and can be made to behave in the way you intend, with a command like c_incl -No_Cache -Absent_System_Mention -Iinclude -C. But this tool is fairly obscure.
It is probably better to use a slightly less obscure GNU make feature instead: order-only prerequisites, as described in Types of Prerequisites. You would list the generated header files (or other Bison output files) as order-only prerequisites for all rules that compile C files, so that they are generated early on first build, but do not needlessly trigger rebuilds afterwards. With this approach, you do not need to generate dependencies on files which do not exist yet.

Specific "cannot open shared object file" error

I'm a first year computer science student following a course on (amongst others) Makefiles. For our first assignment, we had to create a shared library and link against it.
I have the following setup:
A folder hw1 containing the folders app and lib.
Inside lib is a file called libmine.so, the library I want to link against.
Inside app, there are two files: test.cpp and a Makefile. The former uses the libmine library.
The Makefile is as follows (in the file itself, indentation etc. is correct):
all: test
test: test.cpp
g++ -Wall -o test -L../lib -I../lib/include test.cpp -lmine
However, when running test, I get the infamous `libmine.so: cannot open shared object file' error.
I believe this has something to do with exporting LD_LIBRARY_PATH. I have tried doing so (export LD_LIBRARY_PATH=$[very long relative path to the lib folder]), but I want to do this in my Makefile. Additionally, I don't want the path to be relative, as my teachter should be able to open the file when I send it to him (so I think it should be something like ../lib/libmine.so).
I looked at various StackOverflow posts, such as this one, but none seemed to answer this specific question (either it was a different setup or the solution simply didn't work). By the way: putting the line export LD_LIBRARY_PATH=../lib right under test: test.cpp and before the g++ command did not do anything.
Any help is much appreciated :)
when running test, I get the infamous `libmine.so: cannot open shared object file' error.
This is happening because the -L../lib argument tells the static linker where to find the library, but it doesn't tell anything to the dynamic linker (aka loader), and the problem is that the latter can't find this library.
To solve this, you can use LD_LIBRARY_PATH, but this is usually ill-advised.
What you want is something called RPATH or RUNPATH (assuming you are on a Linux or similar system):
g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath=../lib -lmine
Additionally, I don't want the path to be relative, as my teachter should be able to open the file when I send it to him
Is your teacher going to run your binary on the same system, or on a different one? If the former, you could do this:
g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath=/full/path/to/hw1/lib -lmine
If the latter, /full/path/to/hw1/lib may or may not be available on your teacher's machine, and you need to think about what exactly you are going to send to him.
The usual way to solve this is to package both the application and the library into a tar file:
tar cvf to-send.tar app/test lib/libmine.so
The teacher can then extract the parts of your tar file into arbitrary directory, and try to run it. To make this work, you need RPATH that is relative to the application, regardless of where the application ends up. To achieve that, you want:
g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath='$ORIGIN/../lib' -lmine

Trouble with simple makefile in C

I am somewhat of a beginner in C and have a project due where I need to include a makefile to compile my single file program that uses pthreads and semaphores. My makefile looks like:
# Makefile for pizza program
pizza: pizza.o
gcc -lrt -lpthread -g -o pizza pizza.o
pizza.o: pizza.c
gcc -lrt -lpthread -g -c pizza.o pizza.c
and I keep getting:
make: Nothing to be done for 'Makefile'.
I have done several makefiles before and have never gotten this message. I've tried different semantics in the makefile and have only gotten this same message. And yes, the command is tabbed after the target and dependency line.
Using gcc on tcsh. I have read other makefile posts on SO but I wasn't able to use any of the answers to figure it out for my case.
Any help would be greatly appreciated!
The arguments to make are the targets to be built.
You are running make Makefile which is telling make to try to build the Makefile target.
There is no such target in your makefile, make has no built-in rule that applies to that target and the file exists (and is assumed to be up-to-date) which is what that message is telling you.
To run the default target (by default the first target listed) you can just run make (assuming you are using a default name like Makefile for your makefile).
You can also use the -f argument to make to select an alternate makefile name.
So make -f Makefile will in this case (since Makefile is a default searched name) do the same thing as make.

make command with math library

I need to just run the make command for makefile. But when I run this make command I get the error that "undefined reference to `log'" because I know this fact that it doesn't include math Library and we have to include at runtime. I know that if I run this using gcc comiler then i can write -lm at the end, it will include math library. My problem is I need to run it using make command that is- make lu.
In this if I write make lu -lm it is not linking math library. Please help
Using this link How to use LDFLAGS in makefile
I updated my make file but still same problem persists. Please Help.
SHELL=/bin/sh
BENCHMARK=ep
BENCHMARKU=EP
include ../config/make.def
OBJS = ep.o ${COMMON}/c_print_results.o ${COMMON}/c_${RAND}.o \
${COMMON}/c_timers.o ${COMMON}/c_wtime.o
include ../sys/make.common
LDLIBS=-lm
LDFLAGS=-lm
${PROGRAM}: config ${OBJS}
${CLINK} ${CLINKFLAGS} -o ${PROGRAM} $(LDFLAGS) $(LOADLIBES) ${OBJS} ${C_LIB}
ep.o: ep.c npbparams.h
${CCOMPILE} ep.c
clean:
- rm -f *.o *~
- rm -f npbparams.h core
Why does your makefile refer to all sorts of variables that don't exist, like LOADLIBES, C_LIB? Why do you set variables that you never use, like LDLIBS?
The reason it doesn't work is that you're putting the library reference in the LDFLAGS variable, which comes early in your link command before any of your object files. So when the linker goes to link in the math library it thinks that it's not needed because nothing is using it yet.
You have to put libraries at the end of the link line.
Since you already have the C_LIB variable at the end which you are not using, if you add:
C_LIB = -lm
then it should work.

How can I use a makefile for D?

I have written complicated C and C++ makefiles in the past. However, I cannot seem to get my D makefile to work. It throws over a thousand lines of "undefined reference" errors, which look as if Phobos is failing to be linked. How can I fix that?
I am using GNU make and LDC2 on Fedora 19 Linux.
Edit: Compiling and linking directly using LDC2 works correctly. Only when invoked with 'make' is there an error. It seems that make is trying to invoke a separate linker.
Edit 2: Here is my makefile:
# This macro contains the source files
sources := $(wildcard *.d)
binaries := $(sources:%.d=%)
all: $(binaries)
%.o:%.d
ldc2 $< -O5 -check-printf-calls
Deleting the .o fixed it.
I don't know the intricacies of Pattern Rules, but I believe that is where your problem lies.
%.o:%.d
ldc2 $< -O5 -check-printf-calls
You've asked make to convert every .d file into a .o by calling the ldc2 command. However, you aren't requesting ldc2 to build object files, you're asking it to build an executable (I don't know which flag you want dmd/gdc: -c). Though I would have expected compiler errors from this before linker.
By removing the .o I must assume that Make is instead passing all the .d files at once rather than individually.

Resources