How to translate this command into a makefile file? - gcc

gcc testr.c -L/usr/local/hdf/hdf5/lib /usr/local/hdf/hdf5/lib/libhdf5_hl.a /usr/local/hdf/hdf5/lib/libhdf5.a -ldl -lstdc++ -lm -Wl,-rpath -Wl,/usr/local/hdf/hdf5/lib -I /usr/local/hdf/hdf5/include
there is a source file named testr.c, above is the command, and the below is my unfinished example.
LIB=-L/usr/local/hdf/hdf5/lib
INC=-I/usr/local/hdf/hdf5/include
testr: testr.c
gcc -o testr testr.c -I.

Let's start with the simplest conversion possible:
something:
gcc testr.c -L/usr/local/hdf/hdf5/lib /usr/local/hdf/hdf5/lib/libhdf5_hl.a /usr/local/hdf/hdf5/lib/libhdf5.a -ldl -lstdc++ -lm -Wl,-rpath -Wl,/usr/local/hdf/hdf5/lib -I /usr/local/hdf/hdf5/include
We notice that usr/local/hdf/hdf5 comes up a lot, so we put that in a variable:
HDF5 := /usr/local/hdf/hdf5
something:
gcc testr.c -L$(HDF5)/lib $(HDF5)/lib/libhdf5_hl.a $(HDF5)/lib/libhdf5.a -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
Now it's clear that you can invoke the static libraries in a more concise way:
something:
gcc testr.c -L$(HDF5)/lib -lhdf5_hl -lhdf5 -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
And clearly the intended target is testr, and the source ought to be a prerequisite:
testr: testr.c
gcc testr.c -L$(HDF5)/lib -lhdf5_hl -lhdf5 -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
Add a couple of automatic variables:
testr: testr.c
gcc $< -o $# -L$(HDF5)/lib -lhdf5_hl -lhdf5 -ldl -lstdc++ -lm -Wl,-rpath -Wl,$(HDF5)/lib -I $(HDF5)/include
That's a pretty good rule. We could go a little further, depending on what other targets you'd like Make to build, but that should be enough for now. Don't forget to test each step of the above, before you adopt the final version.

Alternatively, you could use predefined implicit rules and just define appropriate variables and the target:
DIR = /usr/local/hdf/hdf5/
INC = $(DIR)include
LIB = $(DIR)lib
CPPFLAGS = -I$(INC)
LDFLAGS = -L$(LIB) -Wl,-rpath,$(LIB)
LOADLIBES = $(LIB)/libhdf5_hl.a $(LIB)/libhdf5.a
LDLIBS = -ldl -lstdc++ -lm
testr:
Note that this way as well as with Beta's solution, the output file is named testr instead of a.out with your original command.

Related

Understanding error from ld "archive member is not mach-o or llvm bitcode file"

I'm getting the following error when trying to link a code on a Mac (Montery). First let me say that up until a recent upgrade to Xcode the code built fine. GCC is 10, OpenMPI and it's a Fortran code. Now there are multiple executables which build and one libaray. The library compiles fine and is archived via ar (ar -ruvs). For example, here's a compile and build line for a code.
mpif90 -O2 -g -fexternal-blas -fbacktrace -fcheck=all,no-array-temps -fallow-argument-mismatch -I../../LIBSTELL/Release -I/opt/local/include -I. -c ../Sources/boozer_coords.f
mpif90 -shared -Wl,-no_compact_unwind -O2 -g -fexternal-blas -fbacktrace -fcheck=all,no-array-temps -fallow-argument-mismatch -I../../LIBSTELL/Release -I/opt/local/include -o xbooz_xform booz_jac.o read_wout_booz.o foranl.o allocate_boozer.o transpmn.o boozer_xform.o setup_booz.o write_boozmn.o harfun.o trigfunc.o booz_params.o vcoords.o boozer.o free_mem_boozer.o boozer_coords.o booz_persistent.o ../../LIBSTELL/Release/libstell.a -L/usr/lib -L/opt/local/lib -lopenblas -lscalapack -L/opt/local/lib -lnetcdf -lnetcdff -L/opt/local/lib -lfftw3 -L/opt/local/lib -lhdf5hl_fortran -lhdf5_hl -lhdf5_fortran -lhdf5 -lz -ldl -lm
This works fine and produces an executable. However, there is another code which links to this code. For that reason archives are made of the compiled code.
mpif90 -ffree-form -ffree-line-length-none -ffixed-line-length-none -O2 -g -fexternal-blas -fbacktrace -fcheck=all,no-array-temps -fallow-argument-mismatch -I../../LIBSTELL/Release -I../../BOOTSJ/Release -I/opt/local/include -I/opt/local/include -I. -c ../Sources/thrift_main.f90
mpif90 -shared -Wl,-no_compact_unwind -O2 -g -fexternal-blas -fbacktrace -fcheck=all,no-array-temps -fallow-argument-mismatch -I../../LIBSTELL/Release -I/opt/local/include -o xthrift thrift_interface_mod.o thrift_runtime.o thrift_main.o ../../BOOTSJ/Release/libbootsj.a ../../LIBSTELL/Release/libstell.a -L/usr/lib -L/opt/local/lib -lopenblas -lscalapack -L/opt/local/lib -lnetcdf -lnetcdff -L/opt/local/lib -lfftw3 -L/opt/local/lib -lhdf5hl_fortran -lhdf5_hl -lhdf5_fortran -lhdf5 -lz -ldl -lm
ld: in ../../BOOTSJ/Release/libbootsj.a(parambs.mod), archive member 'parambs.mod' with length 2800 is not mach-o or llvm bitcode file '../../BOOTSJ/Release/libbootsj.a' for architecture x86_64
collect2: error: ld returned 1 exit status
I've had limited success trying to understand the source of this error. Here's what the table for the archive looks like.
ar -t ../BOOTSJ/Release/libbootsj.a
__.SYMDEF SORTED
SIMPUN.o
al31.o
allocate_angles.o
allocate_radial.o
bongrid.o
bootsj.o
caprsh2.o
datain.o
deallocate_all.o
denmf.o
do_fft.o
driver.o
fraction.o
grad.o
othersums.o
output.o
parambs.o
positiv.o
read_boozer.o
reorganz.o
smooth1.o
sumit.o
temp.o
tok_fraction.o
trig.o
vmec0.o
woflam.o
parambs.mod
trig.mod
vmec0.mod
OK so I was adding the module files (.mod) to the archive. This was incorrect. Only the Object (.o) files should be in the archive.
If I understand correctly the compiler will use the -I <path> command to look for (.mod) files. So the archive only needs the object files.

no profiling data created while compiling with gcc

I want to use the gprof profiling option in order to speed up my code. I am compiling with gcc. The problem is that there is not output file created 'gmon.out' or so. Here is a sample of the Makefile I am using:
CC = gcc
LD = gcc
#LIBGSL = -L/usr/local/lib -lgsl -lgslcblas
#LIBGSL = -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas -lm
#LIBGSL = -L/home/dupont/gsl/gsl-2.4/lib -lgsl -lgslcblas -lm
LIBGSL = -L/n1/soft/64bit/lib -lgsl -lgslcblas -lm
CFLAGSRELEASE = -g -fopenmp -O -Wall -c -pg -I/n1/hhsoft/64bit/include
LFLAGSRELEASE = -g -pg -lm -Wl,--rpath -Wl,/usr/local/lib $(LIBGSL)
CFLAGSDEBUG = -g -p -pg -Wall
LFLAGSDEBUG = -lm
CFLAGSDEBUG = -g -p -pg -Wall -W # -DDEBUG_OUTPUT
LFLAGSDEBUG = -lm -p -pg -Wl,--rpath -Wl,/usr/local/lib $(LIBGSL)
LIBS= -L/home/dupont/folder/soft/pgplot -lm -lcpgplot /home/dupont/folder/soft/pgplot/libpgplot.a -L/usr/X11R6/lib -lX11
CFLAGS = $(CFLAGSRELEASE)
LFLAGS = $(LFLAGSRELEASE)
I don't know much about makefile, do you have any idea of what the problem could be...?
https://sourceware.org/binutils/docs-2.31/gprof/Executing.html
Your program will write the profile data into a file called gmon.out just before exiting
So there's nothing wrong if make produces your program but not gmon.out.
(anyway, you should remove -p, and ensure you use -pg both for compilation and link).

GCC Static Linking And Separate Loader

I'm trying to understand the process of static linking, loading of GCC:
I have the following toy program
#include "stdio.h"
int main() {
fprintf(stdout, "Hello World \n");
return 0 ;
}
I can compile it and run file as follows:
gcc -static -std=gnu99 -Wall -Wno-unused -g test.c -o test;
But as soon as I try to separate out the compile and linking process as follows:
gcc -static -std=gnu99 -Wall -Wno-unused -g test.c -c;
ld -o test -T link.lds test.o
where the link.lds is
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
I get the error "undefined reference to stdouttest.o: In function `main':
test.c:(.text+0x7): undefined reference to `stdout'
test.c:(.text+0x1e): undefined reference to `fwrite'
If I try adding the flag -lc to ld, it tells me that it is not found. I've tried running gcc with -lc
and/or -static-libgcc but I have the same problem.
What am I doing wrong?
Do
gcc -v -static -std=gnu99 -Wall -Wno-unused -g test.c
and look for the collect2 tag.
In my case it is
collect2 --sysroot=/ --build-id -m elf_x86_64 --hash-style=gnu --as-needed -static -z relro -o test /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbeginT.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. /tmp/ccoR98Xr.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
You have to replace the temporary object file. In my case I replaced /tmp/ccoR98Xr.o with test.o. Then do
gcc -c -std=gnu99 -Wall -Wno-unused -g test.c
ld --sysroot=/ --build-id -m elf_x86_64 --hash-style=gnu --as-needed -static -z relro -o test /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbeginT.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. test.o --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
It links to the object files : crt1.o, crti.o, crtbeginT.o, crtend.o, and crtn.o.
It links to the libraires: libgcc.a, libgcc_eh.a, and libc.a.
You can replace --start-group -lgcc -lgcc_eh -lc --end-group with -lgcc -lc -lgcc_eh -lc if you like.
Knowing this we can simply this to
ln -s `gcc -print-file-name=crt1.o`
ln -s `gcc -print-file-name=crti.o`
ln -s `gcc -print-file-name=crtn.o`
ln -s `gcc -print-file-name=libgcc_eh.a`
ln -s `gcc -print-file-name=libc.a`
gcc -c -std=gnu99 -Wall -Wno-unused -g test.c
ld -m elf_x86_64 -o test crt1.o crti.o test.o libc.a libgcc_eh.a libc.a crtn.o
I did not use crtbeginT.o, crtend.o, and libgcc.a because it worked without them.
Take a look at this, strace does the job (show you the secrets) but you will soon realize there are tons of options in it... You need to link a few stuff together (from GNU C lib) to get your executable, not only your object... You can add grep 'exec' in the end to make it cleaner.
Uhhh, also you need to do this:
as obj.s -o obj.o
Use GNU assembler to convert your .s to .o then link with ld.

Can't link static lib for android NDK, cygwin gcc

I have PROJ4 library, succesfully compiled under cygwin and installed to /usr/local.
I'm trying to compile as:
$ arm-linux-androideabi-gcc -o conftest -mthumb temp.c -lproj -L/usr/local/lib -lproj -lz -lm -ldl
C:/dev/Android/android-ndk-r7c/android-8-toolchain/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe: cannot find -lproj
collect2: ld returned 1 exit status
What am I doing wrong?
Try
$ arm-linux-androideabi-gcc -o conftest -mthumb temp.c /usr/local/lib/libproj.a -lz -lm -ldl
Well, the problem is that android-gcc doesn't understand cygwin path, so we need to use windows path:
$ arm-linux-androideabi-gcc -o conftest -mthumb temp.c -lproj -Lc:/path/to/lib -lproj -lz -lm -ldl

Boost static linking in unix

I am using the Boost library in Unix, GCC. I read the following topic: Boost static linking and added -static to my Makefile. However, this does not work.
Here is my Makefile:
all: nbbo
nbbo: nbbo.o reader.o
g++ -static -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -L/usr/lib -lboost_filesystem -lboost_serialization -lboost_iostreams -lz -I /usr/include/boost -o nbbo nbbo.o reader.o
nbbo.o: nbbo.cpp
g++ -static -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -I /usr/include/boost -c -o nbbo.o nbbo.cpp
reader.o: reader.cc reader.h
g++ -static -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -I /usr/include/boost -c -o reader.o reader.cc
clean:
rm *.o
And here is the error message:
nbbo.o: In function `__tcf_10':
nbbo.cpp:(.text+0x3d9): undefined reference to `boost::serialization::extended_type_info::key_unregister() const'
nbbo.cpp:(.text+0x3e3): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::type_unregister()'
nbbo.cpp:(.text+0x3fb): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::~extended_type_info_typeid_0()'
etc
Which "UNIX" are you using? Using the -static flag should work fine on linux. But not on OSX. On OSX you have to remove the static flag and give the complete path to the library in order to link statically. I dont know how this would work on other "UNIXes"
eg.
g++ ..... /path/to/your/lib.a ... -o ..

Resources