OpenWrt Forum Archive

Topic: How do I add a library to a OpenWRT cross-compiling environment?

The content of this topic has been archived on 4 May 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

Greetings everyone, I'm writing a simple application for Arduino Yun which captures a picture with a USB Webcam (using the UVC driver) and saves it in a microSD memory in PNG or JPEG file format (using libpng or libjpeg library). I've set up a cross compile environment for Yun by following this guide.
I've created a virtual machine with VirtualBox and installed Debian 8.0 on it. I installed all the software required to download and compile the OpenWRT-Attitude Adjustment version (which, I think, is the version used by Arduino Yun) on Debian.
So, I've downloaded the OpenWRT source code, downloaded its packages feed (with "git clone git://git.openwrt.org/12.09/packages.git"), downloaded and installed all available "feeds" (with: "./scripts/feeds update -a" "./scripts/feeds install -a") and then compiled it with: "make defconfig", "make prereq" and "make menuconfig".
When I typed in "make menuconfig", a graphical interface prompted. In that interface I selected:
Target System: (Atheros AR7xx/AR9xx);
Base System: I selected libc, libcc and marked as package libpthread and librt.
I left any other option as default. Then I compiled all with "time make V=99" command.
After about 2 hours, the compiling finished and I set the environment variables as the above mentioned guide described.
Looks like now I can compile any C code with this cross-compiler. Anyway, my application includes the png.h header in order to use the libpng library functions, and every time I try to cross-compile it, a "png.h not found" error pops up during the process.
So I tried to cross-compile the libpng library but when I ran "./configure" with the options for cross-compiling (--build and --host), it failed saying that zlib wasn't installed. So I downloaded the zlib library source code but looks like I can't cross-compile it (its ./configure doesn't allow cross-compiling options).
Eventually I compiled zlib and libpng normally on Debian and now, when I try to cross-compile my application, it still says that it can't find png.h... So, how can I "integrate" the libpng library to the cross-compiling environment so I can cross-compile my application?
Sorry for this long question, but it is all I've done today.
As always, I thank you for any help you can give me.

(Last edited by Nilio on 29 May 2015, 18:50)

when you cross compiling, can you send steps to do it?
so that somebody can help you?

Sure.
First, this is how I set the environment variables:

export PATH=${PATH}:/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin
export STAGING_DIR=/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2

Then, this is what happens when I try to compile my application with the cross-compiler:

daniele@debian:~/Scaricati$ mips-openwrt-linux-gcc ScattaFoto.c
ScattaFoto.c:19:17: fatal error: png.h: No such file or directory
compilation terminated.

This, instead, is what happens when I try to compile my applicaton with Debian's gcc:

gcc ScattaFoto.c
/tmp/ccIg9iyt.o: nella funzione "salvaImmaginePNG":
ScattaFoto.c:(.text+0xd34): riferimento non definito a "png_create_write_struct"
ScattaFoto.c:(.text+0xd70): riferimento non definito a "png_create_info_struct"
ScattaFoto.c:(.text+0xd9a): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0xde8): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0xdfe): riferimento non definito a "png_free_data"
ScattaFoto.c:(.text+0xe23): riferimento non definito a "png_init_io"
ScattaFoto.c:(.text+0xe5e): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0xe74): riferimento non definito a "png_free_data"
ScattaFoto.c:(.text+0xead): riferimento non definito a "png_set_IHDR"
ScattaFoto.c:(.text+0xee8): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0xefe): riferimento non definito a "png_free_data"
ScattaFoto.c:(.text+0xf23): riferimento non definito a "png_write_info"
ScattaFoto.c:(.text+0xf64): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0xf7a): riferimento non definito a "png_free_data"
ScattaFoto.c:(.text+0x1013): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0x1029): riferimento non definito a "png_free_data"
ScattaFoto.c:(.text+0x105c): riferimento non definito a "png_write_row"
ScattaFoto.c:(.text+0x10a8): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0x10be): riferimento non definito a "png_free_data"
ScattaFoto.c:(.text+0x10ed): riferimento non definito a "png_write_end"
ScattaFoto.c:(.text+0x10fe): riferimento non definito a "png_destroy_write_struct"
ScattaFoto.c:(.text+0x1114): riferimento non definito a "png_free_data"
collect2: error: ld returned 1 exit status
(where "riferimento non definito a" means "undefined reference to" in italian)

But if I try to compile it with this option, the compilation terminates successfully and the .out file is produced (and it works too):

gcc -L/usr/lib/libpng12 -lpng ScattaFoto.c

Unfortunately, this isn't the same result I get when I provide that option to the cross-compiler:

mips-openwrt-linux-gcc -L/usr/lib/libpng12 -lpng ScattaFoto.c
ScattaFoto.c:19:17: fatal error: png.h: No such file or directory
compilation terminated.

I also tried with the -I option, and this is what I got:

mips-openwrt-linux-gcc -I/usr/include/libpng12 -L/usr/lib/libpng12 -lpng ScattaFoto.c
In file included from ScattaFoto.c:19:0:
/usr/include/libpng12/png.h:536:18: fatal error: zlib.h: No such file or directory
compilation terminated.

I hope this helps to find a solution. Anyway, I want to thank you: I really appreciate your attention.

Nilio wrote:

mips-openwrt-linux-gcc -L/usr/lib/libpng12 -lpng ScattaFoto.c
ScattaFoto.c:19:17: fatal error: png.h: No such file or directory
compilation terminated.

The libraries in /usr/lib are for your desktop machine (probably x86 or x86_64). You can not link your OpenWrt binary against them.

What you need is library files (lib/*.a and/or lib/*.so) and preferably include files (include/*.h) built for OpenWrt with the cross compiler.
Two ways:
1) You find them downloadable (check OpenWrt repositories for lib-png-dev or something)
2) You build them yourself (with the cross compiler)

If you build them yourself, with the cross compiler, I believe you need to use the --prefix option in a smart way.
You do not want to install them in your desktop /usr/lib!
You probably want them in STAGING_DIR/usr/lib or STAGING_DIR/?/usr/lib (check where the other libraries are).

Later when you build ScattaFoto, you need to make sure to use the -L flag to point to your OpenWrt-png-library, not your local png-library.

This is just a rough guide. Perhaps I have missed something important. Perhaps there is a better guide online. But if something is entirely wrong I presume the other people here will let us know. Good Luck!

Thanks zo0ok, your reply made the solution clearer.
Anyway, today I ran the "make menuconfig" and added the following packages to the cross-compiling environment:

Libraries -> I selected libpng;
Kernel Modules -> Libraries -> I selected kmod-lib-zlib;
Video Support -> kmod-video-core -> kmod-video-uvc.

I tried to  cross-compile my application again since now I added libpng to the cross-compiling environment, and this is what happened:

daniele@debian:~/Scaricati$ mips-openwrt-linux-uclibc-gcc ScattaFoto.c
ScattaFoto.c:19:17: fatal error: png.h: No such file or directory
compilation terminated.

So I decided to search for the png.h file and include its directory with the -I option. First, I searched for it:

daniele@debian:~/Scaricati$ sudo find / -name 'png.h'
  [sudo] password for daniele:
  /usr/local/include/png.h
  /usr/local/include/libpng12/png.h
  /usr/include/png.h
  /usr/include/libpng12/png.h
  /home/daniele/.local/share/Trash/files/png.h
  /home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/libpng-1.2.46/ipkg-install/usr/include/ png.h
  /home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/libpng-1.2.46/ipkg-install/usr/include/libpng12/png.h
  /home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/libpng-1.2.46/png.h
  /home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/include/png.h  <--- Here it is.
  /home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/include/libpng12/png.h
  /home/daniele/Scaricati/libpng-1.2.52/png.h

Then I added it in the -I option and:

daniele@debian:~/Scaricati$ mips-openwrt-linux-uclibc-gcc -I/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/include ScattaFoto.c
/tmp/ccbQj34c.o: In function `salvaImmaginePNG':
ScattaFoto.c:(.text+0x1544): undefined reference to `png_create_write_struct'
ScattaFoto.c:(.text+0x1590): undefined reference to `png_create_info_struct'
ScattaFoto.c:(.text+0x15c8): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x1634): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x1654): undefined reference to `png_free_data'
ScattaFoto.c:(.text+0x1680): undefined reference to `png_init_io'
ScattaFoto.c:(.text+0x16d8): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x16f8): undefined reference to `png_free_data'
ScattaFoto.c:(.text+0x1744): undefined reference to `png_set_IHDR'
ScattaFoto.c:(.text+0x179c): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x17bc): undefined reference to `png_free_data'
ScattaFoto.c:(.text+0x17e8): undefined reference to `png_write_info'
ScattaFoto.c:(.text+0x1844): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x1864): undefined reference to `png_free_data'
ScattaFoto.c:(.text+0x1954): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x1974): undefined reference to `png_free_data'
ScattaFoto.c:(.text+0x19ac): undefined reference to `png_write_row'
ScattaFoto.c:(.text+0x1a28): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x1a48): undefined reference to `png_free_data'
ScattaFoto.c:(.text+0x1a80): undefined reference to `png_write_end'
ScattaFoto.c:(.text+0x1a94): undefined reference to `png_destroy_write_struct'
ScattaFoto.c:(.text+0x1ab4): undefined reference to `png_free_data'
collect2: ld returned 1 exit status

This is the same error I got when I tried to compile my application with Debian's gcc. So it is not a problem: I can solve it just adding the -L option to the cross-compiler:

4)daniele@debian:~/Scaricati$ mips-openwrt-linux-uclibc-gcc -I/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/include -L/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib -lpng ScattaFoto.c
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: warning: libz.so.1, needed by /home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so, not found (try using -rpath or -rpath-link)
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `deflate'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `inflate'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `inflateInit_'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `crc32'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `deflateInit2_'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `inflateReset'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `deflateReset'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `inflateEnd'
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libpng.so: undefined reference to `deflateEnd'
collect2: ld returned 1 exit status

This is weird, it never happens when I try to compile the application with gcc...
So I searched for libz.so.1:

daniele@debian:~/Scaricati$ sudo find / -name 'libz.so.1'
/usr/local/lib/libz.so.1
/lib/i386-linux-gnu/libz.so.1
/home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/root-ar71xx/usr/lib/libz.so.1
/home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/zlib-1.2.7/ipkg-install/usr/lib/libz.so.1
/home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/zlib-1.2.7/ipkg-ar71xx/zlib/usr/lib/libz.so.1
/home/daniele/openwrt/openwrt/build_dir/target-mips_r2_uClibc-0.9.33.2/zlib-1.2.7/libz.so.1
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libz.so.1  <---Maybe this one?
/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/root-ar71xx/usr/lib/libz.so.1
/home/daniele/Scaricati/zlib-1.2.8/libz.so.1

How could the cross-compiler not find it? I wonder where does the cross-compiler search for the libraries and header files...

I've managed to cross-compile my application at last. Here's what I've done.
I couldn't cross-compile my application because libpng wasn't installed in the corss-compiling environment. So, thanks to zo0ok's reply, I decided to download the libpng 1.2.52 library source code, cross-compile and install it in the cross-compiling environment (using the --prefix option). However, I couldn't do it because zlib wasn't installed in the cross-compiling environment. So I downloaded zlib 1.2.8 library source code and installed it in the cross-compiling environment following these steps:

1)CC=mips-openwrt-linux-gcc ./configure --prefix=/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2

2)make CC=mips-openwrt-linux-uclibc-gcc LD=mips-openwrt-linux-uclibc-ld

3)make install

Once zlib was installed in the cross-compiling environment, I went on and installed libpng with these steps:

1)./configure --build=i686-pc-linux-gnu --host=mips-openwrt-linux-uclibc

2)make test (it passed)

3)make install

Now that libpng is installed in the environment, I can finally cross-compile my application. This is what happened when I tried to cross-compile it:

daniele@debian:~/Scaricati$ mips-openwrt-linux-gcc -L/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib -lpng ScattaFoto.c
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: skipping incompatible /home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/libpng.so when searching for -lpng
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: skipping incompatible /home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/libpng.a when searching for -lpng
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: skipping incompatible /home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/lib/libpng.so when searching for -lpng
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: skipping incompatible /home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/lib/libpng.a when searching for -lpng
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: skipping incompatible /home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/mips-openwrt-linux-uclibc/bin/../../../toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/libpng.so when searching for -lpng
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: skipping incompatible /home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/mips-openwrt-linux-uclibc/bin/../../../toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/libpng.a when searching for -lpng
/home/daniele/openwrt/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib/gcc/mips-openwrt-linux-uclibc/4.6.3/../../../../mips-openwrt-linux-uclibc/bin/ld: cannot find -lpng
collect2: ld returned 1 exit status

Why are the libpng libraries I cross-compiled incompatible? Anyway, I tried to cross-compile my application with the libraries I downloaded with "make menuconfig" and:

daniele@debian:~/Scaricati$ mips-openwrt-linux-gcc -L/home/daniele/openwrt/openwrt/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib -lpng ScattaFoto.c

It compiled it. Now I wonder why the libpng libraries in the toolchain directory are incompatible. Can someone explain me this, please?

That was fun, wasn't it? Thanks for sharing...

Nilio wrote:

1)./configure --build=i686-pc-linux-gnu --host=mips-openwrt-linux-uclibc

2)make test (it passed)

This makes me very suspicious. If it passed "make test" I would think the library was actually built for your native machine (i686) rather than mips. I can't imagine how "make test" would succeed otherwise. But perhaps it is my imagination that is bad wink

I would try CC=mips... and LD=mips... also for libpng.

You should be able to use the "ld" command, or perhaps the "file" command to figure out if libpng.a and libpng.so are actually i686 or mips binaries.

The discussion might have continued from here.