JNI Cross Compiled from OS-X to Windows Fails with "Can't find dependent libraries" - java-native-interface

I have a Java JNI program that I am building on Apple OS-X and cross-compiling for Windows 10.
The build and runs fine on OS-X. Cross-compiling for Windows 64-bit completes with no errors, but the generated program fails to run under Windows 10 and gives the error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Michael\Documents\JNIExample\MyLib.dll: Can't find dependent libraries
The error occurs only when I add a reference to the C++ new operator. When this is removed the "Can't find dependent libraries" goes away and the application runs. This program did once run with earlier versions of these tools and operating systems.
My guess is that I am missing something crucial from the x86_64-w64-mingw32-gcc to include a statically bound library required for the new operator. Can anyone help?
The command used to build the project are in the bash shell script file: doit.sh
#!/bin/bash
echo "=== Building on OS-X ==="
export JAVA_HOME="`/usr/libexec/java_home -v '14*'`"
# Clean up
rm -rf bin/*.class MyLib/*.o *.dll *.jnilib *.jar
# Compile Java and generate JNI header file
mkdir -p bin
javac -d bin -h MyLib -sourcepath src src/*.java
# Create the JAR file, main entry point in class MyLib
jar cfe Test.jar MyLib -C bin .
# Build the C++ shared library
gcc -c -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" MyLib/MyLib.cpp -o MyLib/MyLib.mac.o
g++ -dynamiclib -o libMyLib.jnilib MyLib/*.mac.o
echo "=== Running on OS-X ==="
java -jar Test.jar
echo "=== Building on OS-X ==="
# Cross compile for the Windows shared library
/usr/local/bin/x86_64-w64-mingw32-gcc -D __LP64__ -c -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin MyLib/MyLib.cpp -o MyLib/MyLib.win.o
/usr/local/bin/x86_64-w64-mingw32-g++ -shared -static-libgcc -static-libstdc++ -o MyLib.dll MyLib/*.win.o
My aim is to make a Windows and Mac distribution of the application using jlink and jpackage so all libraries will ultimately be needed by included with my final distribution.
Tool Versions
| Tool | Version |
|-------------------------|----------------------|
| MacBook Pro | OS-X Catalina 10.15.6 |
| x86_64-w64-mingw32-gcc/g++ | 9.3.0 (GCC) (download with brew install mingw-w64) |
| gcc/g++ | Apple clang version 12.0.0 (clang-1200.0.31.1) |
| java | java version "14.0.1" 2020-04-14 |
x86_64-w64-mingw32-gcc -v Output
michaelellis$ /usr/local/bin/x86_64-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=/usr/local/bin/x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/libexec/gcc/x86_64-w64-mingw32/9.3.0/lto-wrapper
Target: x86_64-w64-mingw32
Configured with: ../configure --target=x86_64-w64-mingw32 --with-sysroot=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64 --prefix=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64 --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --enable-languages=c,c++,fortran --with-ld=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/bin/x86_64-w64-mingw32-ld --with-as=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/bin/x86_64-w64-mingw32-as --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --disable-multilib --enable-threads=posix
Thread model: posix
gcc version 9.3.0 (GCC)
The full SSCCE is available on public git at: https://gitlab.com/Michael51773/jniexample

Next step in investigating this was to create a simple C++ standalone command-line app that utilised the shareable library.
This built and ran correctly on OS-X but when deploying the cross-compiled products to the Windows platform it failed to execute listing the following libraries as missing:
libstc++-6.dll
libwinpthread-1.dll
libgcc_s_seh
Copying these files from the mingw distribution /usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/x86_64-w64-mingw32/.. into the same directory as the application on the Windows platform solved the problem!
It looks to me as if the mingcw g++ -static-libgcc -static-libstdc++ may not be working as they used to!

Related

Configuring compilers on Mac M1 (Big Sur, Monterey) for Rcpp and other tools

I'm trying to use packages that require Rcpp in R on my M1 Mac, which I was never able to get up and running after purchasing this computer. I updated it to Monterey in the hope that this would fix some installation issues but it hasn't. I tried running the Rcpp check from this page but I get the following error:
> Rcpp::sourceCpp("~/github/helloworld.cpp")
ld: warning: directory not found for option '-L/opt/R/arm64/gfortran/lib/gcc/aarch64-apple-darwin20.2.0/11.0.0'
ld: warning: directory not found for option '-L/opt/R/arm64/gfortran/lib'
ld: library not found for -lgfortran
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [sourceCpp_4.so] Error 1
clang++ -arch arm64 -std=gnu++14 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I../inst/include -I"/Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/library/Rcpp/include" -I"/Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/library/RcppArmadillo/include" -I"/Users/afredston/github" -I/opt/R/arm64/include -fPIC -falign-functions=64 -Wall -g -O2 -c helloworld.cpp -o helloworld.o
clang++ -arch arm64 -std=gnu++14 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/lib -L/opt/R/arm64/lib -o sourceCpp_4.so helloworld.o -L/Library/Frameworks/R.framework/Resources/lib -lRlapack -L/Library/Frameworks/R.framework/Resources/lib -lRblas -L/opt/R/arm64/gfortran/lib/gcc/aarch64-apple-darwin20.2.0/11.0.0 -L/opt/R/arm64/gfortran/lib -lgfortran -lemutls_w -lm -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
Error in Rcpp::sourceCpp("~/github/helloworld.cpp") :
Error 1 occurred building shared library.
I get that it can't "find" gfortran. I installed this release of gfortran for Monterey. When I type which gfortran into Terminal, it returns /opt/homebrew/bin/gfortran. (Maybe this version of gfortran requires Xcode tools that are too new—it says something about 13.2 and when I run clang --version it says 13.0—but I don't see another release of gfortran for Monterey?)
I also appended /opt/homebrew/bin: to PATH in R so it looks like this now:
> Sys.getenv("PATH")
[1] "/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Library/TeX/texbin:/Applications/RStudio.app/Contents/MacOS/postback"
Other things I checked:
Xcode command line tools is installed (which clang returns /usr/bin/clang).
Files ~/.R/Makevars and ~/.Renviron don't exist.
Here's my session info:
R version 4.1.1 (2021-08-10)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Monterey 12.1
Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_4.1.1 tools_4.1.1 RcppArmadillo_0.10.7.5.0
[4] Rcpp_1.0.7
Background
Currently (2023-02-20), CRAN builds R 4.2 binaries for Apple silicon using Apple Clang from Command Line Tools for Xcode 13.1 and using an experimental fork of GNU Fortran 12.
If you obtain R from CRAN (i.e., here), then you need to replicate CRAN's compiler setup on your system before building R packages that contain C/C++/Fortran code from their sources (and before using Rcpp, etc.). This requirement ensures that your package builds are compatible with R itself.
A further complication is the fact that Apple Clang doesn't support OpenMP, so you need to do even more work to compile programs that make use of multithreading. You could circumvent the issue by building R itself, all R packages, and all external libraries from sources with LLVM Clang, which does support OpenMP, but that approach is onerous and "for experts only".
There is another approach that has been tested by a few people, including Simon Urbanek, the maintainer of R for macOS. It is experimental and also "for experts only", but it works on my machine and is much simpler than learning to build R and other libraries yourself.
Instructions for obtaining a working toolchain
Warning: These come with no warranty and could break at any time. Some level of familiarity with C/C++/Fortran program compilation, Makefile syntax, and Unix shells is assumed. Everyone is encouraged to consult official documentation, which is more likely to be maintained than answers on SO. As usual, sudo at your own risk.
I will try to address compilers and OpenMP support at the same time. I am going to assume that you are starting from nothing. Feel free to skip steps you've already taken, though you might find a fresh start helpful.
I've tested these instructions on a machine running Big Sur, but they should also work on Monterey and Ventura.
Download an R 4.2 binary from CRAN here and install. Be sure to select the binary built for Apple silicon.
Run
$ sudo xcode-select --install
in Terminal to install the latest release version of Apple's Command Line Tools for Xcode, which includes Apple Clang. You can obtain earlier versions from your browser here. However, the version that you install should not be older than the one that CRAN used to build your R binary.
Download the GNU Fortran binary provided here and install by unpacking to root:
$ curl -LO https://mac.r-project.org/tools/gfortran-12.0.1-20220312-is-darwin20-arm64.tar.xz
$ sudo tar xvf gfortran-12.0.1-20220312-is-darwin20-arm64.tar.xz -C /
$ sudo ln -sfn $(xcrun --show-sdk-path) /opt/R/arm64/gfortran/SDK
The last command updates a symlink inside of the installation so that it points to the SDK inside of your Command Line Tools installation.
Download an OpenMP runtime suitable for your Apple Clang version here and install by unpacking to root. You can query your Apple Clang version with clang --version. For example, I have version 1300.0.29.3, so I did:
$ curl -LO https://mac.r-project.org/openmp/openmp-12.0.1-darwin20-Release.tar.gz
$ sudo tar xvf openmp-12.0.1-darwin20-Release.tar.gz -C /
After unpacking, you should find these files on your system:
/usr/local/lib/libomp.dylib
/usr/local/include/ompt.h
/usr/local/include/omp.h
/usr/local/include/omp-tools.h
Add the following lines to $(HOME)/.R/Makevars, creating the file if necessary.
CPPFLAGS += -I/usr/local/include -Xclang -fopenmp
LDFLAGS += -L/usr/local/lib -lomp
Test that you are able to use R to compile a C or C++ program with OpenMP support while linking relevant libraries from the GNU Fortran installation (indicated by the -l flags in the output of R CMD CONFIG FLIBS).
The most transparent approach is to use R CMD SHLIB directly. In a temporary directory, create an empty source file omp_test.c and add the following lines:
#ifdef _OPENMP
# include <omp.h>
#endif
#include <Rinternals.h>
SEXP omp_test(void)
{
#ifdef _OPENMP
Rprintf("OpenMP threads available: %d\n", omp_get_max_threads());
#else
Rprintf("OpenMP not supported\n");
#endif
return R_NilValue;
}
Compile it:
$ R CMD SHLIB omp_test.c $(R CMD CONFIG FLIBS)
Then call the compiled C function from R:
$ R -e 'dyn.load("omp_test.so"); invisible(.Call("omp_test"))'
OpenMP threads available: 8
If the compiler or linker throws an error, or if you find that OpenMP is still not supported, then one of us has made a mistake. Please report any issues.
Note that you can implement the same test using Rcpp, if you don't mind installing it:
library(Rcpp)
registerPlugin("flibs", Rcpp.plugin.maker(libs = "$(FLIBS)"))
sourceCpp(code = '
#ifdef _OPENMP
# include <omp.h>
#endif
#include <Rcpp.h>
// [[Rcpp::plugins(flibs)]]
// [[Rcpp::export]]
void omp_test()
{
#ifdef _OPENMP
Rprintf("OpenMP threads available: %d\\n", omp_get_max_threads());
#else
Rprintf("OpenMP not supported\\n");
#endif
return;
}
')
omp_test()
OpenMP threads available: 8
References
Everything is a bit scattered:
R Installation and Administration manual [link]
Writing R Extensions manual [link]
R for macOS Developers web page [link]
I resolved this issue by adding a path to the homebrew installation of gfortran to my ~/.R/Makevars following these instructions: https://pat-s.me/transitioning-from-x86-to-arm64-on-macos-experiences-of-an-r-user/#gfortran
I just avoided the issue until MacOS had things working more smoothly. so I either Windows Developer Virtual Machine (VM) or run my code development in another environment. I'm not too impressed with the updated and "faster" chipset, but that it doesn't work with much. Slow to implement and work-a-rounds often are a must.
Tested the following process for making multithread data.table work in a M2 MacBook Pro (macOS Monterey)
Steps are mostly the same with this answer by the user inferator.
Download and install R from CRAN
Download and install RStudio with developer tools
Run the following commands in terminal to install OpenMP
curl -O https://mac.r-project.org/openmp/openmp-12.0.1-darwin20-Release.tar.gz
sudo tar fvxz openmp-12.0.1-darwin20-Release.tar.gz -C /
Add compiler flags to connect clan w/ OpenMP. In terminal, write the following:
cd ~
mkdir .R
nano .R/Makevars
Inside the opened Makevars file paste the following lines. Once finished, hit command+O and then Enter to save. Do a command+X to close the editor.
CPPFLAGS += -Xclang -fopenmp
LDFLAGS += -lomp
Download and run the installer for gfortran by downloading gfortran-ARM-12.1-Monterey.dmg from the respective GitHub repo
This concludes the steps regarding enabling OpenMP and (hopefully) Rcpp in R under a M2 chip system.
Now, for testing that everything works with data.table I did the following
Open RStudio and run
install.packages("data.table", type = "source")
If everything is done correctly, the package should compile without any errors and return the following when running getDTthreads(verbose = TRUE):
OpenMP version (_OPENMP) 201811
omp_get_num_procs() 8
R_DATATABLE_NUM_PROCS_PERCENT unset (default 50)
R_DATATABLE_NUM_THREADS unset
R_DATATABLE_THROTTLE unset (default 1024)
omp_get_thread_limit() 2147483647
omp_get_max_threads() 8
OMP_THREAD_LIMIT unset
OMP_NUM_THREADS unset
RestoreAfterFork true
data.table is using 4 threads with throttle==1024. See ?setDTthreads.
[1] 4

How to build Static Binary for Tesseract?

I am currently building Tesseract 4.0.0 from source (on Ubuntu 14.04 for context), using the instructions found on: https://github.com/tesseract-ocr/tesseract/wiki/Compiling
I am using the following ./configure parameters:
./configure --disable-openmp --disable-graphics --disable-opencl --enable-static LDFLAGS='-static -static-libgcc -static-libstdc++' --disable-shared
Followed by
make and sudo make install
The compiled binary I am running after is src/api/tesseract, which works as intended. The problem is that when I run ldd on this file, it actually shows dependencies.
Am I looking in the wrong spot for the static binary of Tesseract (I ran a find command in the entire repo and didn't see anything else that looked like an executable), or am I misunderstanding the meaning of a static binary - I am under the impression it is pretty much an executable version of Tesseract that does not require any dependencies to be pre installed.
If there is any problem with the configure options too please let me know. I do not believe that --disable-openmp --disable-graphics --disable-opencl impacts static vs shared linking but I am using those for my desired tesseract build so I included them for more context.
$ uname -a
Linux vm00 4.15.0-50-generic #54-Ubuntu SMP Mon May 6 18:46:08 UTC
2019 x86_64 x86_64 x86_64 GNU/Linux
$ echo $CFLAGS
-static
$ echo $LDFLAGS
-static -static-libgcc -static-libstdc++
$ ./configure --enable-static LDFLAGS='-static -static-libgcc -static-libstdc++' --disable-shared
...
Configuration is done.
$ make
...
Making all in unittest
...
$ file src/api/tesseract
src/api/tesseract: ELF 64-bit LSB shared object, x86-64, version 1
(GNU/Linux), dynamically linked, interpreter /lib64/l, for
GNU/Linux 3.2.0,
BuildID[sha1]=96afb1f1ff8962b3f9046c40407364ebf26369d1, with
debug_info, not stripped
Not statically linked.

How to rebuild newlib and newlib-nano of GNU Arm Embedded Toolchain

I downloaded the toolchain “gcc-arm-none-eabi-6-2017-q2-update-win32-sha1.exe” (Windows) from https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads and installed it on my Windows 10 PC.
The installation folder contains a release.txt in “../share/doc/gcc-arm-none-eabi/” which tells:
This release includes the following items:
newlib and newlib-nano :
git://sourceware.org/git/newlib-cygwin.git commit 0d79b021a4ec4e6b9aa1a9f6db0e29a137005ce7
And also the readme.txt in “../share/doc/gcc-arm-none-eabi/” contains:
C Libraries usage *
This toolchain is released with two prebuilt C libraries based on
newlib: one is the standard newlib (libc.a) and the other is
newlib-nano (libc_nano.a) for code size.
Now I want exactly rebuild all the libc.a and libc_nano.a contained in “../arm-none-eabi/lib/thumb”
At the moment I can build on Ubuntu with “gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2”
$ # Downloaded newlib-cygwin (with corresponding hash) into folder newlib-cygwin
$ mkdir build
$ cd build
$ ../newlib-cygwin/configure --target=arm-none-eabi --disable-newlib-supplied-syscalls
$ make
How do I have to configure the newlib to build the exact copies of libc.a and for libc_nano.a contained in gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2?
$ # Downloaded newlib-cygwin (with corresponding hash) into folder newlib-cygwin
$ mkdir build
$ cd build
$ ../newlib-cygwin/configure --target=arm-none-eabi --???
$ make
If i understand you correctly, a more detailed question is:
What configure options did 'GNU Arm Embedded Toolchain' developers used when building newlib libraries shipped in gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 archive?
These ones for newlib:
--target=arm-none-eabi --enable-newlib-io-long-long --enable-newlib-register-fini --enable-newlib-retargetable-locking --disable-newlib-supplied-syscalls --disable-nls
And these ones for newlib-nano:
--target=arm-none-eabi --enable-newlib-reent-small --disable-newlib-fvwrite-in-streamio --disable-newlib-fseek-optimization --disable-newlib-wide-orient --enable-newlib-nano-malloc --disable-newlib-unbuf-stream-opt --enable-lite-exit --enable-newlib-global-atexit --enable-newlib-nano-formatted-io --disable-nls
How I got it? Let's walk through the process:
These packages are build on launchpad, where from you find all the builds that took place on lanuchpad. I picked gcc-arm-none-eabi 6-2017q2-1 from 2017-10-24. There i can find the buildlog. I grepped the buildlog with | grep "^+ " | grep "configure " | grep 'src/newlib' and i was left with:
+ /<<PKGBUILDDIR>>/src/newlib/configure --target=arm-none-eabi --prefix=/<<PKGBUILDDIR>>/install-native --infodir=/<<PKGBUILDDIR>>/install-native/share/doc/gcc-arm-none-eabi/info --mandir=/<<PKGBUILDDIR>>/install-native/share/doc/gcc-arm-none-eabi/man --htmldir=/<<PKGBUILDDIR>>/install-native/share/doc/gcc-arm-none-eabi/html --pdfdir=/<<PKGBUILDDIR>>/install-native/share/doc/gcc-arm-none-eabi/pdf --enable-newlib-io-long-long --enable-newlib-register-fini --enable-newlib-retargetable-locking --disable-newlib-supplied-syscalls --disable-nls
+ /<<PKGBUILDDIR>>/src/newlib/configure --target=arm-none-eabi --prefix=/<<PKGBUILDDIR>>/build-native/target-libs --disable-newlib-supplied-syscalls --enable-newlib-reent-small --disable-newlib-fvwrite-in-streamio --disable-newlib-fseek-optimization --disable-newlib-wide-orient --enable-newlib-nano-malloc --disable-newlib-unbuf-stream-opt --enable-lite-exit --enable-newlib-global-atexit --enable-newlib-nano-formatted-io --disable-nls
A bit of Sherlock Holmes and i deduced that the second line is newlib configured to build as newlib-nano (--enable-newlib-reent-small), the first is newlib configured to build as full newlib.
To answer your topic question, to recompile newlib and newlib-nano the same way pass the options I have posted above to newlib ./configure script.
Hints about how the compiler was configured are found in:
$COMPILER_PATH/arm-none-eabi/include/newlib.h
$COMPILER_PATH/arm-none-eabi/include/newlib-nano/newlib.h
The #defines there have a close correspondence to the options that were passed to 'configure', when newlib was built.
I figured it would be useful to give the default configuration of the ARM built newlib/newlib-nano as of 2023 (for GCC 10):
For Newlib:
--enable-newlib-io-long-long
--enable-newlib-io-c99-formats
--enable-newlib-reent-check-verify
--enable-newlib-register-fini
--enable-newlib-retargetable-locking
--disable-newlib-supplied-syscalls
--disable-nls
For Newlib-nano:
--disable-newlib-supplied-syscalls
--enable-newlib-reent-check-verify
--enable-newlib-reent-small
--enable-newlib-retargetable-locking
--disable-newlib-fvwrite-in-streamio
--disable-newlib-fseek-optimization
--disable-newlib-wide-orient
--enable-newlib-nano-malloc
--disable-newlib-unbuf-stream-opt
--enable-lite-exit
--enable-newlib-global-atexit
--enable-newlib-nano-formatted-io
--disable-nls
Ref: https://community.arm.com/support-forums/f/compilers-and-libraries-forum/53310/gcc-arm-none-eabi-what-were-the-newlib-compilation-options

How to build a 64 bit native JNI library on AIX

I am trying to compile and build 64 bit native library on AIX system and execute using JNI Java. My library contains a simple C++ program which accepts a string and returns reversing it. Basically, I created it in 32 bit environment first, it executed absolutely fine. Here are my commands:
32bit:
g++ -Wall -I/usr/java14/include -shared Reverse.cpp -o libReverse.so
The library generated also looks 32 bit environment specific
$ file libReverse.so
libReverse.so: executable (RISC System/6000) or object module not stripped
and I execute it using 32bit Java which works fine
$ /usr/java14/bin/java -Djava.library.path=. com/test/Reverse test
tset
But when I try the same thing for 64 bit, problem occurs. First I recompile the java class using 64 bit JVM (we have 32 bit and 64 bit installed in same machine) and generate the library 64 bit
$ java -d64 -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build pap6470sr4fp2-20130426_01(SR4 FP2))
IBM J9 VM (build 2.6, JRE 1.7.0 AIX ppc64-64 Compressed References 20130422_146026 (JIT enabled, AOT enabled)
J9VM - R26_Java726_SR4_FP2_20130422_1320_B146026
JIT - r11.b03_20130131_32403ifx4
GC - R26_Java726_SR4_FP2_20130422_1320_B146026_CMPRSS
J9CL - 20130422_146026)
JCL - 20130425_01 based on Oracle 7u21-b09
Here is the compile options I used:
$ g++ -maix64 -Wall -I/usr/java7_64/include/ -I/usr/java7_64/include/aix/ -shared Reverse.cpp -o libReverse.so
$ file libReverse.so
libReverse.so: 64-bit XCOFF executable or object module not stripped
This is the output I get
$ java -Djava.library.path=. com/test/Reverse test
Exception in thread "main" java.lang.UnsatisfiedLinkError: Reverse (A file or directory in the path name does not exist.)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:1197)
at java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:1161)
at java.lang.System.loadLibrary(System.java:527)
at com.test.Reverse.<clinit>(Reverse.java:9)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:236)
This is my G++ version details:
$ g++ -v
Using built-in specs.
Target: powerpc-ibm-aix6.1.0.0
Configured with: ../configure --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable- languages=c,c++,java --prefix=/opt/freeware --enable-threads --enable-version-specific- runtime-libs --host=powerpc-ibm-aix6.1.0.0 --target=powerpc-ibm-aix6.1.0.0 --build=powerpc- ibm-aix6.1.0.0 --disable-libjava-multilib
Thread model: aix
gcc version 4.2.0
While executing the java, I had them in my PATH/LD_LIBRARY_PATH.
My doubts are: Am I not able to generate the 64 bit library properly?Is
there any options got missed out while linking/compiling in G++? I
added -maix64 got it from internet.
Is G++ has platform specific
installation? or same installation I can use for both 32bit/64bit by
passing options?
If yes, how do I check current installation supporting 32 bit/64 bit?
Can you please share the command to build the same in 64 bit?
Help Appreciated! Let me know if you need any other information.
Regards,
Bhaskar
----------------------Modifications I did after suggestions ------------------
64 bit
Export an environment variable OBJECT_MODE=64 to facilitate the 64 bit compile and link environment
$ export OBJECT_MODE=64
Recompiled the java class using 64 bit java
javac -d64 -d classes/ com/test/Reverse.java
Generate the header file using 64 bit java
javah -d64 -jni com.test.Reverse
Compile and generate the library
g++ -maix64 -Wall -I/usr/java7_64/include/ -I/usr/java7_64/include/aix/ -shared Reverse.cpp -o libReverse.so
After quering symbols it looks like:
$ nm -g libReverse.so
.Java_com_test_Reverse_reverse T 268436588
._GLOBAL__DD T 268437816
._GLOBAL__DI T 268437740
._GLOBAL__FD_libReverse_so T 268437532
._GLOBAL__FI_libReverse_so T 268437324
._ZN7JNIEnv_12NewStringUTFEPKc T 268436080
._ZN7JNIEnv_17GetStringUTFCharsEP8_jstringPh T 268436408
._ZN7JNIEnv_18GetStringUTFLengthEP8_jstring T 268436236
.__deregister_frame_info T 268437116
.__fd_select T 268436040
.__register_frame_info_table T 268437076
.malloc T 268436000
.strlen T 268435960
Java_com_test_Reverse_reverse D 536873888
_GLOBAL__FD_libReverse_so D 536873984
_GLOBAL__FI_libReverse_so D 536873912
_GLOBAL__F_Java_com_test_Reverse_reverse_298BA8FC D 536873352
_ZN7JNIEnv_12NewStringUTFEPKc D 536873816 24
_ZN7JNIEnv_17GetStringUTFCharsEP8_jstringPh D 536873864 24
_ZN7JNIEnv_18GetStringUTFLengthEP8_jstring D 536873840 24
__deregister_frame_info U -
__fd_select U -
__gxx_personality_v0 U -
__register_frame_info_table U -
malloc U -
strlen U -
$ file libReverse.so
libReverse.so: 64-bit XCOFF executable or object module not stripped
When I run with -d64 option
$ java -d64 -Djava.library.path=. com/test/Reverse test
Exception in thread "main" java.lang.UnsatisfiedLinkError: Reverse (A file or directory in the path name does not exist.)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:1197)
at java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:1161)
at java.lang.System.loadLibrary(System.java:527)
at com.test.Reverse.<clinit>(Reverse.java:9)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:236)
Trying to use -m64 option instead of -maix64
$ g++ -m64 -Wall -I/usr/java7_64/include/ -I/usr/java7_64/include/aix/ -shared Reverse.cpp -o libReverse.so
cc1plus: error: unrecognized command line option "-m64"
Still no luck and I am stuck at UnsatisfiedLinkError, Is there anything I am still missing?

Linking g++ 4.8 to libstdc++

I downloaded and built gcc 4.8.1 on my desktop, running 64-bit Ubuntu 12.04. I built it out of source, like the docs recommend, and with the commands
../../gcc-4.8.1/configure --prefix=$HOME --program-suffix=-4.8
make
make -k check
make install
It seemed to pass all the tests, and I installed everything into my home directory w/ the suffix -4.8 to distinguish from the system gcc, which is version 4.6.3.
Unfortunately when I compile c++ programs using g++-4.8 it links to the system libc and libstdc++ rather than the newer ones compiled from gcc-4.8.1. I downloaded and built gcc 4.8 because I wanted to play around with the new C++11 features in the standard library, so this behaviour is definitely not what I wanted. What can I do to get gcc-4.8 to automatically link to the standard libraries that came with it rather than the system standard libraries?
When you link with your own gcc you need to add an extra run-time linker search path(s) with -Wl,-rpath,$(PREFIX)/lib64 so that at run-time it finds the shared libraries corresponding to your gcc.
I normally create a wrapper named gcc and g++ in the same directory as gcc-4.8 and g++-4.8 which I invoke instead of gcc-4.8 and g++-4.8, as prescribed in Dynamic linker is unable to find GCC libraries:
#!/bin/bash
exec ${0}SUFFIX -Wl,-rpath,PREFIX/lib64 "$#"
When installing SUFFIX and PREFIX should be replaced with what was passed to configure:
cd ${PREFIX}/bin && rm -f gcc g++ c++ gfortran
sed -e 's#PREFIX#${PREFIX}#g' -e 's#SUFFIX#${SUFFIX}#g' gcc-wrapper.sh > ${PREFIX}/bin/gcc
chmod +x ${PREFIX}/bin/gcc
cd ${PREFIX}/bin && ln gcc g++ && ln gcc c++ && ln gcc gfortran
(gcc-wrapper.sh is that bash snippet).
The above solution does not work with some versions of libtool because g++ -Wl,... -v assumes linking mode and fails with an error.
A better solution is to use specs file. Once gcc/g++ is built, invoke the following command to make gcc/g++ add -rpath to the linker command line (replace ${PREFIX}/lib64 as necessary):
g++ -dumpspecs | awk '/^\*link:/ { print; getline; print "-rpath=${PREFIX}/lib64", $0; next } { print }' > $(dirname $(g++ -print-libgcc-file-name))/specs
I just had the same problem when building gcc-4.8.2. I don't have root access on that machine and therefore need to install to my home directory. It took several attempts before I figured out the magic required to get this to work so I will reproduce it here so other people will have an easier time. These are the commands that I used to configure gcc:
prefix=/user/grc/packages
export LDFLAGS=-Wl,-rpath,$prefix/lib
export LD_RUN_PATH=$prefix/lib
export LD_LIBRARY_PATH=$prefix/lib
../../src/gmp-4.3.2/configure --prefix=$prefix
../../src/mpfr-2.4.2/configure --prefix=$prefix
../../src/mpc-0.8.1/configure --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix
../../src/gcc-4.8.2/configure --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix --with-mpc=$prefix --enable-languages=c,c++
That got me a working binary but any program I built with that version of g++ wouldn't run correctly unless I built it with the -Wl,-rpath,$prefix/lib64 option. It is possible to get g++ to automatically add that option by providing a specs file. If you run
strace g++ 2>&1 | grep specs
you can see which directories it checks for a specs file. In my case it was $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/specs so I ran g++ -dumpspecs to create a new specs file:
cd $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2
$prefix/bin/g++ -dumpspecs > xx
mv xx specs
and then edited that file to provide the -rpath option. Search for the lines like this:
*link_libgcc:
%D
and edit to add the rpath option:
*link_libgcc:
%D -rpath /user/grc/packages/lib/%M
The %M expands to either ../lib or ../lib64 depending on whether you are building a 32-bit or a 64-bit executable.
Note that when I tried this same trick on an older gcc-4.7 build it didn't work because it didn't expand the %M. For older versions you can remove the %M and just hardcode lib or lib64 but that is only a viable solution if you only ever build 32-bit executables (with lib) or only ever build 64-bit executables (with lib64).
gcc -print-search-dirs will tell you where your compiler is looking for runtime libraries, etc. You can override this with the -B<prefix> option.