How can I install GCC and other developer tools inside QEMU virtual machine that only has BusyBox? - linux

I download Linux kernel source code, successfully compiled it and run it with BusyBox in QEMU.
Because of BusyBox, I can use some frequently-used tools, such as vi,ls,cp,cat, etc.
But when I try to compile a simple "hello world" C/C++ program, I get gcc: not found.
In addition, I can't make a new Linux module by make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules inside QEMU.
I googled a lot, still can't figure it out.
So my question is: how can I install common developer tools like gcc, make, etc. inside my bare-bones QEMU VM that is running my custom Linux kernel (and not a standard distribution)?

I see that you are trying to compile some program (or module) to use it inside your QEMU machine, but you do not have a compiler toolchain installed in the machine itself. You have a couple of options:
Probably the easiest: since you already compiled the kernel that you are using for QEMU externally (in your host machine), you can easily also compile anything else this way. For modules, just pointing make to the same kernel source directory where you built the VM kernel should suffice. Once compiled you can then copy them inside the VM disk/image like you did for busybox.
You can download and compile your own GCC from source (always on the host), and then install it inside the QEMU virtual machine. This is usually done by mounting the VM disk (QEMU image or whatever you are using) somewhere (e.g. /mnt/my-qemu-disk) and then configuring GCC with --prefix=/mnt/my-qemu-disk/usr/local, building and installing it with make install. This and other stuff is explained in this documentation page.
Once you have GCC installed inside the machine, you should be able to use it as you normally do. You can now use it to compile GNU Make inside the VM, or you can just compile outside in the same way.
For complex stuff like building kernel modules you will probably also need to build and install GNU binutils in the machine, again either from the inside with the GCC you just installed or from the outside.

Related

how to make excutable files based on source codes

I write some programs on linux with C
I want to run these programs on many remote computers, which are installed with fedora or ubuntu
I compiled the program with gcc on local machine, however the excutable file is not workable on remote machines.
for example: I use
gcc -o udp_server udp_server.c
on local machine to get a excutable binary file udp_server and then I copy it to a remote machine and run it there, the error is:
-bash: ./udp_server: /lib64/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory
the local machine: fedora
Fedora release 16 (Verne)
Kernel \r on an \m (\l)
3.6.10-2.fc16.x86_64 GNU/Linux
the remote machine:
Fedora release 12 (Constantine)
Kernel \r on an \m (\l)
2.6.32-36.onelab.x86_64 GNU/Linux
on these remote machines, there are no gcc compiler
so I hope I can make some excutable files so that they can be executed on those remote machines
so what kind of excutable files should I make, and how to make them?
any recommenation tools or procedures?
thanks!
To run a program written in C, you must first compile it to produce an executable file. On Linux, the C compiler is typically the "Gnu C Compiler", or gcc.
If you compile a C program on Linux, it should usually run on any other Linux computer. However, a few conditions must be met for this to work:
A compiled executable is compiled for a specific processor architecture. For example, if you compile for x86-x64, the program will not run on x86 or PowerPC.
If the program uses shared libraries, these must be installed on the target system. The C library, "libc" is installed everywhere, other libraries may not be.
As to how to compile: For a simple program, you can invoke gcc directly. For more complex programs, some build tool is advisable. There are many to choose from; two popular choices are GNU make (the traditional solution), and CMake.
To distribute the program: If it is only a single executable, you can just copy this executable around. If the program consists of multiple files (images, data files, etc.), you should package it as a software package. This allows users to install it using a package manager such as RPM or dpkg. How to do this is explained in various packaging guides for the different Linux distributions.
Finally, a piece of advice: You seem to know very little about software development in general and in C in particular. Consider reading some tutorial on programmin in C - this will answer these (and many other) questions. There are countless books and online tutorials - I can recommend "The C book", by gbdirect.
The issue you see is you are missing a dynamic library on the target machine. To see which libraries you need you need to use "ldd" program. Example (I just execute it against standard program "test" which is in every single linux distribution):
$ ldd /usr/bin/test
linux-vdso.so.1 => (0x00007fff5fdfe000)
libc.so.6 => /lib64/libc.so.6 (0x00000032d0600000)
/lib64/ld-linux-x86-64.so.2 (0x00000032cfe00000)
On Fedora and RHEL you can find which RPM package you want to install using the following command
$ rpm -q --whatprovides /lib64/ld-linux-x86-64.so.2
glibc-2.16-28.fc18.x86_64
And then you need to install it:
$ yum -y install glibc-2.16-28.fc18.x86_64
I dont use Ubuntu / Debian, not sure how to do this. Please note that on 32bit systems libraries for 64bits are not avaiable, but on 64bit systems these libraries have usualla i686 tag and are installable.
Usually, you can execute your program on different machines as long as you keep the architecture. E.g. you cannot execute 64bit program on a 32bit machine, and also vice versa (you can workaround this by installing 32bit libs but thats maybe too difficult).
If you have different distributions, or different versions of same linux distribution, this might be problem - you need to make sure you have all the dependencies in the same major versions.
Or you can link libraries statically which is not usual in the linux world at all, but you can do this. Learn how to use GCC and then you will find out how to do that.

How do I configure Qt for cross-compilation from Linux to Windows target?

I want to cross compile the Qt libraries (and eventually my application) for a Windows x86_64 target using a Linux x86_64 host machine. I feel like I am close, but I may have a fundamental misunderstanding of some parts of this process.
I began by installing all the mingw packages on my Fedora machine and then modifying the win32-g++ qmake.conf file to fit my environment. However, I seem to be getting stuck with some seemingly obvious configure options for Qt: -platform and -xplatform. Qt documentation says that -platform should be the host machine architecture (where you are compiling) and -xplatform should be the target platform for which you wish to deploy. In my case, I set -platform linux-g++-64 and -xplatform linux-win32-g++ where linux-win32-g++ is my modified win32-g++ configuration.
My problem is that, after executing configure with these options, I see that it invokes my system's compiler instead of the cross compiler (x86_64-w64-mingw32-gcc). If I omit the -xplatform option and set -platform to my target spec (linux-win32-g++), it invokes the cross compiler but then errors when it finds some Unix related functions aren't defined.
Here is some output from my latest attempt: http://pastebin.com/QCpKSNev.
Questions:
When cross-compiling something like Qt for Windows from a Linux host, should the native compiler ever be invoked? That is, during a cross compilation process, shouldn't we use only the cross compiler? I don't see why Qt's configure script tries to invoke my system's native compiler when I specify the -xplatform option.
If I'm using a mingw cross-compiler, when will I have to deal with a specs file? Spec files for GCC are still sort of a mystery to me, so I am wondering if some background here will help me.
In general, beyond specifying a cross compiler in my qmake.conf, what else might I need to consider?
Just use M cross environment (MXE). It takes the pain out of the whole process:
Get it:
$ git clone https://github.com/mxe/mxe.git
Install build dependencies
Build Qt for Windows, its dependencies, and the cross-build tools;
this will take about an hour on a fast machine with decent internet access;
the download is about 500MB:
$ cd mxe && make qt
Go to the directory of your app and add the cross-build tools to the PATH environment variable:
$ export PATH=<mxe root>/usr/bin:$PATH
Run the Qt Makefile generator tool then build:
$ <mxe root>/usr/i686-pc-mingw32/qt/bin/qmake && make
You should find the binary in the ./release directory:
$ wine release/foo.exe
Some notes:
Use the master branch of the MXE repository; it appears to get a lot more love from the development team.
The output is a 32-bit static binary, which will work well on 64-bit Windows.
(This is an update of #Tshepang's answer, as MXE has evolved since his answer)
Building Qt
Rather than using make qt to build Qt, you can use MXE_TARGETS to control your target machine and toolchain (32- or 64-bit). MXE started using .static and .shared as a part of the target name to show which type of lib you want to build.
# The following is the same as `make qt`, see explanation on default settings after the code block.
make qt MXE_TARGETS=i686-w64-mingw32.static # MinGW-w64, 32-bit, static libs
# Other targets you can use:
make qt MXE_TARGETS=x86_64-w64-mingw32.static # MinGW-w64, 64-bit, static libs
make qt MXE_TARGETS=i686-w64-mingw32.shared # MinGW-w64, 32-bit, shared libs
# You can even specify two targets, and they are built in one run:
# (And that's why it is MXE_TARGET**S**, not MXE_TARGET ;)
# MinGW-w64, both 32- and 64-bit, static libs
make qt MXE_TARGETS='i686-w64-mingw32.static x86_64-w64-mingw32.static'
In #Tshepang's original answer, he did not specify an MXE_TARGETS, and the default is used. At the time he wrote his answer, the default was i686-pc-mingw32, now it's i686-w64-mingw32.static. If you explicitly set MXE_TARGETS to i686-w64-mingw32, omitting .static, a warning is printed because this syntax is now deprecated. If you try to set the target to i686-pc-mingw32, it will show an error as MXE has removed support for MinGW.org (i.e. i686-pc-mingw32).
Running qmake
As we changed the MXE_TARGETS, the <mxe root>/usr/i686-pc-mingw32/qt/bin/qmake command will no longer work. Now, what you need to do is:
<mxe root>/usr/<TARGET>/qt/bin/qmake
If you didn't specify MXE_TARGETS, do this:
<mxe root>/usr/i686-w64-mingw32.static/qt/bin/qmake
Update: The new default is now i686-w64-mingw32.static
Another way to cross-compile software for Windows on Linux is the MinGW-w64 toolchain on Archlinux. It is easy to use and maintain, and it provides recent versions of the compiler and many libraries. I personally find it easier than MXE and it seems to adopt newer versions of libraries faster.
First, you will need an arch-based machine (virtual machine or docker container will suffice). It does not have to be Arch Linux, derivatives will do as well. I used Manjaro Linux.
Most of the MinGW-w64 packages are not available at the official Arch repositories, but there is plenty in AUR. The default package manager for Arch (Pacman) does not support installation directly from AUR, so you will need to install and use an AUR wrapper like yay or yaourt. Then installing MinGW-w64 version of Qt5 and Boost libraries is as easy as:
yay -Sy mingw-w64-qt5-base mingw-w64-boost
#yaourt -Sy mingw-w64-qt5-base mingw-w64-qt5-boost #if you use yaourt
This will also install the MinGW-w64 toolchain (mingw-w64-gcc) and other dependencies.
Cross-compiling a Qt project for windows (x64) is then as simple as:
x86_64-w64-mingw32-qmake-qt5
make
To deploy your program you will need to copy corresponding dlls from /usr/x86_64-w64-mingw32/bin/. For example, you will typically need to copy /usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/qwindows.dll to program.exe_dir/platforms/qwindows.dll.
To get a 32bit version you simply need to use i686-w64-mingw32-qmake-qt5 instead. Cmake-based projects work just as easily with x86_64-w64-mingw32-cmake.
This approach worked extremely well for me, was the easiest to set-up, maintain, and extend.
It also goes well with continuous integration services. There are docker images available too.
For example, let's say I want to build QNapi subtitle downloader GUI. I could do it in two steps:
Start the docker container:
sudo docker run -it burningdaylight/mingw-arch:qt /bin/bash
Clone and compile QNapi
git clone --recursive 'https://github.com/QNapi/qnapi.git'
cd qnapi/
x86_64-w64-mingw32-qmake-qt5
make
That's it! In many cases, it will be that easy. Adding your own libraries to the package repository (AUR) is also straightforward. You would need to write a PKBUILD file, which is as intuitive as it can get, see mingw-w64-rapidjson, for example.
Ok I think I've got it figured out.
Based in part on https://github.com/mxe/mxe/blob/master/src/qt.mk and https://www.videolan.org/developers/vlc/contrib/src/qt4/rules.mak
It appears that "initially" when you run configure (with -xtarget, etc.), it configures then runs your "hosts" gcc to build the local binary file ./bin/qmake
./configure -xplatform win32-g++ -device-option CROSS_COMPILE=$cross_prefix_here -nomake examples ...
then you run normal "make" and it builds it for mingw
make
make install
so
yes
only if you need to use something other than msvcrt.dll (its default). Though I have never used anything else so I don't know for certain.
https://stackoverflow.com/a/18792925/32453 lists some configure params.
In order to compile Qt, one must run it's configure script, specifying the host platform with -platform (e.g. -platform linux-g++-64 if you're building on a 64-bit linux with the g++ compiler) and the target platform with -xplatform (e.g. -xplatform win32-g++ if you're cross compiling to windows).
I've also added this flag:
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32-
which specifies the prefix of the toolchain I'm using, which will get prepended to 'gcc' or 'g++' in all the makefiles that are building binaries for windows.
Finally, you might get problems while building icd, which apparently is something that is used to add ActiveX support to Qt. You can avoid that by passing the flag -skip qtactiveqt to the configure script. I've got this one out of this bug report: https://bugreports.qt.io/browse/QTBUG-38223
Here's the whole configure command I've used:
cd qt_source_directory
mkdir my_build
cd my_build
../configure \
-release \
-opensource \
-no-compile-examples \
-platform linux-g++-64 \
-xplatform win32-g++ \
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \
-skip qtactiveqt \
-v
As for yout questions:
1 - Yes. The native compiler will be called in order to build some tools that are needed in the build process. Maybe things like qconfig or qmake, but I'm not entirely sure which tools, exactly.
2 - Sorry. I have no idea what specs files are in the context of compilers =/ . But as far as I know, you wouldn't have to deal with that.
3 - You can specify the cross compiler prefix in the configure command line instead of doing it in the qmake.conf file, as mentioned above. And there's also that problem with idc, whose workaround I've mentioned as well.

How to debug my Cross compiled Linux Kernel?

I 've cross compiled a Linux Kernel (for ARM on i686 - using Cross-LFS).
Now I'm trying to boot this Kernel using QEMU.
$ qemu-system-arm -m 128 -kernel /mnt/clfs-dec4/boot/clfskernel-2.6.38.2 --nographic -M versatilepb
Then, it shows this line and waits for infinite time !!
Uncompressing Linux... done, booting the kernel.
So, I want to debug the kernel, so that I can study what exactly is happening.
I'm new to these kernel builds, Can someone please help me to debug my custom built kernel as it is not even showing anything after that statement. Is there any possibility of the kernel being broken? ( I dont think so, b'se it didnot give any error while compiling )
And my aim is to generate a custom build very minimal Linux OS. Any suggestions regarding any tool-chains etc which would be easy & flexible depending on my requirements like drivers etc.,
ThankYou
You can use GDB to debug your kernel with QEMU you can use -s -S options. If you want a simple and reliable toolchain, you can use ELDK from DENX (http://www.denx.de/wiki/DULG/ELDK).
You can install it like this (It's not the last version, but you got the idea):
wget http://ftp.denx.de/pub/eldk/4.2/arm-linux-x86/iso/arm-2008-11-24.iso
sudo mkdir -p /mnt/cdrom (if necessary)
sudo mount -o loop arm-2008-11-24.iso /mnt/cdrom
/mnt/cdrom/install -d $HOME/EMBEDDED_TOOLS/ELDK/
The command above should install the toolchain under $HOLE/EMBEDDED_TOOLS/ELDK (modify it if you need)
echo "export PATH=$PATH:$HOME/EMBEDDED_TOOLS/ELDK/ELDK42/usr/bin" >> $HOME/.bashrc
You can then see the version of your ARM toolchain like this:
arm-linux-gcc -v
You can test a hello_world.c program like this:
arm-linux-gcc hello_world.c -o hello_world
And you type: file hello_wrold to see the target architecture of the binary, it should be something like this:
hello_wrold: ELF 32-bit LSB executable, ARM, version 1 (SYSV)
Now if you want to compile a production kernel, you need to optimize it (i suggest using busybox) and if you want just one for testing now, try this steps:
Create a script to set your chain tool set_toolchain.sh:
#! /usr/bin/sh
PATH=$PATH:$HOME/EMBEDDED_TOOLS/ELDK/ELDK42/usr/bin
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabi-
export PATH ARCH CROSS_COMPILE
And run your script (source ./set_toolchain.sh)
Download a linux kernel and unzip it (Let's assume 2.6.x, it's an old kernel, but there are a lot of chances that it work without compilation errors).
Inside your unzipped kernel:
cd ~/linux-2.6.29/arch/arm/configs
make versatile_defconfig
Here we use versatile chip, you may need to use make menuconfig to modify the option OABI and set it to ARM EABI, this option is under Kernel features menu
After all this steps, you can compile you kernel:
make
if you want verbose compilation make v=1
After this you got your kernel under arch/arm/boot/zImage.
Hope this help.
Regards.
I would suggest to build your kernel by activating the option in the section Kernel hacking of your configuration file.
Then you may use kdb or kgdb which is easier to use but requires another machine running gdb.
`
You can also connect Qemu and GDB. Qemu has the -s and -S options that run a GDB server and allow you to connect to it via TCP to localhost:1234. Then you can load your kernel image (the unzipped one) in GDB and see how far your kernel boots.

Compiled gcc4.4.6 on one machine, how to let another machine use it?

I built gcc 4.4.6 (to use CUDA) on a fast server, it takes about 10 min. However, on my own desktop, it takes kinda for ever to compile.
So both machines are 64 bit Linux, although 1 is Ubuntu while the other is Arch Linux. Arch Linux has new kernel version.
So on the server, I installed the built gcc-4.4.6 to /opt. And I just copy /opt/gcc-4.4.6 to my PC's /opt/gcc-4.4.6.
em, seems like it doesn't quite work, when I tried
./x86_64-unknown-linux-gnu-gcc ~/Development/c/hello/hello.c
it shows
x86_64-unknown-linux-gnu-gcc: error trying to exec 'cc1': execvp: No such file or directory
So what can I do now?
Thanks,
Alfred
If the systems are similar enough, you could compile GCC on the big machine (don't forget that GCC needs to be configured and built in a directory outside of its source tree), then run make -j3 all and then make install DESTDIR=/tmp/gccinst/ and copy that /tmp/gccinst directory to your small machine, and finally copy it into the root filesystem (on the small machine).
However, GCC 4.4.6 is quite old today, if you are compiling GCC try to compile GCC 4.6.2 (or 4.6.1 at least).
And (shameless plug for my work) if you compile a GCC 4.6, please enable plugins on it, then you might try the GCC MELT [meta-] plugin (MELT is a high level domain specific language to ease the development of GCC extensions).

Installing gcc on linux without c compiler

How can I install gcc on a system that have not any c compiler?
this system is a linux base firewall and have not any c compiler.
I guess you a have an appliance running Linux and shell-access, but neither a package manager nor a compiler is installed.
So, you need to cross-compile gcc and the whole toolchain (at least binutils) - this is quite simple, because the ./configure scripts of gcc, binutils, gdb etc. support cross-compiling with the --target= option. So all you have to do is to find out the target architecure (uname helps) and then download, unpack the gcc sources on a linux-host and run ./configure --target=$YOUR_TARGET.
With this, you now can build a cross-compiler gcc - this still runs on your host, but produces binaries for your target (firewall appliances).
This may already be sufficient for you, a typical desktop PC is much faster than a typical appliance, so it may make sense to compile everything you need on the Desktop PC with the cross-compiler and cross-binutils.
But if you really wish to do so, you can now also use your cross-compiler to compile a gcc running on your target (set this as --host= option) and compiling for your target (set this as --target option).
You can find details about allowed host/targets and examples in the gcc documentation: http://gcc.gnu.org/install/specific.html.
It depends on the distribution, if it's based on debian or some other of the big ones you can install gcc through apt-get or similar tool.
If it's a more basic system you need to compile gcc yourself on another computer and copy it over. It will be easiest if you have another computer with the same architecture (i386, arm or x86_64 for example).
I think that you might want to compile it statically also, so that you don't have dependencies on external libraries.
How do you plan to get all the source code needed for GCC loaded onto your machine? Could you mount the ISO image onto this machine and install from there?
Since you are using Endian Firewall, see "Building a development box" at the following link:
http://alumnus.caltech.edu/~igormt/endian/tips.html
If it's a debian based distribution, you can use
sudo apt-get install gcc
Note: maybe you must change "gcc" by a specific version of the debian package.

Resources