How do I link with gcc on MinWG - gcc

Is this syntax incorrect?
C:\Users\Brett\Compilers>gcc -I MinGW\include -l MinGW\lib\libgdi32.a -o hello
world helloworld.c
The directory's are all fine, I mist be including and linking in the wrong order or something?
Here is the output:
c:/users/Brett/compilers/mingw/bin/../lib/gcc/mingw32/4.6.2/../../../../mingw
2/bin/ld.exe: cannot find -lMinGW\lib\libgdi32.a
collect2: ld returned 1 exit status

The syntax for -l switch is the library name without lib prefix and without the extension. If it cannot be found, it's directory should be given with -L option. So I would write:
gcc -I MinGW\include -L MinGW\lib -lgdi32 -o helloworld helloworld.c
Maybe -L is not needed, maybe you also need -mwindows to tell the linker you want windows app. To specify a library file explicitly, give it without any letter option, like this:
gcc -I MinGW\include MinGW\lib\libgdi32.a -o helloworld helloworld.c
Here is the gcc reference: linking options.

Related

What does -L ${SOME_LIB} means in a Makefile?

Here I am compiling a C code with the following Makefile.
MAIN:
g++ -c -o td.o -I/home/user/dp/pro/include td.c
g++ -c -o disk.o -I/home/user/dp/pro/include disk.c
g++ -o disk disk.o tds2.o -L ${DP_LIB} -L ${LIPN_LIB} -lgnb -lgtd -lnbl -lpin
./disk.exe RUN.dat
What is the purpose of -L ${DP_LIB} here? Precisely, I wish to know the function of ${}.
If it is linking a library, how is it different from -llib?
This makefile is by far very crude (I have seen bigger and better ones). I am new to makefiles, but atleast this one works.
The -L options is telling the linker to add a path to the list it uses to search for libraries. The ${DP_LIB} thing is how variables are used in makefiles. Presumably DP_LIB is a path to somewhere.
All this should be very clear if you just read the documentation and the actual makefile.
With -Ldir you specify a directory where the linker searches for libs. The lib files themselves are specified with the -llib argument.
Example:
-L/usr/X11R6/lib -lX11
means that the linker will look for libX11.so in /usr/X11R6/lib
(...and in other default places.)

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

cannot link boost regex into mingw

my mingw compiler: http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev6.7z
boost: http://sourceforge.net/projects/boost/files/boost/1.52.0/boost_1_52_0.7z
(both on D: drive)
code:
#include <boost\regex.hpp>
int main() {
boost::regex reg("[a-z]+");
}
command line:
SET PATH=%PATH%;D:\mingw\bin;D:\mingw\include
g++ -I "d:\mingw\include" -I "d:\boost" -Os -s -o test.exe test.cpp -std=c++11 -static -L "D:\boost\stage\lib" -lboost_regex
In the d:\boost\stage\lib directory there is libboost_regex-mgw47-mt-1_52.a.
And the process returns :
d:/mingw/bin/../lib/gcc/i686-w64-mingw32/4.7.2/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lboost_regex
collect2.exe: error: ld returned 1 exit status
If I put the exact name of the *.a file the result is cannot find -llibboost_regex-mgw47-mt-1_52.a
even whole path that is -ld:\boost\stage\lib\libboost_regex-mgw47-mt-1_52.a doesn't work. Whatever I put after the -l has the same effect.
As you can see here you must use either (-l followed by the named of the library removing the lib preffix and the extension .a):
g++ -I "d:\mingw\include" -I "d:\boost" -Os -s -o test.exe test.cpp -std=c++11 -static -L "D:\boost\stage\lib" -lboost_regex-mgw47-mt-1_52
or (full path of the library without using -l):
g++ -I "d:\mingw\include" -I "d:\boost" -Os -s -o test.exe test.cpp -std=c++11 -static D:/boost/stage/lib/libboost_regex-mgw47-mt-1_52.a
PS:One thing I personally do is build boost using --layout=tagged. This makes the name of the libraries a lot more manageable (in this case libboost_regex-mt.a).

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.

How can I tell, with something like objdump, if an object file has been built with -fPIC?

How can I tell, with something like objdump, if an object file has been built with -fPIC?
The answer depends on the platform. On most platforms, if output from
readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)'
is empty, then either foo.o was not compiled with -fPIC, or foo.o doesn't contain any code where -fPIC matters.
I just had to do this on a PowerPC target to find which shared object (.so) was being built without -fPIC. What I did was run readelf -d libMyLib1.so and look for TEXTREL. If you see TEXTREL, one or more source files that make up your .so were not built with -fPIC. You can substitute readelf with elfdump if necessary.
E.g.,
[user#host lib]$ readelf -d libMyLib1.so | grep TEXT # Bad, not -fPIC
0x00000016 (TEXTREL)
[user#host lib]$ readelf -d libMyLib2.so | grep TEXT # Good, -fPIC
[user#host lib]$
And to help people searching for solutions, the error I was getting when I ran my executable was this:
root#target:/# ./program: error while loading shared libraries: /usr/lib/libMyLi
b1.so: R_PPC_REL24 relocation at 0x0fc5987c for symbol 'memcpy' out of range
I don't know whether this info applies to all architectures.
Source: blogs.oracle.com/rie
I assume, what you really want to know is whether or not a shared library is composed from object files compiled with -fPIC.
As already mentioned, if there are TEXTRELs, then -fPIC was not used.
There is a great tool called scanelf which can show you the symbols that caused .text relocations.
More information can be found at HOWTO Locate and Fix .text Relocations TEXTRELs.
-fPIC means that code will be able to execute in addresses different form the address that was compile for.
To do it , disasambler will look like this....
call get_offset_from_compilation_address
get_offset_from_compilation_address: pop ax
sub ax, ax , &get_offset_from_compilation_address
now in ax we have an offset that we need to add to any access to memory.
load bx, [ax + var_address}
readelf -a *.so | grep Flags
Flags: 0x50001007, noreorder, pic, cpic, o32, mips32
This should work most of the time.
Another option to distinguish whether your program is generated wit -fPIC option:
provided that your code has -g3 -gdwarf-2 option enabled when compiling.
other gcc debug format may also contains the macro info:
Note the following $'..' syntax is assumes bash
echo $' main() { printf("%d\\n", \n#ifdef __PIC__\n__PIC__\n#else\n0\n#endif\n); }' | gcc -fPIC -g3
-gdwarf-2 -o test -x c -
readelf --debug-dump=macro ./test | grep __PIC__
such a method works because gcc manual declares that if -fpic is used, PIC is defined to 1, and
if -fPIC used, PIC is 2.
The above answers by checking the GOT is the better way. Because the prerequest of -g3 -gdwarf-2 I guess seldom being used.
From The Linux Programming Interface:
On Linux/x86-32, it is possible to create a shared library using
modules compiled without the –fPIC option. However, doing so loses
some of the benefits of shared libraries, since pages of program text
containing position-dependent memory references are not shared across
processes. On some architectures, it is impossible to build shared
libraries without the –fPIC option.
In order to determine whether an existing object file has been
compiled with the –fPIC option, we can check for the presence of the
name _GLOBAL_OFFSET_TABLE_ in the object file’s symbol table, using
either of the following commands:
$ nm mod1.o | grep _GLOBAL_OFFSET_TABLE_
$ readelf -s mod1.o | grep _GLOBAL_OFFSET_TABLE_
Conversely, if either of the following equivalent commands yields any
output, then the specified shared library includes at least one object
module that was not compiled with –fPIC:
$ objdump --all-headers libfoo.so | grep TEXTREL
$ readelf -d libfoo.so | grep TEXTREL
However, neither above quoting nor any answer of this question works for x86_64.
What I've observed on my x86_64 Ubuntu machine is that, whether specifying -fPIC or not, it would generate fPIC .o. That is
gcc -g -Wall -c -o my_so.o my_so.c // has _GLOBAL_OFFSET_TABLE_
gcc -g -Wall -fPIC -c -o my_so_fpic.o my_so.c // has _GLOBAL_OFFSET_TABLE_
readelf -s my_so.o > 1.txt && readelf -s my_so_fpic > 2.txt && diff 1.txt 2.txt
has no difference and both my_so.o and my_so_fpic.o can be used to create a shared library.
In order to generate non fpic object file, I found a gcc flag called -fno-pic in the first comment of How to test whether a Linux binary was compiled as position independent code? .
This works,
gcc -g —Wall -fno-pic -c -o my_so_fnopic.o my_so.c // no _GLOBAL_OFFSET_TABLE_
and
gcc -g -Wall -shared -o libdemo.so my_so_fnopic.o
gives error:
/usr/bin/ld: my_so_fnopic.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
collect2: error: ld returned 1 exit status
can not create a shared library with non pic .o.

Resources