How do I resolve OSX rpath-referenced library? - macos

I want to link a DLL using a couple of other DLLs but am having trouble getting them to properly resolve:
$ g++ -o libsuba.dylib -dynamiclib -Wl,-install_name,#rpath/libsuba.dylib suba.cpp
$ g++ -o liba.dylib -dynamiclib -Wl,-install_name,#rpath/liba.dylib -Wl,-reexport_library,libsuba.dylib a.cpp
The above gives me the two libraries, liba.dylib and libsuba.dylib.
$ otool -l liba.dylib
...
Load command 10
cmd LC_REEXPORT_DYLIB
cmdsize 48
name #rpath/libsuba.dylib (offset 24)
time stamp 2 Wed Dec 31 18:00:02 1969
current version 0.0.0
compatibility version 0.0.0
...
In another directory, I want to now link against liba.dylib:
$ cd build
$ c++ -o b b.cpp ../liba.dylib -Wl,-rpath,..
ld: file not found: #rpath/libsuba.dylib for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
However, this works:
$ c++ -o b b.cpp ../liba.dylib -L..
Can someone explain why the explicit linker rpath option doesn't replace the #rpath macro and allow the reexported library to be located?

Related

Why can't I rename a shared library after it's been built?

Here's a simple example:
lib.c:
#include <stdio.h>
void hello_world(void) {
puts("Hello, world!");
}
program.c:
void hello_world(void);
int main() {
hello_world();
return 0;
}
If I compile the library normally and link it, everything works fine:
$ cc lib.c -fPIC -shared -o libmylib.dylib
$ cc program.c -L. -lmylib
$ ./a.out
Hello, world!
But if I rename the library after building it (but before building the program), it doesn't work:
$ cc lib.c -fPIC -shared -o totally_different_name.dylib
$ mv totally_different_name.dylib libmylib.dylib
$ cc program.c -L. -lmylib
$ ./a.out
dyld: Library not loaded: totally_different_name.dylib
Referenced from: /private/tmp/./a.out
Reason: image not found
[1] 13229 abort ./a.out
Why is this the case? Why is dyld looking for the original library name?
This works okay on Linux, but when I try on macOS it completely fails (I don't know if it's a macOS vs Linux thing, or a clang vs gcc thing, since I'm using clang on macOS and gcc on Linux).
If it's relevant, cc --version is Apple LLVM version 8.0.0 (clang-800.0.42.1) x86_64-apple-darwin16.4.0.
Thanks to Florian Zwoch's comment, I was able to find a way to fix this. Run this command after renaming the dylib:
install_name_tool -id libmylib.dylib libmylib.dylib
That command changes the internal ID of the dylib. The command syntax is install_name_tool -id <new-id> <dylib-path>.
Originally, the dylib has the ID of totally_different_name.dylib. Renaming the file doesn't change the ID it has stored internally, and that has to be updated separately with install_name_tool.

Breaking NASM files into multiple with link errors on OS X

My base assembler file foidlrt.asm started getting a bit too large so I broke it up into two. Here is the entirety of the second file folder_stdio.asm:
; foidl_stdio.asm
%include "foidlstnd.inc"
section .text
DEFAULT REL
global foidl_fclose ; Raw file close
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; foidl_close
; Raw file close
; REGISTERS (1):
; RDI file handle
; CALLS:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
foidl_fclose:
mov rax,SYSCALL_FILE_CLOSE ; 0x2000006
syscall
ret
However, now when I build I am now getting this error from make despite the global declaration in the new file:
nasm src/foidlrt.asm -f macho64 --prefix _ -g -O0 -Iincludes/ -o asmobjs/foildrt.o
nasm src/foidlrt.asm -f macho64 --prefix _ -g -O0 -Iincludes/ -o asmobjs/foidl_stdio.o
libtool -static -s -o libs/libfoidlrt.a asmobjs/foildrt.o asmobjs/foidl_stdio.o
gcc src/testlink.c -L libs -l foidlrt -Wall -g -L. -Wl,-pie -I. -o bin/testlink
Undefined symbols for architecture x86_64:
"_foidl_fclose", referenced from:
_main in testlink-4b5ad3.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Version information:
XCode - 7.2.1 (7C1002)
nasm - NASM version 2.12 compiled on Feb 28 2016
gcc - Apple LLVM version 7.0.2 (clang-700.1.81)
RESOLVED
Error was all mine, makefile rule was bad. Working as expected now.

error 127 while executing makefile.linux

I wanted to take backup of my MQ objects.
The version of MQ is v6.0.1.0.
OS version is Linux ip-10-0-0-136 2.6.32.19-0.3-ec2 #1 SMP 2010-09-17 20:28:21 +0200 x86_64 x86_64 x86_64 GNU/Linux
I downloaded MS03 and extracted the files as I wanted to run the command saveqmgr.
When I want to compile makefile.linux I get the following error :
/tmp> make -f makefile.linux
gcc -c -DUNIX -Wall -o saveqmgr.o -I. -I/opt/mqm/inc saveqmgr.c
make: gcc: Command not found
make: *** [saveqmgr.o] Error 127
How do I check what is Error 127? where do I check for errors ?
The linker option set in makefile.linux is
LCOPTS = -m64 -o $# -L$(MQMLIB) -L. $(LIBS)
LCOPTC = -m64 -o $# -L$(MQMLIB) -L. $(LIBC)
# MQM library directory
MQMLIB = /opt/mqm/lib64
Is there anything else I am missing ?
See this table of exit codes with special meaning. Error 127 corresponds to the preceding gcc: Command not found. You apparently don't have gcc installed on your system, or you don't have it in your PATH environment variable.

Linking to libusb

I know this is something so simple I'm going to hate myself for having to ask it, but my head is aching from repeated hits on the desktop. I've read dozens of stackoverflow and google results which suggest that the following should work:
$ ls /usr/local/lib/libusb*
/usr/local/lib/libusb-1.0.a /usr/local/lib/libusb-1.0.so /usr/local/lib/libusb-1.0.so.0.1.0
/usr/local/lib/libusb-1.0.la /usr/local/lib/libusb-1.0.so.0
$ gcc -I ~/libusb-1.0.18/libusb -c test.c
$ gcc -L/usr/local/lib -o test test.o -llibusb
/usr/bin/ld: cannot find -llibusb
collect2: error: ld returned 1 exit status
$ gcc -L/usr/local/lib -o test test.o -llibusb-1.0
/usr/bin/ld: cannot find -llibusb-1.0
collect2: error: ld returned 1 exit status
Why is that not correct? One of those should have worked and I've tried many, many more variations.
For completeness I'm running Ubuntu 14.04 (fresh VM installation).
I built libusb from source (~/libusb-1.0.18) with:
./configure --disable-udev
make
sudo make install
The leading lib and trailing .so are automatically filled in by the linker, so you should not specify either on the command line. Your command should be:
gcc -L/usr/local/lib -o test test.o -lusb-1.0

Why doesn't my lib search path work with gcc and MinGW

I am trying to compile a sample using gcc under MinGW in windows 7
Why does this work:
$ gcc -m32 -o cube.exe cube.o shader.o matrix.o window.o
/c/dev/mixed/SDKs/Extracted/OpenGLESEmulatorv1.3.0/examples/OpenGLES_20/cube/libEGL.lib
But this doesn't:
$ gcc -m32 -o cube.exe cube.o shader.o matrix.o window.o
-L/c/dev/mixed/SDKs/Extracted/OpenGLESEmulatorv1.3.0/examples/OpenGLES_20/cube
-llibEGL.lib
It fails with:
c:/mingw/bin/../lib/gcc/mingw32/4.7.0/../../../../mingw32/bin/ld.exe: cannot find -llibEGL.lib
collect2.exe: error: ld returned 1 exit status
Shouldn't the -L add the correct search path?
Per the MinGW documentation the -l argument adds lib to the front and .a to the end OR just adds .lib to the end. Removing the .lib from the end allows this to compile.

Resources