I need to include some platform specific jni files in the following dir:
$ ls -l /home/ubuntu/jdk8/include/linux
total 8
-rw-r--r-- 1 ubuntu ubuntu 995 Mar 15 09:00 jawt_md.h
-rw-r--r-- 1 ubuntu ubuntu 824 Mar 15 09:00 jni_md.h
So the gcc command was appropriately (?) augmented:
gcc -I"/home/ubuntu/jdk8/include/linux" -I"$JAVA_HOME/include" ..
But the files inside the linux subdir are not found:
gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4)
COLLECT_GCC_OPTIONS='-I' '"/home/ubuntu/jdk8/include/linux"' '-I' '/home/ubuntu/jdk8/include' ..
/home/ubuntu/jdk8/include/jni.h:45:20: fatal error: jni_md.h: No such file or directory
So what needs to be tweaked here? If it matters this is on ubuntu16.0.4` and
gcc --version
gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Update Here is the inclusion statement in jni.h
#include "jni_md.h"
Now how can they expect that to be found - should it not be
#include <jni_md.h>
Update on the update Per Arkadiusz Drabczyk and a link he provided http://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html they should both be OK. In fact the behavior appears to be the same.
Note if I copy the files under include/linux/*.h to the parent include dir the compilation work: so the only problem is the include path.
YAU (Yet another update) Per Arkadiusz I tried out clang: same error.
It's possible, but unlikely, that it needs a trailing slash on the directory string. Is jni.h including <jni_md.h> or "jni_md.h" ??
Turns out the order of the options was messing up: I had
-I<something> -odmaserver.so -I<something else>
It needs to be
-I<something> -I<something else> -odmaserver.so
Related
I have the following code(file.c):
int main() {}
I go gcc file.c, and the output file file.exe is 26.5KB
I also tried with -O2, -Ofast, -Os but the size stays the same. I have included no headers, nothing; I even tried putting int main(void) {}.
Shouldn't the output file be roughly 1KB? [I am using Windows 10 - GCC 4.8.1]
Context:
I am trying to understand how PE files work in windows, and so far, I think I have a great grasp of the concept, so I wanted to run some tests because I want to be able to take code from another file, lets say file2.exe, and try to sneak it inside file.exe with OllyDBG. But since this pretty much NULL code yields a freaking 26.5KB, I really dont know what to do...
there are a LOT of items that get added to a file to make it executable.
In the following example, on Linux 16.04
gcc version: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
I wrote the following source in a
file named untitled2.c
int main(void)
{
}
Then compiled it into untitled2.o
gcc -ggdb -Wall -Wextra -Wconversion -std=gnu11 -pedantic -Wmissing-prototypes -c untitled2.c -o untitled2.o -I.
then linked it into untitleed2
gcc -ggdb -std=gnu11 -o untitled2 untitled2.o
Here are the results.
-rw-r--r-- 1 rkwill root 22 Mar 21 20:41 untitled2.c
-rw-rw-r-- 1 rkwill rkwill 2608 Mar 21 20:41 untitled2.o
-rwxrwxr-x 1 rkwill rkwill 16904 Mar 21 20:41 untitled2
I.E. the original source file is 22 bytes. The compiled file is 2608 bytes (no optimization parameters) the executable file is 16904 bytes
striping the file (removing the debug info) would reduce the file size slightly, but not enough to eliminate the significant difference in size.
I am trying to make use of a library, https://github.com/go-steem/rpc, that makes use of some C code, which references a library.
The C library can be found here, https://github.com/bitcoin-core/secp256k1
I followed the steps to get that installed
$ ./autogen.sh
$ ./configure
$ make
$ ./tests
$ sudo make install # optional
And have this output;
$ sudo make install
Password:
CC src/libsecp256k1_la-secp256k1.lo
CCLD libsecp256k1.la
CC src/tests-tests.o
CCLD tests
CC src/exhaustive_tests-tests_exhaustive.o
CCLD exhaustive_tests
build-aux/install-sh -c -d '/usr/local/lib'
/bin/sh ./libtool --mode=install /usr/bin/install -c libsecp256k1.la '/usr/local/lib'
libtool: install: /usr/bin/install -c .libs/libsecp256k1.0.dylib /usr/local/lib/libsecp256k1.0.dylib
libtool: install: (cd /usr/local/lib && { ln -s -f libsecp256k1.0.dylib libsecp256k1.dylib || { rm -f libsecp256k1.dylib && ln -s libsecp256k1.0.dylib libsecp256k1.dylib; }; })
libtool: install: /usr/bin/install -c .libs/libsecp256k1.lai /usr/local/lib/libsecp256k1.la
libtool: install: /usr/bin/install -c .libs/libsecp256k1.a /usr/local/lib/libsecp256k1.a
libtool: install: chmod 644 /usr/local/lib/libsecp256k1.a
libtool: install: /usr/bin/ranlib /usr/local/lib/libsecp256k1.a
build-aux/install-sh -c -d '/usr/local/include'
/usr/bin/install -c -m 644 include/secp256k1.h '/usr/local/include'
build-aux/install-sh -c -d '/usr/local/lib/pkgconfig'
/usr/bin/install -c -m 644 libsecp256k1.pc '/usr/local/lib/pkgconfig'
I try to run the upvote example from that Go library, go-steem/rpc/examples/upvote/ and get the following output;
$ go run main.go
# github.com/go-steem/rpc/transactions
../../transactions/signing.c:5:10: fatal error: 'secp256k1.h' file not found
Already it feels as though the wheels are falling off...
Please bear with me as I do not develop in C, so I get a bit hack-y.
After much reading, and googling I decide to copy the files from the 'include' directory where I compiled libsecp256k1 into the same directory as the error is originating from.
You can see the files are not there;
$ ls -la ../../transactions/
total 48
drwxr-xr-x 8 shaunmorrow staff 272 May 8 18:09 .
drwxr-xr-x 15 shaunmorrow staff 510 May 8 18:09 ..
-rw-r--r-- 1 shaunmorrow staff 256 Apr 27 17:53 chains.go
-rw-r--r-- 1 shaunmorrow staff 3731 May 8 18:09 signed_transaction.go
-rw-r--r-- 1 shaunmorrow staff 1849 May 8 18:09 signed_transaction_test.go
-rw-r--r-- 1 shaunmorrow staff 3075 Apr 27 17:53 signing.c
-rw-r--r-- 1 shaunmorrow staff 408 Apr 27 17:53 signing.h
-rw-r--r-- 1 shaunmorrow staff 1049 May 8 18:09 transactions.go
and after the copy;
$ ls -la ../../transactions/
total 128
drwxr-xr-x 11 shaunmorrow staff 374 Jul 18 19:08 .
drwxr-xr-x 15 shaunmorrow staff 510 May 8 18:09 ..
-rw-r--r-- 1 shaunmorrow staff 256 Apr 27 17:53 chains.go
-rw-r--r-- 1 shaunmorrow staff 27071 Jul 18 19:08 secp256k1.h
-rw-r--r-- 1 shaunmorrow staff 1014 Jul 18 19:08 secp256k1_ecdh.h
-rw-r--r-- 1 shaunmorrow staff 4700 Jul 18 19:08 secp256k1_recovery.h
-rw-r--r-- 1 shaunmorrow staff 3731 Jul 18 19:05 signed_transaction.go
-rw-r--r-- 1 shaunmorrow staff 1849 May 8 18:09 signed_transaction_test.go
-rw-r--r-- 1 shaunmorrow staff 3075 Apr 27 17:53 signing.c
-rw-r--r-- 1 shaunmorrow staff 408 Apr 27 17:53 signing.h
-rw-r--r-- 1 shaunmorrow staff 1049 May 8 18:09 transactions.go
Now I get a new error;
$ go run main.go
# github.com/go-steem/rpc/transactions
ld: library not found for -lsecp256k1
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This has me reading and googling some more,
Finally I get even more hack-y and change transactions.go;
// #cgo LDFLAGS: -lsecp256k1
// #include <stdlib.h>
// #include "signing.h"
import "C"
becomes
// #cgo LDFLAGS: -L/usr/local/lib
// #include <stdlib.h>
// #include "signing.h"
import "C"
which fails, output on that later
I also try;
// #cgo LDFLAGS: -L/usr/local/lib -I/usr/local/include
// #include <stdlib.h>
// #include "signing.h"
import "C"
and copy the .h files into the /usr/local/include directory.
None of this works and now I am stuck with an error like this
$ go run main.go
# github.com/go-steem/rpc/transactions
ld: library not found for -lsecp256k1
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ShaunsSePc-2:upvote shaunmorrow$ go run main.go
# github.com/go-steem/rpc/transactions
Undefined symbols for architecture x86_64:
"_secp256k1_context_create", referenced from:
_sign_transaction in signing.o
_verify_recoverable_signature in signing.o
"_secp256k1_context_destroy", referenced from:
_sign_transaction in signing.o
_verify_recoverable_signature in signing.o
"_secp256k1_ec_pubkey_serialize", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recover", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recoverable_signature_convert", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recoverable_signature_parse_compact", referenced from:
_verify_recoverable_signature in signing.o
"_secp256k1_ecdsa_recoverable_signature_serialize_compact", referenced from:
_sign_transaction in signing.o
"_secp256k1_ecdsa_sign_recoverable", referenced from:
_sign_transaction in signing.o
"_secp256k1_ecdsa_verify", referenced from:
_verify_recoverable_signature in signing.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
At this point I really have no idea how to continue.
As you can see I am not experienced in C at all and have no idea how to test if the library libsecp256k1 is even installed properly!
This is where I ended up, but it's highly likely I took a wrong turn early in my journey, I would appreciate any help given as I have been struggling with this for a few nights already now :(
Not sure whats needed so here some env variables
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/shaunmorrow/Work/go/"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/86/hlqptn5101z5bcydjz05qy8m0000gn/T/go-build689438019=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
Version is go version go1.8.3 darwin/amd64 with no old versions lying around.
Thanks!
Your problem is twofold:
Improperly configured libsecp256k1 package
Your C compiler not searching /usr/local directories for installed headers/libs
Fixing the improperly libsecp256k1 configured package
Your "undefined symbols" issue when it comes to linking C libraries sometimes points to an improperly configured package (in the sense of an Autotools package or a CMake package, not a Go package). Running ./configure --help, I see there is an option named --enable-module-recovery. Judging by names like _secp256k1_ecdsa_sign_recoverable and _secp256k1_ecdsa_recover, you need to add that option when configuring, meaning instead of executing the simpler ./configure, you should execute this:
./configure --enable-module-recovery
Is the C compiler broken?
Since the secp256k1.h header file isn't found in /usr/local/include, despite the fact that the header file most definitely exists after sudo make install is finished, it means your compiler doesn't search /usr/local.
Barring any fixes in the linked question, you can work around the issue by altering the source of the Go package as needed to add/modify the CFLAGS and LDFLAGS used when dealing with import "C" statements like this:
// #cgo CFLAGS: -I/usr/local/include
// #cgo LDFLAGS: -L/usr/local/lib -lsecp256k1
// #include <secp256k1.h>
import "C"
If you have pkg-config installed, you can use that instead of setting CFLAGS and LDFLAGS manually:
Export the PKG_CONFIG_PATH environment variable with a custom set of paths. Because no prefix (i.e. directory serving as the install root) was specified, /usr/local is assumed, meaning /usr/local/include will contain headers and /usr/local/lib will contain libraries. This means you need to export PKG_CONFIG_PATH on your command line as in export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig. The default setting of PKG_CONFIG_PATH when unset includes /usr/lib/pkgconfig and /usr/share/pkgconfig in that order on Linux and are specified as a fallback for other packages that might be used, though it may not be necessary in this case. The default set of paths may differ on OS X, so consult your pkg-config man page for reference.
Use // #cgo pkg-config: libsecp256k1, and CFLAGS and LDFLAGS will be set as necessary without you needing to do anything to them. Since not all systems have pkg-config installed, relying on this is perhaps a bad idea if you want a package to remain portable. Then again, I think it'd be preferable to the mess you dealt with since pkg-config simply wouldn't be found.
Change to the upvote directory and type make to build a working upvote binary.
Additional customization
Custom prefix
If you use something other than /usr/local as your prefix (e.g. ./configure --enable-module-recovery --prefix=/opt/libsecp256k1), then you'll need to adjust some things accordingly:
// #cgo CFLAGS: -I/opt/libsecp256k1/include
// #cgo LDFLAGS: -L/opt/libsecp256k1/lib -lsecp256k1
// #include "secp256k1.h"
import "C"
// or just use pkg-config and export the PKG_CONFIG_PATH environment
// variable containing the following paths:
// /opt/libsecp256k1/lib/pkgconfig
// /opt/libsecp256k1/share/pkgconfig
// /usr/lib/pkgconfig
// /usr/share/pkgconfig
You'll also need to modify the provided Makefile in the upvote directory to set the runtime path of the binary that gets built, else libsecp256k1.0.dylib will not be found:
# If you copy and paste this, replace the spaces in front of `go build`
# with a single horizontal tab character, else `make` will fail.
#
# Note that the "ldflags" specified are for the Go linker (go tool link),
# not the system's linker (ld).
build:
go build -ldflags="-r /opt/libsecp256k1/lib"
For more information about working with cgo, check out the following resources:
"C? Go? Cgo!" introduction to cgo on The Go Blog
Cgo documentation
I'm trying to get the following simple 'Hello World' program to compile using a cross compiler (GCC 4.9.2) targeting mips:
#include <stdio.h>
int main()
{
int x = 5;
printf("x = %d\n", x);
}
The x variable is there to stop GCC changing printf to puts, which it seems to do automatically for a simple newline-terminated string.
I've built a cross compiler under ${HOME}/xc and am executing it using the following command:
${HOME}/xc/bin/mips-gcc -v hello.c
However, I'm getting the following error:
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status
I'm assuming this is a problem with the linker, as I'd expect the process to fail earlier if for example stdio.h couldn't be found on the search path. I can compile a simpler program which simply returns zero, so it's not the case that the entire toolchain is broken, presumably just the standard library linking (I'm using newlib 2.2.0-1).
I get the same error regardless of whether I run the cross compiler under Linux (Ubuntu 14.10) or Cygwin (Windows 8).
The full output from GCC is:
Using built-in specs.
COLLECT_GCC=/home/paul/xc/bin/mips-gcc
COLLECT_LTO_WRAPPER=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper
Target: mips
Configured with: /home/paul/xc/mips/tmp/gcc-4.9.2/configure --prefix=/home/paul/xc --target=mips --enable-languages=c --with-newlib --without-isl --without-cloogs --disable-threads --disable-libssp --disable-libgomp --disable-libmudflap
Thread model: single
gcc version 4.9.2 (GCC)
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/libexec/gcc/mips/4.9.2/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -auxbase hello -version -o /tmp/ccCpAajQ.s
GNU C (GCC) version 4.9.2 (mips)
compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/sys-include"
#include "..." search starts here:
#include <...> search starts here:
/home/paul/xc/lib/gcc/mips/4.9.2/include
/home/paul/xc/lib/gcc/mips/4.9.2/include-fixed
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/include
End of search list.
GNU C (GCC) version 4.9.2 (mips)
compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: cffaaedf0b24662e67a5d97387fc5b17
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/as -EB -O1 -no-mdebug -mabi=32 -o /tmp/ccW5mHJu.o /tmp/ccCpAajQ.s
COMPILER_PATH=/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/
LIBRARY_PATH=/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib/
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/libexec/gcc/mips/4.9.2/collect2 -plugin /home/paul/xc/libexec/gcc/mips/4.9.2/liblto_plugin.so -plugin-opt=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper -plugin-opt=-fresolution=/tmp/cc8TAJb9.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc -EB /home/paul/xc/lib/gcc/mips/4.9.2/crti.o /home/paul/xc/lib/gcc/mips/4.9.2/crtbegin.o -L/home/paul/xc/lib/gcc/mips/4.9.2 -L/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib /tmp/ccW5mHJu.o -lgcc -lgcc /home/paul/xc/lib/gcc/mips/4.9.2/crtend.o /home/paul/xc/lib/gcc/mips/4.9.2/crtn.o
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400050
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status
The build script I'm using is here (I wrote it based on half a dozen tutorials which all suggested slightly different things):
https://github.com/UoMCS/mips-cross-compile
Basically it does the following steps:
Build binutils.
Build GCC (stage 1).
Build newlib.
Build GCC (stage 2).
I'm aware that there are other tools such as crosstool-ng and builtroot, however the person I'm building this toolchain for wants to edit parts of binutils before setting off the build process, and the toolchain also has to work under Cygwin (crosstool-ng won't for various reasons, including case-sensitive file paths).
I think this is probably going to be something obvious, but I've been messing around with this for a week and can't see what it could be. Any help would be greatly appreciated!
It is necessary to build libraries to go with your cross compiler. In particular, you need to have a cross-compiled version of glibc or some other implementation of the standard library, to get a version of printf().
Have a look at this link for an example of the type of things you need to consider to get all the things you need - the cross-compiler, the headers, and libraries.
Try linking the library on the command line:
${HOME}/xc/bin/mips-gcc -v hello.c -lib
Including the std libraries (lib and io)header links the implementations by default (libc.so or .a). However, you are using a 'user-defined' implementation and may not be linking the proper one.
I suggest explicit linkage on the command line. I'm not certain of the syntax.
EDIT:
Or better Still, use a makefile to compile with the following lines, and specifying other include directories in the INCLUDES place holder:
CC = gcc
CXX = g++
INCLUDES =
CFLAGS = -g -Wall $(INCLUDES)
CXXFLAGS = -g -Wall $(INCLUDES)
LDFLAGS = -g
hello: hello.o newlib.o
hello.o: hello.c newlib.h
newlib.o: newlib.c newlib.h
newlib.h is the header file you'll include in newlib.c (implementation/definition) source file (that declares the functions) and hello.c. It may be named differently from stdio.h.
Check this out, it may help:
Why do you have to link the math library in C?
and this too:
http://www.tldp.org/HOWTO/Glibc2-HOWTO-6.html
A custom specs file could work:
cd /home/paul/xc/lib/gcc/mips/4.9.2/
${HOME}/xc/bin/mips-gcc -dumpspecs > specs
Add to the specs file:
*lib:
-lc
Note that there must be empty lines before *lib: and after -lc. Perhaps you have to change the library name to the name of your newlib-c-library. Perhaps more must be added than only -lc, e.g. the *lib:-section on my Linux looks more complex.
UPDATE: The builtin specs lib for the default libraries are configured here:
In file gcc-4.9.2/gcc/gcc.c lines 527-530:
/* config.h can define LIB_SPEC to override the default libraries. */
#ifndef LIB_SPEC
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#endif
In file gcc-4.9.2/gcc/config/mips/elf.h lines 40-42:
/* Leave the linker script to choose the appropriate libraries. */
#undef LIB_SPEC
#define LIB_SPEC ""
Perhaps the default LIB_SPEC in gcc.c works for you by commenting out lines 40-42 in elf.h.
Perhaps you need to edit elf.h and replace the empty LIB_SPEC with "-lc" or something similar.
UPDATE: When you configured gcc you gave --target=mips. In gcc-4.9.2\gcc\config.gcc there are other mips-targets which are more specific, e.g.mips*-*-linux*, perhaps selecting the appropriate one gives the right LIB_SPEC and linking will be successful.
UPDATE: big endian Linux target: mips-unknown-linux-gnu little endian Linux target: mipsel-unknown-linux-gnu source
UPDATE: Using your build script I was able to link your sample program with following modifications:
In your config.sh:
export ISL_VERSION="0.12.2"
In file gcc-4.9.2/gcc/config/mips/elf.h lines 40-42:
/* Leave the linker script to choose the appropriate libraries. */
#undef LIB_SPEC
#define LIB_SPEC "-lc -lcfe -lc"
If you don't want the modification in elf.h the libraries must be given when invoking mips-gcc.
UPDATE:
newlib doesn't work at all, GCC fails in the second stage with an error about not being able to find crti.o etc.
Strange, using your build script crti.o was created:
[osboxes#osboxes 4.9.2]$ pwd
/home/osboxes/xc/lib/gcc/mips/4.9.2
[osboxes#osboxes 4.9.2]$ ll
total 6240
-rw-r--r--. 1 osboxes osboxes 3248 May 16 19:49 crtbegin.o
-rw-r--r--. 1 osboxes osboxes 1924 May 16 19:49 crtend.o
-rw-r--r--. 1 osboxes osboxes 1040 May 16 19:49 crti.o
-rw-r--r--. 1 osboxes osboxes 1056 May 16 19:49 crtn.o
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 include
drwxrwxr-x. 2 osboxes osboxes 4096 May 16 19:45 include-fixed
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 install-tools
-rw-r--r--. 1 osboxes osboxes 6289352 May 16 19:49 libgcc.a
-rw-r--r--. 1 osboxes osboxes 56844 May 16 19:49 libgcov.a
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 plugin
-rw-rw-r--. 1 osboxes osboxes 6215 May 18 18:45 specs
printf() was implemented in libc,
Please check your c lib, such as glibc, oh, yours is newlib.
try #4566976 's way
use readelf -s check is there a printf section exists in libc.so libc.a
( i'm not sure the lib filename in newlib, mine is glibc )
The most convenient way to achieve this is to use putchar in place of printf. May be you have to change some of your code, or may be you have to add macros/functions that may run like printf.
I came across a strange issue when using gcc to link the shared library in specified path but not in the standard path.
When I downloaded GNU readline library version 6.3 and compiled it successfully in path $HOME/Downloads.
GNU readline library needs to link libtinfo, so I installed it by sudo apt-get install libtinfo.
After that, I created a small sample test named rl.c to check it. To build my sample project, I also created two symbolic links like follow:
$ ls -lrt ~/Downloads/
drwxr-xr-x 6 sfzhang sfzhang 4096 Mar 2 15:45 readline-6.3
lrwxrwxrwx 1 sfzhang sfzhang 12 Mar 2 16:00 readline -> readline-6.3
$ ls -lrt ~/Downloads/readline-6.3/shlib/
-rwxr-xr-x 1 sfzhang sfzhang 833856 Mar 2 15:36 libreadline.so.6.3
lrwxrwxrwx 1 sfzhang sfzhang 18 Mar 2 16:28 libreadline.so -> libreadline.so.6.3
To use the new built readline library, I export the path to LD_LIBRARY_PATH:
$ echo $LD_LIBRARY_PATH
/home/sfzhang/Downloads/readline/shlib
And, I compiled rl.c using the following command:
$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo
Checking the rl linked libraries:
$ ldd rl
linux-vdso.so.1 => (0x00007fffe09a3000)
libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007fe22d243000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fe22d01a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe22cc8d000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe22d492000)
I also tried anther command, but got the same result:
gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo -Wl,-rpath,$HOME/Downloads/readline/shlib
So, why the rl was liked to /lib/x86_64-linux-gnu/libreadline.so.6 but not $HOME/Downloads/readline/shlib/libreadline.so.
OS: Linux debian 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u1 x86_64 GNU/Linux
gcc: gcc version 4.7.2 (Debian 4.7.2-5)
ldd: ldd (Debian EGLIBC 2.13-38+deb7u6) 2.13
You need a symbolic link called libreadline.so.6 too, not just libreadline.so. The reason is that the soname of libreadline.so.6.3 is libreadline.so.6.
A soname is a "generic" name embedded in the library itself. When you link against a shared library that has a soname, it is that name that gets embedded in your executable and is later looked up by the dynamic linker. (For shared libraries without sonames the filename is used instead, though this is uncommon.) You can tell what the soname of a library is by running e.g.
objdump -p <library> | grep SONAME
The point of sonames is to make it so that your executable is linked against the most generic library name that should be compatible (usually this is the library name with just the major version -- 6 in this case -- tacked on), rather than just the specific (e.g., minor bug fix release) version that you happened to link against.
The output from ldd also tells you that it's looking specifically for libreadline.so.6.
If you really want a path to a library to be hardcoded in the executable, you will need to pass the following to gcc:
-Wl,-rpath=$HOME/Downloads/readline/shlib
setting custom LD_LIBRARY_PATH is not recommended, if you want to use it, use it as a parameter for execution.
LD_LIBRARY_PATH=$HOME/Downloads/readline/shlib ./rc
The are alternative ways to fix your issue:
Link against full path to the .so. E.g.
$ gcc -o rl rl.c -I$HOME/Downloads $HOME/Downloads/readline/shlib/readline.so.6.3 -ltinfo
And as #Ulfalizer suggests, you may need another symbolic link with just the major number.
If you are using LD_LIBRARY_PATH do not forget to export it.
When using -L<path> also use -Wl,-rpath,<path>, so that runtime linker ld.so.2 finds the shared library in the same path as ld does, e.g:
$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -Wl,-rpath,$HOME/Downloads/readline/shlib -lreadline -ltinfo
When debugging linker issues use readelf -d <binary> command to see which exact versions of shared libraries <binary> needs (NEEDED attribute) and where it looks for them (RPATH attribute) prior to looking in the standard linker directories (configuration in /etc/ld.so.conf/).
I've got a tiny C program with the following header:
#include <gmp.h>
I compile it doing:
gcc test.c -o test.o -L/gmp_install/lib -lgmp
And then I can run it fine. But it is using the "stock" GMP library on my system.
Now I'd like to compile it using another version of the GMP lib, which I installed locally and I can't make it work.
The new library is apparently installed in /usr/local/lib:
... $ ls -l /usr/local/lib
-rw-r--r-- 1 root staff 1276320 Jun 15 02:22 libgmp.a
-rwxr-xr-x 1 root staff 914 Jun 15 02:22 libgmp.la
lrwxrwxrwx 1 root staff 16 Jun 15 02:22 libgmp.so -> libgmp.so.10.2.0
lrwxrwxrwx 1 root staff 16 Jun 15 02:22 libgmp.so.10 -> libgmp.so.10.2.0
-rwxr-xr-x 1 root staff 528715 Jun 15 02:22 libgmp.so.10.2.0
But no matter what I try, it's apparently the old library that is used.
Even using:
gcc perf.c -o perf.o -O3 -L/ -lgmp
But it's using the GMP version in /usr/lib/x86_64-linux-gnu/.
What is the correct way to use the GMP version in /usr/local/bin, knowing I'd like to keep the old version too?
Also, once the executable is created, is there an easy way to see which library it shall use at runtime? (can I create the executable with one version of GMP and then execute it with another version of GMP, knowing the lib is dynamically linked?)
Do two things:
Use -L/usr/local/lib flag while compiling
Set LD_LIBRARY_PATH variable while running your program to have /usr/local/lib. Thus, if you are using a bash shell, you will have to do something like
$ export LD_LIBRARY_PATH=/usr/local/lib
$ ./your_program
to use the /usr/local/lib version at runtime. Also, in order to see which one it will use at runtime, you can always do ldd <your binary name> which will print out all the dynamic dependencies.