buildrpm fails when cross building C++ for 32-bit ARM (from x86-64) - raspberry-pi

I successfully compiled C++ code for a Raspberry Pi (ARM architecture).
Such binaries have a file command return the following :
usr/local/company/product/this: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=9fe73c254b317e239758e4445d12b8441a3cb13e, not stripped
I now wish to generate RPM packages (not .deb packages, real .RPM packages!).
I've tried many --target and spec's file buildarch combinations without much success.
Tried armv7l, arm-linux-gnueabihf, arm-linux ...
Same result is returned by rpmbuild :
Building target platforms: arm-unknown-linux
Building for target arm-unknown-linux
error: No compatible architectures found for build
I'm compiling from an x86_64 Ubuntu. The destination architecture is arm-linux-gnueabihf.
I call rpmbuild as follow :
rpmbuild -bb --target armv7l myfile.spec

On my RHEL 7 computer, the /usr/lib/rpm/rpmrc includes several ARM variants:
armv3l, armv4b, armv4l, armv4tl, armv5tel, armv5tejl, armv6l, armv7l, armv7hl, armv7hnl. I guess your file will have a similar selection, and thus include the armv7l option you selected.
I found that for cross-packaging, running rpmbuild --target _target_ was not enough. I also had to use a setarch _target_ wrapper around the build command.

You may need to add your arm architecture (displayed by uname -m) to /usr/lib/rpm/rpmrc configuration.

GOARCH=amd64 or arm64
used the command:
rpmbuild ... --define="GOARCH ${GOARCH}"
spec file should include this content
%if %{GOARCH} == "amd64"
BuildArch: x86_64
%endif
%if %{GOARCH} == "arm64"
BuildArch: aarch64
%endif

Related

C++ wxWidgets: cross compilation from Raspberry Pi 3

I have a C++ application that uses WxWidgets. It compiles perfectly with g++ on my computer.
However I need to run the application on a Raspberry Pi 3. Compiling directly on Raspi takes almost an hour.
So I want to do a cross compilation: compile it on my computer and copy the executable to raspberry.
I tried to follow a tutorial, however the generated file is an "x86-64" file:
http://yasriady.blogspot.com/2015/10/how-to-build-wxwidgets-for-raspberry-pi.html
My computer:
Ubuntu 20.04.2 LTS;
g++ 9.3.0;
wxWidgets v3.1.5.0;
build flags for my computer: CC_FLAGS=-std=c++17 -w -c -rdynamic -W wx-config --cxxflags --libs --gl-libs geos-config --cflags -lgeos -lglut -lGLU -lGL -lm -lGLEW .
Should I re-install wxWidgets for arm? I'm new to cross-compilation
Thank you so much
I already have wxWidgets installed and compiling for x86. Afterwards, I installed wxWidgets for arm-linux following the tutorial.
When I run "make for the examples from the samples folder, the generated file is for x86.
Maybe "make" is compiling using the x86 compiler, not the newly installed arm compiler.
You should be able to cross-compile for RPi without any problems, double check that you've specified the correct --host option and didn't get any errors from configure (if you did, look at config.log to see why).

How do I build 32-bit binaries with Red Hat Developer Toolset?

I can't find any documentation whatsoever on how to target 32-bit with Red Hat Developer Toolset (version 9.0 in this case running on CentOS 7). The release notes mention:
Generation and manipulation of 32-bit binaries is also supported
It also ships the needed 32-bit libraries in:
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/32/
However, building fails. Example trying to build a minimal int main() {} program:
$ scl enable devtoolset-9 'g++ -m32 tst.cpp'
/opt/rh/devtoolset-9/root/usr/libexec/gcc/x86_64-redhat-linux/9/ld: skipping incompatible /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/libstdc++_nonshared.a when searching for -lstdc++_nonshared
/opt/rh/devtoolset-9/root/usr/libexec/gcc/x86_64-redhat-linux/9/ld: cannot find -lstdc++_nonshared
collect2: error: ld returned 1 exit status
The library it fails to find actually exists though:
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/32/libstdc++_nonshared.a
No amount of -L flags fixes it (and it would be the wrong solution anyway; the linker should not even be attempting to load 64-bit libraries in -m32 mode.)
What am I missing here?
I guess you didn't notice that /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/32/libstdc++_nonshared.a is quite likely a dangling symlink:
$ file /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/32/libstdc++_nonshared.a
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/32/libstdc++_nonshared.a: broken symbolic link to `../../../i686-redhat-linux/9/libstdc++_nonshared.a'
$
The destination file /opt/rh/devtoolset-9/root/usr/lib/gcc/i686-redhat-linux/9/libstdc++_nonshared.a is however unfortunately not provided by any CentOS package (but it should be in devtoolset-9-libstdc++-devel.i686). Thus it's likely a CentOS-specific packaging mistake as RHEA-2019:4134 provides the questioned package devtoolset-9-libstdc++-devel-9.1.1-2.6.el7.i686.rpm for Red Hat Enterprise Linux 7 including the desired file (explicitly verified by yum install /opt/rh/devtoolset-9/root/usr/lib/gcc/i686-redhat-linux/9/libstdc++_nonshared.a on RHEL 7).

Building only gcc using yocto

I was trying to build only gcc using yocto. I tried with "bitbake-layers show-recipes" it was showing multiple recipes for gcc, similarly for bitbake -s.
#bitbake-layers show-recipes
gcc:
meta 4.8.2
gcc-cross:
meta 4.8.2
gcc-cross-canadian-arm:
meta 4.8.2
gcc-cross-initial:
meta 4.8.2
gcc-crosssdk:
meta 4.8.2
gcc-crosssdk-initial:
meta 4.8.2
gcc-runtime:
meta 4.8.2
gccmakedep:
meta 1:1.0.2
#bitbake -s
gcc :4.8.2-r0
gcc-cross :4.8.2-r0
gcc-cross-canadian-arm :4.8.2-r0
gcc-cross-initial :4.8.2-r0
gcc-crosssdk :4.8.2-r0
gcc-crosssdk-initial :4.8.2-r0
gcc-runtime :4.8.2-r0
gccmakedep 1:1.0.2-r3
Please guide me to understand why there are multiple recipes related to gcc and which one I have to build.
In yocto, is there one to one match for recipe and package. i.e for creating each package there is a corresponding only one recipe?
To explain each one in turn:
gcc is the recipe for gcc that runs on the target machine itself.
gcc-cross is the cross-compiler that the build system uses. If you build any recipe for the target that needs to be compiled with gcc, this is what will be used to compile that.
gcc-cross-canadian- is the final relocatable cross-compiler for the SDK, in this case for the ARM architecture.
gcc-crosssdk is an intermediate step in producing gcc-cross-canadian.
the *-initial are the initial versions of the compiler required to bootstrap the toolchain separately for the standard cross-compiler and for the SDK.
gcc-runtime builds the runtime components that come as part of gcc (e.g. libstdc++).
gccmakedep isn't really part of gcc itself, it's a script that comes as part of the X11 utilities that some projects need to determine dependencies for each source file.
When you say "you only need to build gcc", it's not entirely clear what you mean, but I suspect it's either gcc for the target (in which case it's "gcc", though I suspect you'll probably need more than that - packagegroup-core-buildessential may be what you want) or you want a cross-compiler you can install separately in which case you probably ought to bitbake meta-toolchain or bitbake -c populate_sdk imagename. That'll contain more than just gcc but it's likely gcc alone isn't going to be enough anyway.
GCC is a huge project. Maybe this recipe could help you understand GCC and Yocto a little bit better. The following information is some information paraphrase from "Embedded Linux Projects Using Yocto Project Cookbook" by Alex Gonzalez
GNU toolchain contains the following components:
Assembler (GNU as): part of the binutils package
Linker (GNU Id):
part of the binutils package
Compiler (GNU gcc): support for C, C++,
Java, Ada, Fortran, and Objective C
Debugger (GNU gdb): GNU debugger
Binary file tools (objdump, nm, objcopy, readelf, strip, and so on):
these are part of the binutils package
These components are enough to build bare metal applications
bootloaders like u-boot, Linux Kernel because they do not need C
library and they implement C library functions they need.
POSIX-compliant C library is needed for LInux user space applications.
glibc is the default C library used in the Yocto Project.
On Embedded Systems, we need a cross-compilation toolchain. We build
in a host computer but run the result binarines on the target which is
usually different architecture. There are several types of toolchains
based on build machine, target machine.
The most common combinations are:
Native: An example of this is an x86 machine running a toolchain that >has also been built on an x86 machine
producing binaries to run on an x86 machine. This is common in desktop
computers.
Cross-compilation: This is the most common on embedded
systems; for example, an x86 machine running a toolchain that has also
been built on an x86 machine but producing binaries to run on a
different architecture, like ARM.
Cross-native: This is typically the
toolchain running on targets. An example of this is where a toolchain
has been built on an x86 machine but runs on ARM and produces
Canadian: Rarely seen, this is where the build, host, and target
machines are all different.

beaglebone a6 setting cross compile - cannot execute binary. Wrong abi version?

I am trying to setup Eclipse to build binaries for beaglebone a6. On bb I have Debian stable wheezy and on my PC I have Arch installed. Using gcc linaro 4.9 but it won't work:
gdbserver :2345 /home/dragonn/bbcpp;exit
dragonn#debian:~$ echo $PWD'>'
/home/dragonn>
dragonn#debian:~$ gdbserver :2345 /home/dragonn/bbcpp;exit
Process /home/dragonn/bbcpp created; pid = 2158
Cannot exec /home/dragonn/bbcpp: No such file or directory.
Child exited with status 127
No program to debug. GDBserver exiting.
logout
file command shows this:
root#debian:/home/dragonn# file bbcpp
bbcpp: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.4.104, BuildID[sha1]=0xb9518d4e4550dfa8ac66db0625ed514460bc70d7, not stripped
root#debian:/home/dragonn# file a.out
a.out: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x2dc9c698a5186e4ca4ca78c9d698ff92ecabc377, not stripped
bbcpp is complied via Eclipse and a.out directly on bb. I think the ABI version of my binary is to high? I am right? How can I change that?

How to make an rpm spec that installs libraries to /usr/lib xor /usr/lib64 based on arch?

I'm working on an RPM spec for centos and it needs to install the shared libraries to /usr/lib64 if the arch is 64 bit and /usr/lib otherwise?
That's not how it's supposed to work. It's not the kernel type that should determine where your libraries go, but the library types themselves - 64-bit .so's go to /usr/lib64, 32-bit to /usr/lib.
You can't have one RPM contain both architectures, the result should be 2 different RPMs, and if I am not mistaken RPM macros should resolve this for you if you use %_libdir.
The path a library is installed into would be determined by the type of package you are creating.
It would appear that for Redhat (and CentOS) 6, the RPM macro already injects the —libdir=/usr/lib64.
This is how RH/CentOS 6 sets the lib64 which is through RPM SPEC file.
On RH/CentOS 6, doing automake/configure does not (and according to RH, will not) do the library prefix to /usr/lib64 in case of x86_64 arch type.
All this has been fixed for RH/CentOS 7 and higher.