How to use rpath with LLD linker (LLVM) - g++

I recently managed to use the lld linker in a big cmake project. (LLVM 11, from this package)
I do not use clang, I use G++ with LLD.
But I encounter the following issue: lld: error: unknown argument: -rpath
Following the clang documentation, -rpath should work, at least with clang I guess ?
Here is the g++ command generated by cmake:
g++.exe [...] -fuse-ld=lld [...] -Wl,-rpath='$ORIGIN' [...]
I manually tried a lot of combinations:
-Wl,-rpath='$ORIGIN'
-Wl,-rpath,'$ORIGIN'
-Wl,-rpath '$ORIGIN'
... etc, nothing work.
Of what I understand, lld should behave exactly like ld ?, so -Wl,-rpath='$ORIGIN' should work ?
Did I miss something ?

Related

Categories in static lib not regocnized at runtime

I am building an executable ("tool") on Linux. Using include $(GNUSTEP_MAKEFILES)/tool.make.
It's linked to a static lib that has also be build with GNUstep. The lib
contains Categories.
The executable builds fine but has errors at runtime not recognizing
methods defined in the static lib's Category:
Uncaught exception NSInvalidArgumentException, reason:
ClassNameOfClassTheCategoryExtends(instance) does not recognize
nameOfMethodInCategory
I am trying to fix that by passing -ObjC to the linker flags (also
tried -all_load) in the executable's GNUmakefile:
ADDITIONAL_LDFLAGS = -ObjC -all_load
But that seems to be ignored by clang. Here is the relevant output of
make install messages=yes debug=yes
clang: warning: argument unused during compilation: '-ObjC'
[-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-all_load'
[-Wunused-command-line-argument]
It looks like ADDITIONAL_LDFLAGS are used compiling, not linking.
Using this leads to the same result:
LDFLAGS := $(LDFLAGS) -ObjC
The excecutables GNUmakefileincludes the following:
include $(GNUSTEP_MAKEFILES)/common.make
# My make
include $(GNUSTEP_MAKEFILES)/tool.make
The resulting command line output is:
$ make install messages=yes debug=yes
This is gnustep-make 2.9.0. Type 'gmake print-gnustep-make-help' for help.
Running in gnustep-make version 2 strict mode.
Making all for tool NameOfExcecutable...
clang -ObjC -fuse-ld=/usr/bin/ld.gold -pthread -fexceptions -rdynamic -fobjc-runtime=gnustep-2.0 -fblocks -o obj/NameOfExcecutable \
./obj/NameOfExcecutable.obj/main.m.o ./obj/NameOfExcecutable.obj/MyClass.m.o ./obj/NameOfExcecutable.obj/StreamRunLoop.m.o ./obj/NameOfExcecutable.obj/Connector.m.o ./obj/NameOfExcecutable.obj/HTTPClient.m.o \
-L/home/user/GNUstep/Library/Libraries -L/usr/GNUstep/Local/Library/Libraries -L/usr/GNUstep/System/Library/Libraries -lgnustep-base -ldispatch -l/path/to/libOwnLib1.a -l/path/to/libOwnLib2.a -l/path/to/libOwnHavingTheCategories.a -l/path/to/libOwnLib4.a -l/path/to/libOwnLib5.a -luuid -lz -lpthread -ldl -lpthread -lobjc -lm
clang: warning: argument unused during compilation: '-ObjC' [-Wunused-command-line-argument]
Question:
What am I doing wrong
or
How can I work around the issue?
After digging into the issue of the linker not knowing the -ObjC flag (which we are used to use in Xcode) it looks like:
only ld.ld64 is aware of this flag
ld.ld64 is a (too genericly named) "linker for macOS" (from LLDB.org)
thus is not available for Linux linkers
To workaround we first stopped using GNUstep makefiles to
disable all GNUstep magic understand what is going on and wrote our own makefiles.
The actual fix to force link/load all .o files was to explicitly pass --whole-archive to the linker:
-Wl,-whole-archive path/to/static/lib/containing/categories/libOwnLib1.a -Wl,-no-whole-archive

Emitting a single IR bitcode File with LLVM LLD using CMake

I'm using Ubuntu 16.04 x86_64 and LLVM 5.0 and would like to compile a project to a single LLVM IR bitcode file using CMake. I know there is a way to do this using the GOLD Linker with the LLVM Plugin and add the CMake linker flags "-fuse-ld=gold -Wl,-plugin-opt=emit-llvm" and the CXX flag "-flto".
But when I try to compile the project with the LLVM LLD linker and the "-fuse-ld=lld -Wl,-plugin-opt=emit-llvm" respectively "-flto" Flag, the linker is generating a native executable and no LLVM IR file. I was searching for other LLD options to emit a LLVM IR file but found nothing.
Is there a way (or option) to generate a single LLVM IR file using LLD?
You can use the -save-temps option.
clang -flto -fuse-ld=lld -Wl,-save-temps a.o b.o -o myprogram
This will generate myprogramXYZ.precodegen.bc among other files. You can then use llvm-dis to get it in readable IR format.

Lapack undefined reference

I am new to g++ and lapack, and attempting to use them. I encountered a problem when I tried to compile the following naive code
#include <lapackpp.h>
int main()
{
LaGenMatDouble A;
return 0;
}
If I run the command
$g++ -L/usr/local/lib -llapackpp test2.cpp
where test2.cpp is the name of the cpp file, the terminal would give an error:
test2.cpp:1:22: fatal error: lapackpp.h: No such file or directory
But if I run the command:
$g++ -I/usr/local/include/lapackpp -L/usr/local/lib -llapackpp test2.cpp
the terminal would give an error:
/tmp/ccUi11DG.o: In function `main':
test2.cpp:(.text+0x12): undefined reference to `LaGenMatDouble::LaGenMatDouble()'
test2.cpp:(.text+0x23): undefined reference to `LaGenMatDouble::~LaGenMatDouble()'
collect2: ld returned 1 exit status
BTW, if I run the command
$pkg-config lapackpp --libs
the result is
-L/usr/local/lib -llapackpp
Could you please help me solve this? Thanks in advance!
Lapack requires fortran libraries, so that's where the -lgfortran comes from. Moreover, it appears the exact way to provide that library for the compiler depends on the Linux distriburion. From the documentation:
Requirements
This package requires the packages "blas", "lapack" (without the "++"), and a Fortran compiler. On most Linuxes these are available as pre-compiled binaries under the name "blas" and "lapack". For SuSE 10.x, the Fortran compiler is available as package "gfortran". For SuSE 9.x, the Fortran compiler is available as package "gcc-g77".
Not sure why pkg-config lapackpp --libs does not list -lgfortran
The -I/usr/local/include/lapackpp specifes the lapackpp-related header files. Without it the compiler cannot find lapackpp.h when you try to include it (#include <lapackpp.h>) -- see the compiler error in your question
I finally solved the problem but would still wonder why it has to be so.
The only command that can link cpp file to lapackpp library is:
g++ foo.cpp -o foo -lgfortran -llapackpp -I/usr/local/include/lapackpp
It would not work without -lgfortran, or with -I/usr/local/include/lapackpp replaced by -L/usr/local/lib.
Does anyone have an answer?

Problems when compiling Objective C with Clang (Ubuntu)

I'm learning Objective-C language. Since I don't have a Mac, I'm compiling and running my code within Ubuntu 11.04 platform.
Until now, I was using gcc to compile. I've installed GNUStep and all was working. But then I started to try some Objective-C 2.0 features, like #property and #synthesize, that gcc does not allow.
So I tried to compile the code with Clang, but it seems that it is not correctly linking my code with the GNUStep libraries, not even with a simple Hello world program.
For example, if I compile the following code:
#import <Foundation/Foundation.h>
int main(void) {
NSLog(#"Hello world!");
return 0;
}
The output of the compiler is:
/tmp/cc-dHZIp1.o: In function `main':
test.m:(.text+0x1f): undefined reference to `NSLog'
/tmp/cc-dHZIp1.o: In function `.objc_load_function':
test.m:(.text+0x3c): undefined reference to `__objc_exec_class'
collect2: ld returned 1 exit status
clang: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)
The command I'm using to compile is
clang -I /usr/include/GNUstep/ test.m -o test
with the -I directive to include the GNUStep libraries (otherwise, Clang is not able to find Foundation.h).
I've googled my problem, and visited both GNUStep and Clang web pages, but I haven't found a solution to it. So any help will be appreciated.
Thanks!
The problem was that the library gnustep-base was not being used by the linker. So the solution to this was using the option -Xlinker, that sends arguments to the linker used by clang:
clang -I /usr/include/GNUstep/ -Xlinker -lgnustep-base test.m -o test
The statement "-X linker -lgnustep-base" made the magic. However, I had problems with this command related to the class that represents a string in Objective-C:
./test: Uncaught exception NSInvalidArgumentException, reason: GSFFIInvocation:
Class 'NXConstantString'(instance) does not respond to forwardInvocation: for
'hasSuffix:'
I could solve it adding the argument "-fconstant-string-class=NSConstantString":
clang -I /usr/include/GNUstep/ -fconstant-string-class=NSConstantString \
-Xlinker -lgnustep-base test.m -o test
In addition, I've tried with some Objective-C 2.0 pieces of code and it seems to work.
Thank you for the help!
You can try gcc compiler:
First of all install GNU Objective-C Runtime: sudo apt-get install gobjc
then compile: gcc -o hello hello.m -Wall -lobjc
You are not able to use ObjC 2.0 features because you're missing a ObjC-runtime supporting those. GCC's runtime is old and outdated, it doesn't support ObjC 2.0. Clang/LLVM doesn't have a acompanied runtime, you need to install the ObjC2-runtime from GNUstep (which can be found here: https://github.com/gnustep/libobjc2 ) and reinstall GNUstep using this runtime.
Here are some bash scripts for different Ubuntu versions, that do everything for you:
http://wiki.gnustep.org/index.php/GNUstep_under_Ubuntu_Linux
And please don't try to reinvent GNUstep make, instead, use it:
http://www.gnustep.org/resources/documentation/Developer/Make/Manual/gnustep-make_1.html
If you really don't think so, here is some excerpt from there:
1.2 Structure of a Makefile
Here is an example makefile (named GNUmakefile to emphasis the fact that it relies on special features of the GNU make program).
#
# An example GNUmakefile
#
# Include the common variables defined by the Makefile Package
include $(GNUSTEP_MAKEFILES)/common.make
# Build a simple Objective-C program
TOOL_NAME = simple
# The Objective-C files to compile
simple_OBJC_FILES = simple.m
-include GNUmakefile.preamble
# Include in the rules for making GNUstep command-line programs
include $(GNUSTEP_MAKEFILES)/tool.make
-include GNUmakefile.postamble
This is all that is necessary to define the project.
In your case replace all occurrences of simple with test and you're done
1.3 Running Make
Normally to compile a package which uses the Makefile Package it is purely a matter of typing make from the top-level directory of the package, and the package is compiled without any additional interaction.

LD: linking with STL libraries

I was trying to compile a OpenCV's VideoCapture example. When I compile it, I get the following output:
gpp test.c
Info: resolving vtable for cv::VideoCapture by linking to __imp___ZTVN2cv12VideoCaptureE (auto-import)
c:/programs/mingw/bin/../lib/gcc/mingw32/4.5.0/../../../../mingw32/bin/ld.exe: warning: auto-importing has
enable-auto-import specified on the command line.
This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.
(Btw, gpp is an alias to g++ -lhighgui -lcv -lcxcore)
So, I tried to compile with "gpp --enable-auto-import", but g++ didn't recognize this option. So, I tried to compile like this:
gpp -c test.c
ld test.o
And I've got the same error AND many other errors about STL functions, indicating it didn't link with STL:
undefined reference to std::cout
...
And, finally, when I compiled like this:
gpp -c test.c
ld --enable-auto-import test.o
This time, I've only got the STL errors. The VideoCapture error is gone! So I guess I solved this problem. The only thing is: how do I make ld link my program with STL libraries??????
Thanks in advance
The correct solution is build with
g++ test.c -lhighgui -lcv -lcxcore -Wl,--enable-auto-import
Unlike your 'gpp' alias, this puts libraries after objects which reference them (important when linking with archive libraries), and also properly passes --enable-auto-import flag to the linker.
Your current "fix" only works "by accident".