Skip to content

Instantly share code, notes, and snippets.

@c-mendoza
Last active November 19, 2021 16:20
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save c-mendoza/6bf84b42ee1bdc094ebcf19fcf3904b8 to your computer and use it in GitHub Desktop.
Save c-mendoza/6bf84b42ee1bdc094ebcf19fcf3904b8 to your computer and use it in GitHub Desktop.
openFrameworks Cross-Compiling Environment for MacOS > RPi

Cross-compiling openFrameworks apps from MacOS to RaspberryPI

Version 0.2.1

If you use macOS you might be able to use a cross-compilation environment that runs on macOS, but produces binaries that run on a RaspberryPI. Native speed and no VM's required! The environment consists of a disk image that contains a cross-platform toolchain created using crosstool-ng, and an rpi-root folder containing necessary files from Raspbian Buster.

References

The cross-compiler was created based on instructions written by Jared Wolff. The OF side of the environment was based on jcleave's post on cross-compilers.

Compatibility

Compilation has only been tested on MacOS 10.14 using openFrameworks 0.10.1. Binaries produced are armv6 and have only been tested on a Raspbian Stretch and Buster on a RPi 2B. Running on earlier OS's will probably require updating libraries, but binaries should run on newer Pi models. armv7 binaries would require modifications of the appropriate OF makefile, which I have not done. Using older versions of OF will likely not work without some modifications to the provided makefile.

Concept

The idea behind the environment is to be able to compile an OF app directly from the source files located in your Mac, and to produce binaries that are stored in your Mac's OF app directory (inside a bin folder, just like in Linux). You can then copy those binaries to your RPi for execution.

Setup

The following instructions assume that you are using a standard release of openFrameworks. If you are using OF from the repository these steps might be slightly different.

  1. Begin by downloading the zip file containing the disk image. The archive is about 2.6GB, but you'll need an additional 6.5GB of hard drive space to decompress it.
  2. Download and decompress the Linux armv6 release of openFrameworks (download 0.10.1 [here] (https://openframeworks.cc/versions/v0.10.1/of_v0.10.1_linuxarmv6l_release.tar.gz)), which we'll need to get some libraries that we'll copy to macOS.
  3. In Finder, open the macOS openFrameworks folder. Let's call this folder <your_macOS_OF_Folder>.
  4. Now we'll copy the libraries necessary to link RPi apps to the libs folder of our OF release in macOS. In Finder, open the libs folder of the release you just downloaded. Copy the following:
    1. The folder kiss to <your_macOS_OF_Folder>/libs
    2. The folder tess2/lib/linuxarmv6l to <your_macOS_OF_Folder>/libs/libstess2/lib/
  5. Make a new folder called linuxarmv6l in <your_macOS_OF_Folder>/libs/openFrameworksCompiled/project/
  6. Mount the disk image you downloaded by double-clicking xtools-build-env.sparsebundle
  7. Copy /Volumes/xtools-build-env/extras/config.linuxarmv6l.default.mk to the folder you created in step 5.
  8. Now you need to modify your bash profile:
    1. In Terminal, type nano ~/.bash_profile.
    2. Add the following lines to it:
export GST_VERSION=1.0
export PLATFORM_OS=Linux
export PLATFORM_ARCH=armv6l
export PLATFORM_VARIANT=default
export RPI_ROOT=/Volumes/xtools-build-env/rpi-root
export TOOLCHAIN_ROOT=/Volumes/xtools-build-env/arm-unknown-linux-gnueabihf
export PKG_CONFIG_PATH=$RPI_ROOT/usr/lib/arm-linux-gnueabihf/pkgconfig:$RPI_ROOT/usr/share/pkgconfig:$RPI_ROOT/usr/lib/pkgconfig
export TOOLCHAIN_PREFIX=arm-unknown-linux-gnueabihf
export GCC_PREFIX=arm-linux-gnueabihf
export GCCVER=6
3. Save it by typing `cntrl+o` and then exit with `cntrl+x`.
4. Close the Terminal window.
  1. Ok, almost there! At this point you should try to compile an OF example:
    1. MAKE SURE THAT THE DISK IMAGE IS MOUNTED! None of this works without the disk image!
    2. Use the [Project Generator])https://openframeworks.cc/learning/01_basics/create_a_new_project/) to create the makefiles for any example.
    3. Open a new Terminal window in the folder of the example that you are using.
    4. Type the following command: make PLATFORM_ARCH=armv6l Release -j4
    5. This should compile OF as well as the example, but it should end with a linking error mentioning something about crti.o and crt1.o not being found. THIS IS EXPECTED. If this is where you are, don't close the Terminal window and go to step 10.
      • If this is not the error you get then something has gone wrong. Check that the image is mounted and that you've added the correct lines to your ~/.bash_profile. If you need to modify your profile, save it and then open an new Terminal window to apply the changes (you can also use the source command to apply your profile by typing in your Terminal window source ~/.bash-profile).
  2. Due to some mysterious reason that I don't understand AT ALL, crti.o, crt1.o, and crtn.o, which are part of the toolchain and are necessary to link c++ programs, are not found by the linker. Because of this you need to copy them to your project folder, and to make this easier I have provided copies that are in /Volumes/xtools-build-env/extras.
    1. Copy crti.o, crt1.o and crtn.o to your project folder.
    2. In the Terminal window that you left open, type make PLATFORM_ARCH=armv6l Release -j4 (or just press the up arrow to show the last command you typed).
    3. If the compilation process completed, congratulations! You now have a shiny new executable in the bin folder of your project that should run on the Raspberry Pi!

Important

For any new project you want to cross-compile you'll need to copy crti.o, crt1.o and crtn.o to your project's folder. Yes, unfortunately you have to do this for every project, but it is a small annoyance for a huge gain in convenience and performance. If you figure out how to fix this LET ME KNOW!!

@stephanschulz
Copy link

stephanschulz commented Dec 29, 2019

trying it now.
2 things I am unsure about:
8. i. Is this .bash_profile a file in the current user root or in the OF folder?
9. ii. Do I select Platform OS X or Linux ARMv6 or both ?

Here is my console printout with all it's errors:
https://gist.github.com/stephanschulz/add4ea4541846603ef1aacd707df6e06

for example
/Volumes/xtools-build-env/arm-unknown-linux-gnueabihf/lib/gcc/arm-unknown-linux-gnueabihf/6.4.0/../../../../arm-unknown-linux-gnueabihf/bin/ld.bfd: cannot find -lm

Screen Shot 2019-12-28 at 9 33 01 PM

also:

Stephan-2:~ stephanschulz$ source ~/.bash-profile
-bash: /Users/stephanschulz/.bash-profile: No such file or directory

@c-mendoza
Copy link
Author

All of those errors are the linker not finding the libraries, likely because your environment variables are not set correctly in your bash_profile.

.bash_profile should be in your home directory (your user root, as you put it). If it doesn't exist then you should create it. Easiest way to do that from the command line is to write nano ~/.bash_profile (nano is a command line text editor). Copy the required lines in step 8, paste them into nano, then ctrl+o to save, ctrl+x to exit.

To make sure your environment variables are set correctly, open a new command line window and type echo $TOOLCHAIN_ROOT. If the response isn't /Volumes/xtools-build-env/arm-unknown-linux-gnueabihf then there is something wrong with your ~/.bash_profile.

Good question about step 9! The platform should include Linux ARMv6 (Makefiles).

You can either try the make command that is on the instructions above, or the following:
make Release PLATFORM_ARCH=armv6l PLATFORM_VARIANT=default -j4

Hope that helps!

@stephanschulz
Copy link

stephanschulz commented Dec 29, 2019

thanks. your help is very much appreciated.
here a screen shot showing the correct location of .bash_profile and the correct response to echo $TOOLCHAIN_ROOT and the proof that .bash_profile has the proper content.
but I still get the same compile errors.
Screen Shot 2019-12-29 at 8 33 04 AM

@c-mendoza
Copy link
Author

Oy, I think I shipped the wrong makefile with the zip archive. Can you trying using this one instead?

If it still doesn't work, can you compile using the following command and post the output?
make Release PLATFORM_ARCH=armv6l PLATFORM_VARIANT=default -j1 MAKEFILE_DEBUG=1

@stephanschulz
Copy link

stephanschulz commented Dec 29, 2019

  • downloaded your new makefile
  • placed in location at instructed in step 7. (see image)
  • still got the linking error
  • ran you longer make Release PLATFORM_ARCH=armv6l PLATFORM_VARIANT=default -j1 MAKEFILE_DEBUG=1

here the result:
https://gist.github.com/stephanschulz/477ce7398d04c964f38c88f1548c9254

maybe somehow my OS does not let your scripts access thing due to strange permission stuff?

Screen Shot 2019-12-29 at 6 28 22 PM

@stephanschulz
Copy link

sorry about this long process. but I am very happy we are trying to work this out. thank you.

as per your suggestion I used make Release PLATFORM_ARCH=armv6l PLATFORM_VARIANT=default -j1

and get this print out:
https://gist.github.com/stephanschulz/07aa55f3bff33cdcf16541a116b77681

@stephanschulz
Copy link

is it possible that I have to install all those tool in order for ld.bfd to find them.

like -lX11, -lpcre, -lXinerama, -luriparser etc

@c-mendoza
Copy link
Author

Gah, there is an error in one of the export statements in the bash profile.

It should be:
export GCC_PREFIX=arm-linux-gnueabihf

After you save the profile, either source it or open a new terminal window for it to take effect.

@stephanschulz
Copy link

Sorry about the slow reply; New Years ...

It seems to compile well now. Yeah. I still will have to try it on the RPI.

Here the terminal printout: https://gist.github.com/stephanschulz/d22a7c4fe2c1451bf057b811d1d1f84c

THANK YOU.

@c-mendoza
Copy link
Author

🎉

@stephanschulz
Copy link

I copied over the bin folder with compiled app on to a RPI 4 with the new buster version.
simply double clicking on the app icon did not make it run.
I then followed the apt steps from here: https://openframeworks.cc/setup/raspberrypi/raspberry-pi-getting-started/
Still app did not run.

Next I will install OF on the RPI and see if that helps somehow.

@stephanschulz
Copy link

I installed OF on the RPI 4 as per the usual instructions.
Then call make and make run

pi@raspberrypi:~/openFrameworks/examples/gui/guiExample $ make run VER ID IS 10 using newer build and GLFW window

I wonder if GLFW window has something to do with the cross compiled app not working.

@stephanschulz
Copy link

stephanschulz commented Jan 6, 2020

next test was to move the guiExample_macOS folder (which contains the cross compiled app) in to the RPI 4 example folder and run 'make' on it.

I get these errors:
https://gist.github.com/stephanschulz/6c5cdf72a4fbd9a30a8fd8b31f526bf8

@c-mendoza
Copy link
Author

c-mendoza commented Jan 6, 2020 via email

@stephanschulz
Copy link

thanks.

I installed OF and was able to compile directly on the RPI and an example run fine.
Now I followed your steps and get this error when calling ./guiExample
pi@raspberrypi:~/openFrameworks/examples/gui/guiExample_macOS/bin $ ./guiExample ./guiExample: error while loading shared libraries: libboost_filesystem.so.1.62.0: cannot open shared object file: No such file or directory

@stephanschulz
Copy link

ok I will try OF 0.10.1 and not 0.11.0 and see if this helps

@c-mendoza
Copy link
Author

c-mendoza commented Jan 6, 2020 via email

@steeley
Copy link

steeley commented Oct 9, 2021

Can this been used to make 64 bit binaries for RPI?

I can't find how to make OF 0.11 compile directly on Raspios 64 bit. Posted on OF forum and Github - nobody knows
(or is not interested)

@c-mendoza
Copy link
Author

Sorry, no idea, since I don't have a 64bit RPi

@lysdexic-audio
Copy link

lysdexic-audio commented Nov 19, 2021

Same here.. can't get anything before 11.02 to compile for the pi (on the pi) - but using this cross compiler on MacOS yields the following for 11.02:

Undefined symbols for architecture x86_64:
  "___isPlatformVersionAtLeast", referenced from:
      _singleipconnect in curl.a(libcurl_la-connect.o)
      _darwinssl_connect_common in curl.a(libcurl_la-darwinssl.o)
      _darwinssl_version_from_curl in curl.a(libcurl_la-darwinssl.o)
ld: symbol(s) not found for architecture x86_64

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment