How to do a Makefile using a specific libraries in different paths? - makefile

The issue I'm having is that I need to compile my code using specific libraries that are in different path locations. I need to use -lncurses library from ./ramdisk/libs path, the problem is that this directory also cointains a version of lthr library that I don't want to be linked. The makefile is pulling both libraries from the same location which is not what I want. I can't change the contents of these library directories in the filesystem, so I need to find a way to tell the Makefile to link lncurses library from path A and link lthr library from path B instead using the lthr from path A.
Any suggestions?
CC=icc
NCE=-L./ramdisk/libs
CFLAGS+=-I$(ROOTDIR)/../../include
#LDFLAGS=-static -lthr
$(DESTDIR)/nce: nce
mkdir -p $(DESTDIR)
$(INSTALL) -m 777 nce $(DESTDIR)
nce: nce.c
$(CC) $(CFLAGS) nce.c $(LDFLAGS) -o nce -lthr $(NCE) -lncurses

You can (probably) bypass the search by giving the full path to the library archive. So instead of specifying -lncurses, you might try ./ramdisk/libs/libncurses.a (or whatever). You didn't specify whether it was a shared lib or not, and I'm not entirely sure that this works for shared libraries, but probably worth a try.
[edit]
Since this is a shared lib issues, maybe something like:
CC=icc
THR=/full/path/to/wherever/libthr/lives
NCE=/full/path/to/ramdisk/libs
CFLAGS+=-I$(ROOTDIR)/../../include
LDFLAGS=-static
nce: nce.c
$(CC) $(CFLAGS) nce.c $(LDFLAGS) -o nce -L$(THR) -W,-rpath=$(THR) -lthr -L$(NCE) -W,-rpath=$(NCE) -lncurses
I'm kind of shooting in the dark here as I'm not familiar with icc, but the idea is to make sure the linker puts thr's path on the runtime linker's search path before the one on the ramdisk so that thr gets found there first.

You could copy the remote library to a local working directory.
ncurses would source from one location while thr would source from another.

Related

REPAST HPC WSL Installation leads to boost no being found

When trying to run Repast HPC executables I get the following error:
./main.exe: error while loading shared libraries: libboost_mpi-mt.so.1.61.0: cannot open shared object file: No such file or directory ./main.exe: error while loading shared libraries: libboost_mpi-mt.so.1.61.0: cannot open shared object
In the make file I define the link to boost in an env file with the below:
BOOST_INCLUDE= -I$(HOME)/sfw/Boost/Boost_1.61/include/
BOOST_LIB_DIR= -L$(HOME)/sfw/Boost/Boost_1.61/lib/
This is linked to a make file with the following make file
include ./env
.PHONY: clean
clean:
rm -f *.o
rm -f *.exe
.PHONY: compile
compile:
$(MPICXX) $(BOOST_INCLUDE) -c Main.cpp -o Main.o
$(MPICXX) $(BOOST_LIB_DIR) -o main.exe Main.o $(BOOST_LIBS)
.PHONY: all
all: clean compile
Boost in tsnow#DESKTOP-IF7CEHL:~/sfw/Boost/Boost_1.61/lib$ so it should link well across.
Any help appreciated, just trying to get a tutorial running.
We typically don't link repast to boost, but rather use rpath to let the model executable know where the boost and repast libraries are. For example in your Makefile:
REPAST_LIB_DIR = $(REPAST_HOME)/lib
BOOST_LIB_DIR = $(HOME)/theta/sfw/boost-1.66.0/lib
RPATHS += -Wl,-rpath -Wl,$(REPAST_LIB_DIR) -Wl,-rpath -Wl,$(BOOST_LIB_DIR)
and then add $(RPATHS) after the list of libraries during linking.
model : $(EXEC_OBJECTS)
$(CXXLD) -fopenmp -dynamic $^ $(LIBS) $(RPATHS) -o $(NAME)
Some of those args might not be appropriate for WSL, but hopefully the RPATHS part makes sense.
So, if after your include directive, you add
RPATHS=-Wl,-rpath -Wl,$(BOOST_LIB_DIR)
and update the second line of your compile target with
$(MPICXX) $(BOOST_LIB_DIR) -o main.exe Main.o $(BOOST_LIBS) $(RPATHS)
The location of your boost libs is compiled into main.exe, and it should find it.
The command:
export LD_LIBRARY_PATH=/home/tsnow/sfw/Boost/Boost_1.61/lib/
allowed boost to be found.

How to create and link a static library for an ARM project using arm-none-eabi-gcc?

I want to create a static library libmylib.a from mylib.c/.h and link it to a project to use this library in bootloader code using the arm-none-eabi-gcc cross compiler in ubuntu 20.04 LTS.
I have an electronic engineering background, so I'm kind of new in this compiler and linker stuff.
What I know:
I've been searching about this, and found out that '.a' are just packed '.o' files, and that's it. You can do it using ar in linux. I don't know how to manage the dependencies for this '.a' file, for example, or how to link it to the project.
What I want to know:
I really want to understand how it works, to compile and generate the bin, elf or hex files using these static libraries for arm using the arm-none-eabi-gcc cross compiler (found some for linux), but I don't know how to search for this properly, how to learn it in a linear way. If you guys could help me on this I would be really grateful.
First you create your library objects. Let us say that you have a foo function written in foo.c, then you do:
arm-none-eabi-gcc -c foo.c
The -c options tells the compiler to stop after assembling and no go further.
Then you need to create the .a file
arm-none-eabi-ar -rc libfoo.a foo.o
this command creates a static library called libfoo.a
At the end you compile your main with:
arm-none-eabi-gcc -L. -lfoo main.c -o main
Note that in -l flag we don put "lib" and ".a", those are automagically added. The -L. flag tells gcc to look into the current folder for library files.

Makefile library prerequisite

I have a makefile, which I am using to cross-compile for and embeded ARM platform with gcc. Specifcally, I am using arm-none-eabi-gcc, but the same appiles to avr-gcc, msp430-gcc, etc. Typically when using make+gcc (and not cross compiling) I list libs as prerequisite as follows:
programA.elf: programA.o foo.o -lm ...etc
programB.elf: programB.o bar.o -lftdi ...etc
%.elf:
gcc $(LDFLAGS) -o $# $^
Make handles this "-lsyntax" very nicely, and its very convienient if you are building multiple progams/targets and want to have a generic rule for linking. The problem I have run into durring cross-compiling is that arm-none-eabi-gcc obviously has a different libm.a than my system's gcc libm.so (for example), but Make doesn't know whats going on here and keeps trying to use the x86 libm instead of the ARM base one. I can get things to work by adding the line:
.LIBPATTERNS = /usr/lib/arm-none-eabi/newlib/lib%.a
but it seems kinda clunky and exposes anyone wanting to compile the project to knowing a little more about the toolchain's install locations than is normally expected.
My question is: "Is there a better convention to list a binary's lib dependencies I should be using here that wont break when cross-compiling?"
This can be done. But a general solution is complex. I have Makefiles which build arm, x86, and c67 executables from a single set of sources. The page you reference eludes to the key: VPATH. I suggest a separate subdirectory for each architecture. The following is not working code, but it gives the idea
all: arm/pgma x86/pgma
vpath %.c $(CURDIR)
arm x86:
mkdir -p $#
arm/pgma: arm/main.o arm/sub.o | arm
x86/pgma: x86/main.o x86/sub.o more.o | x86
arm/%: CC=arm-none-eabi-gcc
arm/%: CFLAGS += -march=armv7-a -mtune=corex-a8
x86/%: CC=gcc
arm/%: VPATH = /usr/lib/arm-none-eabi/newlib
# Notice, VPATH not needed for x86 since it is the native host
This entire concept can be extend to build dependency file is each subdirectory as well debug and release variants. I have not tried this with the -lfoo, but it should work. E.g.,
arm/pgma: arm/main.o arm/sub.o -lmylib | arm

Cross-Compiling for an embedded ARM-based Linux system

I try to compile some C code for an embedded (custom) ARM-based Linux system. I set up an Ubuntu VM with a cross-compiler named arm-linux-gnueabi-gcc-4.4 because it looked like what I needed. Now when I compile my code with this gcc, it produces a binary like this:
$ file test1
test1: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked
(uses shared libs), for GNU/Linux 2.6.31,
BuildID[sha1]=0x51b8d560584735be87adbfb60008d33b11fe5f07, not stripped
When I try to run this binary on the embedded Linux, I get
$ ./test1
-sh: ./test1: not found
Permissions are sufficient. I can only imagine that something's wrong with the binary format, so I looked at some working binary as reference:
$ file referenceBinary
referenceBinary: ELF 32-bit LSB executable, ARM, version 1, dynamically linked
(uses shared libs), stripped
I see that there are some differences, but I do not have the knowledge to derive what exactly I need to fix and how I can fix that. Can someone explain which difference is critical?
Another thing I looked at are the dependencies:
$ ldd test1
libc.so.6 => not found (0x00000000)
/lib/ld-linux.so.3 => /lib/ld-linux.so.3 (0x00000000)
(Interestingly, this works on the target system although it cannot execute the binary.) The embedded system only has a libc.so.0 available. I guess I need to tell the compiler the libc version I want to link against, but as I understand it, gcc just links against the version it comes with, is this correct? What can I do about it?
Edit: Here's the Makefile I use:
CC=/usr/bin/arm-linux-gnueabi-gcc-4.4
STRIP=/usr/bin/arm-linux-gnueabi-strip
CFLAGS=-I/usr/arm-linux-gnueabi/include
LDFLAGS=-nostdlib
LDLIBS=../libc.so.0
SRCS=test1.c
OBJS=$(subst .c,.o,$(SRCS))
all: test1
test1: $(OBJS)
$(CC) $(LDFLAGS) -o main $(OBJS) $(LDLIBS)
$(STRIP) main
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^>>./.depend;
clean:
rm -f $(OBJS)
include .depend
What you should probably do is to install libc6 on the embedded system. Read this thread about a similar problem. The solution in post #5 was to install:
libc6_2.3.6.ds1-13etch9_arm.deb
linux-kernel-headers_2.6.18-7_arm.deb
libc6-dev_2.3.6.ds1-13etch9_arm.deb
Your other option is to get the libc from the embedded system onto your VM and then pass it to the gcc linker and use the -static option.
This solution was also mentioned in the above thread. Read more about static linking here.
Other things to try:
In this thread they suggest removing the -mabi=apcs-gnu flag from your makefile if you're using one.
This article suggests feedint gcc the -nostdlib flag if you're compiling from the command line.
Or you could switch to using the arm-none-eabi-gcc compiler. References on this can be found here and here.

GCC is not linking library to a non-default path

I have boost C++ libraries already installed on my Fedora10 machine but I want to use a newer version that I keep at some location in my home folder. I want g++ to use include and library files from my home folder location instead of default (/usr/include and /usr/lib64).
For that matter, I also have declared CPLUS\_INCLUDE\_PATH and LIBRARY\_PATH environment variables in my ~/.bashrc file as explained here.
Now when I run,
g++ -o hello.so -fPIC hello.cpp -shared -lboost_python
The preprocessor uses include files from my home folder location, overriding the default location (as it should, because CPLUS\_INCLUDE\_PATH has a higher precedence in the search path). But the linker does not seem to follow the same precedence rule. It always uses libboost_python.so from the default location /usr/lib64 instead of first searching LIBRARY\_PATH. It only links to the libboost\_python.so library in my home folder when I explicitly specify with -L switch. This is really inconvenient.
The -L switch is the standard way of telling the compiler where to find the libraries. Write a makefile that builds your compiler/linker switches - you'll find it's worth investing your time. You can do something like:
MY_LIBPATH += -L$(BOOST_LIB_PATH)
MY_INCPATH += -I$(BOOST_INC_PATH)
hello.so: hello.cpp
g++ -o $# -fPIC $(MY_INCPATH) $(MY_LIBPATH) hello.cpp -shared -lboost_python
And then you can control this via environment (of course there could be many variations on how to structure the makefile.)

Resources