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?
Related
I'm trying to compile a 32-bit C application on Ubuntu Server 12.04 LTS 64-bit using gcc 4.8. I'm getting linker error messages about incompatible libraries and skipping -lgcc. What do I need to do to get 32 bit apps compiled and linked?
This is known to work on Ubuntu 16.04 through 22.04:
sudo apt install gcc-multilib g++-multilib
Then a minimal hello world:
main.c
#include <stdio.h>
int main(void) {
puts("hello world");
return 0;
}
compiles without warning with:
gcc -m32 -ggdb3 -O0 -pedantic-errors -std=c89 \
-Wall -Wextra -pedantic -o main.out main.c
And
./main.out
outputs:
hello world
And:
file main.out
says:
main.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=87c87a83878ce7e7d23b6236e4286bf1daf59033, not stripped
and:
qemu-i386 main.out
also gives:
hello world
but fails on an x86_64 executable with:
./main.out: Invalid ELF image for this architecture
Furthermore, I have:
run the compiled file in a 32 bit VM
compiled and run an IA-32 C driver + complex IA-32 code
So I think it works :-)
See also: Cannot find crtn.o, linking 32 bit code on 64 bit system
It is a shame that this package conflicts with the cross compilers like gcc-arm-linux-gnueabihf https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
Running versions of the question:
https://unix.stackexchange.com/questions/12956/how-do-i-run-32-bit-programs-on-a-64-bit-debian-ubuntu
https://askubuntu.com/questions/454253/how-to-run-32-bit-app-in-ubuntu-64-bit
We are able to run 32-bit programs directly on 64-bit Ubuntu because the Ubuntu kernel is configured with:
CONFIG_IA32_EMULATION=y
according to:
grep CONFIG_IA32_EMULATION "/boot/config-$(uname -r)"
whose help on the kernel source tree reads:
Include code to run legacy 32-bit programs under a
64-bit kernel. You should likely turn this on, unless you're
100% sure that you don't have any 32-bit programs left.
This is in turn possible because x86 64 bit CPUs have a mode to run 32-bit programs that the Linux kernel uses.
TODO: what options does gcc-multilib get compiled differently than gcc?
To get Ubuntu Server 12.04 LTS 64-bit to compile gcc 4.8 32-bit programs, you'll need to do two things.
Make sure all the 32-bit gcc 4.8 development tools are completely installed:
sudo apt-get install lib32gcc-4.8-dev
Compile programs using the -m32 flag
gcc pgm.c -m32 -o pgm
Multiarch installation is supported by adding the architecture information to the package names you want to install (instead of installing these packages using alternative names, which might or might not be available).
See this answer for more information on (modern) multiarch installations.
In your case you'd be better off installing the 32bit gcc and libc:
sudo apt-get install libc6-dev:i386 gcc:i386
It will install the 32-bit libc development and gcc packages, and all depending packages (all 32bit versions), next to your 64-bit installation without breaking it.
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!
I want to install xgboost using anaconda python. In this process, I am trying to install xgboost. While trying to "make" the xgboost i am getting the below error:
C:\GitRepository\xgboost>
g++ -m64 -c -Wall -O3 -msse2 -Wno-unknown-pragmas -funroll-loops -fopenmp -fPIC
-o updater.o src/tree/updater.cpp
src/tree/updater.cpp:1:0: warning: -fPIC ignored for target (all code is positio
n independent)
// Copyright 2014 by Contributors
^
src/tree/updater.cpp:1:0: sorry, unimplemented: 64-bit mode not compiled in
make: *** [updater.o] Error 1
I understood from the other Stack overflow posts that 32 bit gcc cannot go with the 64bit anaconda that i am using. However when i installed mingw-w64 i could see that it has g++ only for mingw32 and not for mingw-w64. Under the mingw-w64 package, g++ and other applications+folders are present only for mingw32 and not for 64. For mingw-64 only a batch file and a internet short cut is present.
Could you please guide me what is going wrong or guide me to an appropriate place from where i can download for mingw-64.
Thanks in advance.
If you are really using MSYS2, then you should not be downloading separate compilers. You should install 64-bit g++ using MSYS2's package manager, by running pacman -S mingw-w64-x86_64-toolchain. Then make sure that you start the MSYS2 shell using the shortcut that is named something like "MSYS2 Win64 Shell" in your start menu. Type which g++ in Bash and make sure it outputs /mingw64/bin/g++. Then you should be able to compile code for 64-bit Windows.
I'm not sure that this answer is complete. If you need more help with MSYS2, it would be good to post the exact commands you are running to download/extract the source code and build so that others can reproduce the error.
Ok, this is just a bit of a fun exercise, but it can't be too hard compiling programmes for some older linux systems, or can it?
I have access to a couple of ancient systems all running linux and maybe it'd be interesting to see how they perform under load. Say as an example we want to do some linear algebra using Eigen which is a nice header-only library. Any chance to compile it on the target system?
user#ancient:~ $ uname -a
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown
user#ancient:~ $ gcc --version
egcs-2.91.66
Maybe not... So let's compile it on a current system. Below are my attempts, mainly failed ones. Any more ideas very welcome.
Compile with -m32 -march=i386
user#ancient:~ $ ./a.out
BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed!
Compile with -m32 -march=i386 -static: Runs on all fairly recent kernel versions but fails if they are slightly older with the well known error message
user#ancient:~ $ ./a.out
FATAL: kernel too old
Segmentation fault
This is a glibc error which has a minimum kernel version it supports, e.g. kernel 2.6.4 on my system:
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, for GNU/Linux 2.6.4, not stripped
Compile glibc myself with support for the oldest kernel possible. This post describes it in more detail but essentially it goes like this
wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.bz2
tar -xjf glibc-2.14.tar.bz2
cd glibc-2.14
mkdir build; cd build
../configure --prefix=/usr/local/glibc_32 \
--enable-kernel=2.0.0 \
--with-cpu=i486 --host=i486-linux-gnu \
CC="gcc -m32 -march=i486" CXX="g++ -m32 -march=i486"
make -j 4
make intall
Not sure if the --with-cpu and --host options do anything, most important is to force the use of compiler flags -m32 -march=i486 for 32-bit builds (unfortunately -march=i386 bails out with errors after a while) and --enable-kernel=2.0.0 to make the library compatible with older kernels. Incidentially, during configure I got the warning
WARNING: minimum kernel version reset to 2.0.10
which is still acceptable, I suppose. For a list of things which change with different kernels see ./sysdeps/unix/sysv/linux/kernel-features.h.
Ok, so let's link against the newly compiled glibc library, slightly messy but here it goes:
$ export LIBC_PATH=/usr/local/glibc_32
$ export LIBC_FLAGS=-nostdlib -L${LIBC_PATH} \
${LIBC_PATH}/crt1.o ${LIBC_PATH}/crti.o \
-lm -lc -lgcc -lgcc_eh -lstdc++ -lc \
${LIBC_PATH}/crtn.o
$ g++ -m32 -static prog.o ${LIBC_FLAGS} -o prog
Since we're doing a static compile the link order is important and may well require some trial and error, but basically we learn from what options gcc gives to the linker:
$ g++ -m32 -static -Wl,-v file.o
Note, crtbeginT.o and crtend.o are also linked against which I didn't need for my programmes so I left them out. The output also includes a line like --start-group -lgcc -lgcc_eh -lc --end-group which indicates inter-dependence between the libraries, see this post. I just mentioned -lc twice in the gcc command line which also solves inter-dependence.
Right, the hard work has paid off and now I get
$ file ./prog
./prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, for GNU/Linux 2.0.10, not stripped
Brilliant I thought, now try it on the old system:
user#ancient:~ $ ./prog
set_thread_area failed when setting up thread-local storage
Segmentation fault
This, again, is a glibc error message from ./nptl/sysdeps/i386/tls.h. I fail to understand the details and give up.
Compile on the new system g++ -c -m32 -march=i386 and link on the old. Wow, that actually works for C and simple C++ programmes (not using C++ objects), at least for the few I've tested. This is not too surprising as all I need from libc is printf (and maybe some maths) of which the interface hasn't changed but the interface to libstdc++ is very different now.
Setup a virtual box with an old linux system and gcc version 2.95. Then compile gcc version 4.x.x ... sorry, but too lazy for that right now ...
???
Have found the reason for the error message:
user#ancient $ ./prog
set_thread_area failed when setting up thread-local storage
Segmentation fault
It's because glibc makes a system call to a function which is only available since kernel 2.4.20. In a way it can be seen as a bug of glibc as it wrongly claims to be compatible with kernel 2.0.10 when it requires at least kernel 2.4.20.
The details:
./glibc-2.14/nptl/sysdeps/i386/tls.h
[...]
/* Install the TLS. */ \
asm volatile (TLS_LOAD_EBX \
"int $0x80\n\t" \
TLS_LOAD_EBX \
: "=a" (_result), "=m" (_segdescr.desc.entry_number) \
: "0" (__NR_set_thread_area), \
TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \
[...]
_result == 0 ? NULL \
: "set_thread_area failed when setting up thread-local storage\n"; })
[...]
The main thing here is, it calls the assembly function int 0x80 which is a system call to the linux kernel which decides what to do based on the value of eax, which is set to
__NR_set_thread_area in this case and is defined in
$ grep __NR_set_thread_area /usr/src/linux-2.4.20/include/asm-i386/unistd.h
#define __NR_set_thread_area 243
but not in any earlier kernel versions.
So the good news is that point "3. Compiling glibc with --enable-kernel=2.0.0" will probably produce executables which run on all linux kernels >= 2.4.20.
The only chance to make this work with older kernels would be to disable tls (thread-local storage) but which is not possible with glibc 2.14, despite the fact it is offered as a configure option.
The reason you can't compile it on the original system likely has nothing to do with kernel version (it could, but 2.2 isn't generally old enough for that to be a stumbling block for most code). The problem is that the toolchain is ancient (at the very least, the compiler). However, nothing stops you from building a newer version of G++ with the egcs that is installed. You may also encounter problems with glibc once you've done that, but you should at least get that far.
What you should do will look something like this:
Build latest GCC with egcs
Rebuild latest GCC with the gcc you just built
Build latest binutils and ld with your new compiler
Now you have a well-built modern compiler and (most of a) toolchain with which to build your sample application. If luck is not on your side you may also need to build a newer version of glibc, but this is your problem - the toolchain - not the kernel.
When building C++ projects using make on OSX 10.6, I have determined that the preprocessor definition __LP64__ seems to be always automatically set by the compiler (i.e., it is not defined in any header file) (see Where is __LP64__ defined for default builds of C++ applications on OSX 10.6?). This leads to the question: Is it even possible to build a 32-bit application on OSX 10.6 that targets (and runs) on another OSX 10.6 system?
I have heard that OSX 10.6 is always a 64-bit OS - that it's not even possible to run OSX 10.6 as a 32-bit operating system. If this is the case, it would make sense that it is impossible to build a 32-bit application on OSX 10.6 that will run on another OSX 10.6 system.
I need to know this so I can know whether I'm building a 64-bit application or not (I have been attempting to build my current project as a 32-bit application, since the corresponding Windows version is also being built as 32-bit - but perhaps I need to enable all 64-bit flags and build the OSX 10.6 version of this application as a full-fledged 64-bit application).
Yes, it is perfectly possible to do that. One limited demonstration:
$ tar -xf Packages/range-1.14.tgz
$ cd range-1.14
$ ls
COPYING Makefile README gpl-3.0.txt range.c range.mk stderr.c stderr.h
$ rmk CC='gcc -m32'
gcc -m32 -g -c stderr.c
gcc -m32 -g -c range.c
gcc -m32 -o range -g stderr.o range.o
$ file range
range: Mach-O executable i386
$ rmk -u CC='gcc -m64'
gcc -m64 -g -c stderr.c
gcc -m64 -g -c range.c
gcc -m64 -o range -g stderr.o range.o
$ file range
range: Mach-O 64-bit executable x86_64
$
rmk -u is equivalent to (GNU) make -B. This GCC is my home-built 4.6.0. You can do more with the Apple-provided versions of GCC - like cross-compiling and/or universal builds.
Mac OS X 10.6 runs perfectly well on 32-bit Intel Macs. It dropped support for PowerPC. Future versions of Mac OS X (cough cough NDA cough) may or may not drop support for 32-bit Intel Macs, requiring a 64-bit system.
Even a 64-bit Mac, however, has implicit support for running 32-bit processes, and GCC can cross-compile for i386 targets (or PPC/PPC64/ARMv6/ARMv7 targets.) You must make sure the desired architectures are specified in your build flags however, or it will default to the native architecture (i.e. x86_64.)
If you use the xcodebuild command-line utility and pass it the path to an Xcode project bundle, it will automatically use the build settings in the project when calling on GCC. There's rarely a need to use GCC directly on Mac OS X unless you're compiling from generic *NIX sources.
If you tell us why you're using make on Mac OS X, we may be able to give you more specific advice, but the preferred command-line compilation method on Mac OS X is still xcodebuild.