automake putting object files after libraries - gcc

src/Makefile.am:
myproj_CXXFLAGS = -fopenmp -O3 -std=c++17 -g -I/home/software/miniconda3/include -I$(top_srcdir)/external
myproj_LDFLAGS = -L/home/software/miniconda3/lib -Wl,-rpath=/home/software/miniconda3/lib -fopenmp -lz -ligraph -pthread
bin_PROGRAMS = myproj
myproj_SOURCES = gfa.cpp graph.cpp myproj.cpp gfa.h graph.h
bindir = $(top_srcdir)/bin
This builds the object files just fine, but when building the target, it tries running
g++ -fopenmp -O3 -std=c++17 -g -I/home/software/miniconda3/include -I../external -g -O2 -L/home/software/miniconda3/lib -Wl,-rpath=/home/software/miniconda3/lib -fopenmp -lz -ligraph -pthread -o myproj myproj-gfa.o myproj-graph.o myproj-komb.o
The issue with this is that the object files come after the library files, which causes the error
/home/software/miniconda3/lib/libz.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
I can easily fix this by adding the -lz -ligraph flags at the very end, but how can I get automake to add the LDFLAGS after the object files as opposed to before?

That's because you're using the wrong variable. To pass libraries, you should use myproj_LDADD, not myproj_LDFLAGS.

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

Cannot find -mpich when using make

Trying to install this software, and having extracted the tarball, attemping to make I get the error:
/usr/bin/ld: cannot find -lmpich
collect2: error: ld returned 1 exit status
Makefile:162: recipe for target 'N-GenIC' failed
In the Makefile we have:
SYSTYPE="Chris#Adam"
FFTW_INCL = -I/usr/common/pdsoft/include
FFTW_LIBS = -L/usr/common/pdsoft/lib
CC = mpicc # sets the C-compiler (default)
OPTIMIZE = -O3 -Wall # optimization and warning flags (default)
MPICHLIB = -lmpich
#————————————— Adjust settings for target computer
ifeq ($(SYSTYPE),”Chris#Adam”)
CC = mpicc
OPTIMIZE = -O3 -Wall
GSL_INCL = -I/usr/local/include
GSL_LIBS = -L/usr/local/lib
FFTW_INCL= -I/usr/local/include
FFTW_LIBS= -L/usr/local/lib
MPICHLIB = -L/usr/lib
endif
...
LIBS = -lm $(MPICHLIB) $(FFTW_LIB) $(GSL_LIBS) -lgsl -lgslcblas
Now 2 things confuse me about this - I recently intalled GADGET2 which has an almost identical Makefile, also with:
SYSTYPE=”Chris#Adam”
#————————————— Adjust settings for target computer
ifeq ($(SYSTYPE),”Chris#Adam”)
CC = mpicc
OPTIMIZE = -O3 -Wall
GSL_INCL = -I/usr/local/include
GSL_LIBS = -L/usr/local/lib
FFTW_INCL= -I/usr/local/include
FFTW_LIBS= -L/usr/local/lib
MPICHLIB = -L/usr/lib
endif
...
LIBS = $(HDF5LIB) -g $(MPICHLIB) $(GSL_LIBS) -lgsl -lgslcblas -lm $(FFTW_LIB)
so what I don't understand is why is it fine to make GADGET2 but not the other package I'm trying to install? And what's causing the error? I have read some previous questions on this with similar errors and they suggest adding a symlink, but I can't even find where mpich is actually stored, the only executable or symlink i can find is mpicc.
If you're using the mpicc that's provided with MPICH, there's no need to add -lmpich your flags. The mpicc wrapper should take care of all of that for you. If you want to see what mpicc turns into, you can use mpicc -show.

gcc and linking files with CFLAGS

I am trying to run program from the Learn C Hard Way book
I need to pass the library filename 'build/liblcthw.a' as the last parameter.
For eg :
Doesnt Work on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
Works on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/list_tests.c -o tests/list_tests build/liblcthw.a
How do I handle this in Makefile ? CFLAGS will only add it before the source filename and it doesnt work. How do I force CFALGS to add the library filename at the end of the command ?
CFLAGS are flags for the C compiler. Libraries typically go into a variable called LDLIBS. Set LDLIBS=build/liblcthw.a and see if that works.
The first invocation doesn't succeed because the order of sources and libraries in the command line is wrong. The correct order is source files, then object files, followed by static libraries followed by dynamic libraries.

Ubuntu LDFLAGS --as-needed

I have a C project that won't link correctly, and I suspect it's because of the --as-needed flag passed to the ld program by gcc. Because of that flag, gcc sees any linked library listed as an option before the *.c files as unnecessary, and won't link them.
PREFIX?=/usr/local
CFLAGS=-D_LARGEFILE64_SOURCE=1 -g -Wall -I${PREFIX}/apr/include/apr-1 -I${PREFIX}/apr/include/apr-util-1
LDFLAGS=-lapr-1 -pthread -laprutil-1
all: devpkg
devpkg: bstrlib.o db.o shell.o commands.o
install: all
install -d $(DESTDIR)/$(PREFIX)/bin/
install devpkg $(DESTDIR)/$(PREFIX)/bin/
clean:
rm -f *.o
rm -f devpkg
rm -rf *.dSYM
When I run this makefile I get the following.
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o bstrlib.o bstrlib.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o db.o db.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o shell.o shell.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -c -o commands.o commands.c
cc -D_LARGEFILE64_SOURCE=1 -g -Wall -I/usr/local/apr/include/apr-1 -I/usr/local/apr/include/apr-util-1 -lapr-1 -pthread -laprutil-1 devpkg.c bstrlib.o db.o shell.o commands.o -o devpkg
/tmp/ccZcAm9b.o: In function `main':
/home/zach/Desktop/devpkgzed/devpkg.c:14: undefined reference to `apr_pool_initialize'
/home/zach/Desktop/devpkgzed/devpkg.c:15: undefined reference to `apr_pool_create_ex'
/home/zach/Desktop/devpkgzed/devpkg.c:29: undefined reference to `apr_getopt_init'
/home/zach/Desktop/devpkgzed/devpkg.c:31: undefined reference to `apr_getopt'
My issue is that I don't really understand how make is coming up with these commands via the CFLAGS that are set. How can I get the linker options to follow the compilation part instead of the other way around, which is triggering this issue?
Make has built-in rules to compile source files and link executables and libraries. The commands you list are produced by these rules.
The reason this fails for you is that, when linking, libraries should be listed after object files, because the linker does a single pass through its arguments and will discard any symbols that are not unresolved at the time they are seen. To correct it, put your libraries in the LDLIBS variable, not the LDFLAGS variable (i.e. just replace LDFLAGS by LDLIBS). The LDFLAGS variable is meant for non-library options for the linker, such as -L or -shared etc

Resources