Why does my cross-compiling fail? - c

I'm new to Linux programming and I'm trying to compile a c file including the GTK+ library. My file is called test.c and it's supposed to run on Windows computers. I'm using the command:
i586-mingw32msvc-gcc `pkg-config --cflags gtk+-3.0` -o test test.c `pkg-config --libs gtk+-3.0`
I get an awful error, I tried to figure out what went wrong by myself but didn't manage to understand what's going on here.
This is the output:

You're almost certainly running pkg-config with the host metadata files, such output will likely make your cross-compiler, erm, cross.
Try this tutorial, it explains how to do what you want starting with downloading the required GTK+-3.0 win32 binaries, and setting up your linux environment so that pkg-config picks up the target metadata files:
http://www.tarnyko.net/en/?q=node/45
The job of pkg-config is to provide a straightforward way for one program to determine the compiler and linker requirements, and any dependent libraries for a library it uses. It also makes it easier for autoconf (and the user) to determine the presence, version and dependencies of specific packages. Your examples are using:
pkg-config --cflags gtk+-3.0
pkg-config --libs gtk+-3.0
Those will output the compiler and library flags that a program using gtk+-3.0 needs. Assuming you have a native version installed on your system, the default output will be suitable only for your type of system (paths, library names, dependent libraries etc).
The trick with cross-compiling is to have a separate tree of source, .pc (pkg-config meta-data), libraries and header files (for each targeted architecture). When you run pkg-config during configure/compile, you can set PKG_CONFIG_PATH as in the tutorial above so it picks up the correct .pc files for the targeted architecture.
There's a little bear trap here though: PKG_CONFIG_PATH adds to the start of the search path, so it can still fall back to the wrong package details if you have not installed the required software into your target tree, but you have a "native" version installed. You should usually set PKG_CONFIG_LIBDIR instead, this replaces the default path (typically /usr/lib/pkgconfig). That way when you cross-compile something more elaborate that uses autoconf (configure scripts) you (hopefully) get a sensible diagnostic about missing packages, rather than having the wheels come off mid-way through the compile.
For example, I can use this to list just the OpenWRT MIPS packages I have in one cross-compile tree:
WRTROOT=/openwrt/staging_dir/target-mips_r2_uClibc-0.9.32/
PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR=${WRTROOT}/usr/lib/pkgconfig pkg-config --list-all
Unsetting PKG_CONFIG_PATH prevents it finding extra packages in my /usr/local, setting PKG_CONFIG_LIBDIR means it won't find the native system ones.

In addition to setting the PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR variables, it might be necessary to pass --define-prefix to pkg-config:
PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR=/openwrt/staging_dir/target-mips_34kc_eglibc-2.19/usr/lib/pkgconfig pkg-config --define-prefix --cflags libmodbus
-I/openwrt/staging_dir/target-mips_34kc_eglibc-2.19/usr/include/modbus
Otherwise you get the include path on your host system:
PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR=/openwrt/staging_dir/target-mips_34kc_eglibc-2.19/usr/lib/pkgconfig pkg-config --cflags libmodbus
-I/usr/include/modbus
which might work, provided the host system and the cross-compile environment have the same include files installed.

Related

pkg-config: print Requires.private without being recursive

I have a problem which I think I can solve if I manage to get from pkg-config the list in Requires.private without being recursive. First I'll post the problem, and then my try to workaround it.
Problem:
I had a static-only library (let's call it libfoo.a) with no pkg-config files, which I just included as a submodule of my programs. I had to take into account in the program makefile all the dependencies that my library might have, because as a static library, it didn't carry the information of which shared library it depended on. That meant that I had to dinamically link with a lot of libraries in my programs' makefiles, but that worked.
Example:
$(CC) $(OBJS) -o $# -L path/foo/ -l foo `pkg-config --libs opencv gsl ncurses`
It worked, because it could only find a static version of libfoo, and after that it had a list of what libfoo needed (instead of what the program actually needed dinamically).
Now I have improved that library so that it is installed in /usr/local/, provide pkg-config files, and both .a and .so files.
When I link dinamically to my library, everything is fine.
When I try to link statically, if the program doesn't use opencv at all, it is fine (I don't know if it's opencv that is broken when trying to link statically, or that I broke it installing some updates from the testing repo; if I had a clean installation I would know, but I don't). The problem comes when I try to link statically, and some opencv is used. There are some libraries not found, so what I thought as a solution is to replicate what happened before I installed my library.
But now I don't want to hardcode my library's dependencies in my program's makefile, so I use pkg-config.
My try:
Assuming that my program only depends directly on libfoo, and libfoo depends on opencv, gsl and ncurses directly (which my program ignores), this is what I would do:
$(CC) $(OBJS) -o $# -Wl,-Bstatic `pkg-config --libs foo` -Wl,-Bdynamic `pkg-config --static --libs foo`
the first pkg-config is to expose only libfoo to be linked statically, and the second one is to expose libfoo's dependencies to be linked dinamically. But the problem is that I'm exposing, not only libfoo's direct dependencies, but also all the recursive dependencies, which I don't want to.
Is there any way to expose only the direct dependencies? Or is there any other workaround to this situation?
In this case, it is needed to the problem with a broken openCV, and someone could say: hey, just solve that problem with openCV, and forget about that.
But this is also useful for someone who wants to link statically to a library which performance is critical, but still link dinamically to other heavier libraries which aren't as critical.
System:
Debian 10
GCC 8
OpenCV might have some packages or dependencies installed from testing.
I just bumped into this, and I think I'm going to have to write a bit of Python to just repeatedly call pkg-config.

Type fatal error: gtk/gtk.h: No such file or directory during Eclipse (Oxygen) compilation

I've some errors compiling C code with GTK widgets in Eclipse, indicating that gtk/gtk.h cannot be found. I've already installed GTK+2 and GTK+3; and also included the header paths for GTK but it seems that the Eclipse environment is still unable to find the required header.
Greatly appreciate any advice from the community!
You didn't provide enough information to actually know what is going on, but I guess the include paths you configured are somehow wrong.
My advice would be that you should use pkg-config to obtain the correct compiler flags instead of adding include dirs etc. manually.
This will give you a list of all packages, pkg-config knows are installed on your machine:
pkg-config --list-all
The GTK package should be something like gtk+-3.0
Use this to get the CFLAGS for use with GTK3:
pkg-config --cflags gtk+-3.0
And here is how to get the libraries for the linker stage:
pkg-config --libs gtk+-3.0
So instead of doing something like this:
# Don't do this
gcc -I... main.c
... use something like this:
gcc $(pkg-config --cflags gtk+-3.0) ... main.c
Read the man page of pkg-config for more informations.
There was an Eclipse plugin for pkg-config support, but it doesn't seem to work with Oxygen. I managed to get a building example with these settings, though Eclipse itself won't find the includes.

Questions about how libraries work in C

I am a newbie student learning C and wish to use the gLib library functions for a project: http://www.linuxfromscratch.org/blfs/view/svn/general/glib2.html
(I am using Ubuntu)
I have a couple questions about how libraries work in C and what happens when you install one or want to use one:
When I install this (run ./configure && make && make install inside the folder), what exactly is it doing? From what I learned there are shared libraries in C and static libraries in C. Is it true that it is installing library and include files to /usr/lib/ or somewhere?
When using gcc with external libraries, you have to specify -L and -I flags to specify where to look for library and header files. When I install glib, will I need to specify these flags?
If I want to package my executable for another machine, what would happen if the other machine doesn't have glib? I think if I had static libraries I would be able to include it in the binary, but how would it work for glib?
I am familiar with developing with GTK+ and GLIB. As i'm aware library files reside in /usr/lib and include files are found in /usr/include. Some libraries might be in places such as /usr/local/lib. I will attempt to answer your questions as best as I could.
When installing a library through the source package yes it installs files to the various folders /usr/share /usr/lib /usr/include and etc. It's highly recommended you use your distribution's package manager to install library packages and development headers. Installing from source is always bound to fail as necessary dependencies might be required.
This is where tools such as autogen and makefiles come handy. You don't necessarily need to concern yourself with specifying all that. tools such as pkg-config handle all that work. Most libraries will install a package configuration file into /usr/lib/pkgconfig & /usr/share/pkgconfig directories. This helps anyone developing an application easily link their code to the libraries.
Using package config to get the config:
$ pkg-config --cflags --libs glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0
Linking using GCC & package config:
$gcc example.c `pkg-config --cflags --libs gtk+2.0 glib-2.0` -o example
The above command would link my program with gtk & glib.
Using Makefile to not ever have to enter those long lines again:
Makefile:
OBJS = main.o callbacks.o
CFLAGS = `pkg-config --cflags --libs gtk+-2.0`
program: $(OBJS)
gcc -o program $(OBJS)
main.o: main.c
gcc -c main.c $(FLAGS)
callbacks.o: callbacks.c callbacks.h
gcc -c callbacks.c $(FLAGS)
.PHONY : clean
clean:
rm *.o
rm program
.PHONY : install
install:
cp program /usr/bin
.PHONY : uninstall
uninstall:
rm /usr/bin/program
The above makefile is for a simple GTK+2.0 application as you can tell by what package config is including in CFLAGS to make the program executable all you have to enter in your source directory would be make. pkg-config will only work if you have installed the development packages for the library you are trying to work with. For ubuntu to install GTK+-3.0 and GLIB development files you would enter:
$ apt-get install libgtk-3-dev
I think this is a good concern for portability. No single static library is going to be cross platform. It would have to be compiled for those platforms manually. I reckon to get rid of all the headache you would use Anjuta IDE developed by the GNOME software foundation. It makes developing GLIB & GTK+ apps a breeze supporting both C & C++. It will create the Makefile, configure and other files to make developing code on cross platforms easy and make deployment easy. I could link you some resources, but my reputation on stack overflow is less then 10. So I will just mention the name of some resources below.
Further Reading
Makefile Tutorial
Anjuta IDE (C/C++)): ://anjuta.org/
GTK+-3.0 Hello World with Compiling and linking using pkg-config:
When I install this (run ./configure && make && make install inside
the folder), what exactly is it doing? From what I learned there are
shared libraries in C and static libraries in C. Is it true that it is
installing library and include files to /usr/lib/ or somewhere?
Well it is running first ./configure and then if that succeeds it runs make and if that succeeds it runs make install. configure is a script that takes care of a lot of compatibility issues between systems. They are usually shell scripts as this is the common denominator across systems so the configure script will work across various systems. One of the thing configure does is create a Makefile. The second command make will use the newly created Makefile to build the library or executable. Since you did not specify a target (like you will in the make install) make will build the default target, which is typically the all target. This is just by convention. Makefiles are basically a list of things to build (targets) along with what they depend on (dependencies) and how to build to target (rules). Finally, make install will actually install the necessary components. For libraries this is the library and necessary header files for executables it is just the program. man pages might also be installed. Where you install the libraries depends on where you specify to install them. Typically configure will take the --prefix argument that lets you control where they are installed. If you do not use --prefix you will most likely install in the default location for your system.
When using gcc with external libraries, you have to specify -L and -I
flags to specify where to look for library and header files. When I
install glib, will I need to specify these flags?
Your question is a little unclear, so let me first make sure I understand. Are you asking if after you install glib will you need to use -L and -I to tell gcc where to look for them? If so it depends on where you install them. Typically when you make and install a library you will install the library and header files in the default location or not. If you did then assuming your gcc is configured correctly then no you will not. If you did not then you will most likely have to use -L and -I
If I want to package my executable for another machine, what would
happen if the other machine doesn't have glib? I think if I had static
libraries I would be able to include it in the binary, but how would
it work for glib?
If it doesn't have glib and you used the shared libraries your application will not work. You will need to either have the same version glib libraries on the other machine or build the libraries statically. How to build them statistically depends on the library. This SO question might help.
Regarding configure, make and make install. configure is a shell script that is used to discover (and configure) your development environment. make and make install are convenient way of building your software. Where make would normally involve compiling and linking, where as make install would normally involve copying executables and libraries to standard path and setting up things (also include files if any usually in /usr/include), so that you don't have to explicitly give path before running the executable. What make does can be done by hand, but it's very cumbersome.
For glibc - yes you have to specify those flags. Normally all libraries will come in two flavors on most of the platforms. The binary form are used for dynamic linking when programs are actually loaded. Also - most distributions will have -dev or -devel versions of those libraries. Those are required for building software that makes use of those libraries (configure above can help find out whether devel libraries are installed). Typically when you see a library installed but not it's devel - you are likely to see configure errors. In short you require devel versions if you want to link with those libraries. This step is not needed if you are building libraries also from source using make and make install.
If you want to package your executable for another machine and you are not sure whether another glib is there or you want to be sure that the glib to be installed should be one specific version that you want, you should statically link while building (compiling/linking) the library. this gcc man page has got several details about link options. I believe there should be a way to statically link glib(or glib2). Though normally that may not be required if you have enough applications that are using it already.

Compiling 32-bit GTK+ Applications of 64 bit Linux

I am having some trouble compiling 32-bit GTK+ applications on 64-bit Linux, specifically Ubuntu 10.04. Compiling 64-bit GTK+ applications works fine, and everything is set up to compile 32-bit apps as well, but it doesn't work with GTK+
I have a very simple test program that I am using for trouble shooting that is simply a gtk_init and a gtk_main, which compiles fine as -m64. I am compiling with gcc 4.6.2, calling it with:
gcc -m32 gtktest.c `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`
These are the two different kinds of error messages I get:
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libXext.so.6, needed by /usr/lib/../lib32/libgtk-x11-2.0.so, not found (try using -rpath or -rpath-link)
and
/usr/lib/../lib32/libgdk-x11-2.0.so: undefined reference to `XmbSetWMProperties'
Keep in mind that these aren't the only errors, I just included the two specific types for reference and to keep it short, I get errors for the whole stack of GTK+ libraries.
I do have all of the proper 32-bit versions of the libraries in my lib32 folders.
Hopefull someone has had this problem before and can help me, this is really causing me quite the headaches, and I can't fine much help any where on the net.
Please ask if there is any other information you need me to provide to help with diagnosing this problem.
Note: I do have the ia32-libs and gcc-multilib packages. Ubuntu 10.04 does not have a separate ia32-libs-gtk packages, but I think these are wrapped in to the ia32-libs packages. They all are present on my system.
I think this must be some sort of linker config problem. I've recently built the new Free Pascal compiler and a 32 bit cross compiler, and I also upgraded GCC to 4.6.2 to take advantage of some of the new C++ features and fixes to C99 support. The default 4.4.3 GCC still exists on my system. Where I think the problem has been introduced is when I installed a new binutils because I've been experimenting with Clang and LLVM as a toolchain, and I wanted and ld with plug-in capabilities, so I figured might as well upgrade them all.
Everything works fine compiling 64 bit programs, there hasn't been a single problem with the new tools at all, and I can compile 32-bit programs but when it comes time to explicitly link something in I have problems.
I know my current set of libs is appropriate, and I have Free Basic installed which only emits 32 bit code, and I was able to build 32-bit GTK+ programs no problem before this upgrade.
Just wondering if anyone has any ideas what configs might have been changed in this upgrade or has had this happen to them before? I really should upgrade to a newer distro so I can take advantage of all the new software with out have to hack up all of my packages, but unfortunatly there is a bug in the newer kernels that prevents my computer from coming back from standby, and this is a laptop I use for personal side projects, so proper power management is pretty important, and it's not a huge loss if I bork the system, other than I have it set up pretty much perfect for my workflow.
You may tell pkg-config to search for the 32-bit libraries with the environment variable PKG_CONFIG_PATH.
For Ubuntu:
export PKG_CONFIG_PATH=/usr/lib32/pkgconfig:$PKG_CONFIG_PATH
For Redhat:
export PKG_CONFIG_PATH=/usr/lib/pkgconfig:$PKG_CONFIG_PATH
I think you need to install the ia32-libs-gtk & gcc-multilib packages, and you need to compile and link with gcc -m32 as you already do.
The GTK package in 12.04 doesn't seem to work correctly with multiarch. You can work around this on Ubuntu 12.04 by creating the following symlinks:
sudo ln -s /lib/i386-linux-gnu/libglib-2.0.so.0 /usr/lib32/libglib-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0 /usr/lib32/libgtk-x11-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0 /usr/lib32/libgdk-x11-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libatk-1.0.so.0 /usr/lib32/libatk-1.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libpangox-1.0.so.0 /usr/lib32/libpangox-1.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libpango-1.0.so.0 /usr/lib32/libpango-1.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgmodule-2.0.so.0 /usr/lib32/libgmodule-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgobject-2.0.so.0 /usr/lib32/libgobject-2.0.so
sudo ln -s /usr/lib/i386-linux-gnu/libgdk_pixbuf-2.0.so.0 /usr/lib32/libgdk_pixbuf-2.0.so
I found the answer in this thread: http://www.blitzbasic.com/Community/posts.php?topic=101357
Alternatively (probably better), you can leave the base system untouched and update your link to search by file name instead of library name. Something like:
gcc -m32 gtktest.c `pkg-config --cflags gtk+-2.0` -L/usr/lib/i386-linux-gnu -l:libgio-2.0.so.0 ...
This isn't great. You'll have to add a -l: for each library that the linker can't find and your build will break if the library file name ever changes.

How can I include a needed C library using GCC?

I am trying to compile the simple C example from this tutorial on Ubuntu using GCC. What do I have to use as arguments for GCC to include the needed libraries for #include <libappindicator/app-indicator.h>?
-I<search path to include files>
-L<search path to the lib file>
-l<libname>
Use the -l command line option. You can specify the library search path with the -L option. E.g:
gcc -o myprogram -lfoo -L/home/me/foo/lib myprogram.c
This will link myprogram with the static library libfoo.a in the folder /home/me/foo/lib.
If you used apt-get, Synaptic Package Manager, etc. to get the appindicator library (vs. building it from source), did you only install the libappindicator1 package or did you also install libappindicator-dev to get the libappindicator header files? Linux packages very often have split the runtime libraries from the compile-time headers. That way people who only need the libraries to satisfy a dynamic link don't have to install unneeded headers. But since you're doing development you need those headers and therefore need the libappindicator-dev package as well.
What I do is:
pkg-config --list-all | grep indicator
Use:
gcc example.c -o example `pkg-config --cflags --libs appindicator-0.1`
pkg-config will fetch the required include and library flags for libappindicator and its dependencies. This assumes libappindictaor-dev package is already installed.
You are trying to make a GTK app, and the previous solutions are as applicable anywhere like using the -l option and -I option,
However, for GTK applications, you may also use pkg-config which makes it easier as your paths can be predefined.
An interesting example can be found in
http://developer.gnome.org/gtk/2.24/gtk-compiling.html

Resources