<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: EduardoRFS</title>
    <description>The latest articles on Forem by EduardoRFS (@eduardorfs).</description>
    <link>https://forem.com/eduardorfs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F412037%2F69e8dac2-adb5-4674-92da-8698a7947d96.jpeg</url>
      <title>Forem: EduardoRFS</title>
      <link>https://forem.com/eduardorfs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/eduardorfs"/>
    <language>en</language>
    <item>
      <title>A journey into Reason Mobile</title>
      <dc:creator>EduardoRFS</dc:creator>
      <pubDate>Wed, 19 Aug 2020 10:09:05 +0000</pubDate>
      <link>https://forem.com/eduardorfs/a-journey-into-reason-mobile-37al</link>
      <guid>https://forem.com/eduardorfs/a-journey-into-reason-mobile-37al</guid>
      <description>&lt;p&gt;This is mostly a report on why simple things aren't simple so no TLDR. And also a bit about Reason Mobile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Last year(2019) when I was still employed, I was looking at a cool piece of tech, called &lt;code&gt;Revery&lt;/code&gt; a framework to develop desktop applications using Reason Native, JSX and super fast, also it's not React, it felt really cool, trying some applications like Oni2 the performance was really impressive.&lt;/p&gt;

&lt;p&gt;At the time I was working with embedded, on a device with 128mb of memory, running on a armv7hf linux box with a broken userspace running QT and using QML, a screen that could only make full updates 5 times per second, yes 5fps. Then I was really curious would it be possible to use something like Revery to make embedded development? Sure this thing can run Revery right?&lt;/p&gt;

&lt;p&gt;I was correct(I always am)&lt;/p&gt;

&lt;h2&gt;
  
  
  But ... OCaml
&lt;/h2&gt;

&lt;p&gt;Normally I would say that a cool feature of Reason is being fully compatible with OCaml, so that you can easily use the tools from the OCaml ecosystem like the compiler, build system's like &lt;code&gt;Dune&lt;/code&gt; and even packages from &lt;code&gt;opam&lt;/code&gt; to build native applications aka Reason Native.&lt;/p&gt;

&lt;p&gt;This time was a little bit different, see, using the OCaml ecosystem also makes Reason Native suffer from the same problems as the OCaml ecosystem, like missing proper tooling to cross compile and not having a great support for Android and iOS.&lt;/p&gt;

&lt;p&gt;Yeah the hardware could easily run it, it's possible to run Revery with less than 64mb of memory and a potato as a CPU, it will not be exactly efficient on battery but that was okay for me, but the tooling? There was no tooling&lt;/p&gt;

&lt;p&gt;To make things worse, we also have a new tool, called &lt;code&gt;esy&lt;/code&gt; which can consume opam and npm packages, while also making a really easy to reproduce environment, is a really cool piece of tech, but how does it works? Yeah sandboxing, and that completely break the previous attempts to cross compile from the OCaml ecosystem namely &lt;code&gt;opam-cross&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The easy trick
&lt;/h2&gt;

&lt;p&gt;The obvious choice is "caveman cross-compiling" just emulate the entire environment, sure, it did work, took a couple of hours and I got to compile binaries from Linux x86_64 to Linux ARMv7l, there is just a single detail, the reason why it took a couple of hours isn't because the setup of the environment needed any trick, nope, with esy that "just works", it took a couple hours because emulating an ISA is one of the slowest thing you can ever do if you're doing it properly and especially emulating a RISC on a CISC like ARMv7l on x86_64.&lt;/p&gt;

&lt;p&gt;But the trick that I was doing is called full system emulation, there is also another trick which uses user-space emulation combined with binfmt to run a chroot(like a docker container) from one architecture in the other. That was a lot better, but probably still 5x slower than natively compiling on my desktop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackish Solution
&lt;/h2&gt;

&lt;p&gt;A couple of months ago, I was not employed anymore and had a lot of spare time, so I tried to properly address that by adding cross compiling support on &lt;code&gt;esy&lt;/code&gt;, yeah that wasn't so simple, modeling multiple versions of the same package turned out to be really tricky, and I didn't have any proper knowledge on package managers, then I made a hackish solution, like really hackish, I don't even want to tell you how it works, but trust me it's a hackish solution.&lt;/p&gt;

&lt;p&gt;I called it &lt;a href="https://github.com/EduardoRFS/reason-mobile"&gt;reason-mobile&lt;/a&gt; a bad name, but the intent was "providing tools to cross compile Reason to mobile aka Android and iOS", on that ... yeah I got it to work.&lt;/p&gt;

&lt;p&gt;This entire time I was only looking on Android, because it's what I daily drive ... no iOS wasn't simpler. But well what you need to know now is that it works, in a &lt;code&gt;future post&lt;/code&gt; the road to iOS can be discussed. Currently it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it?
&lt;/h2&gt;

&lt;p&gt;It's a hackish solution, you clone the repository, &lt;strong&gt;put your project inside the root of the project&lt;/strong&gt;, and run some magic, there is a example on the README, but the commented script is the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:EduardoRFS/reason-mobile.git
&lt;span class="nb"&gt;cd &lt;/span&gt;reason-mobile/hello-reason

&lt;span class="c"&gt;## it will install the host dependencies&lt;/span&gt;
esy &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;## cursed node magic, don't ask&lt;/span&gt;
node ../generate/dist/cli.js android.arm64

&lt;span class="c"&gt;## builds all the dependencies for host and target&lt;/span&gt;
&lt;span class="c"&gt;## it's going to take a while, seriously&lt;/span&gt;
esy @android.arm64

&lt;span class="c"&gt;## enter the patched esy shell&lt;/span&gt;
esy @android.arm64 not-esy-setup &lt;span class="nv"&gt;$SHELL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Inside this shell you can run the normal commands, like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## it will build for Android ARM64&lt;/span&gt;
dune build &lt;span class="nt"&gt;-x&lt;/span&gt; android.arm64

&lt;span class="c"&gt;## binary located at&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lah&lt;/span&gt; &lt;span class="nv"&gt;$cur__target_dir&lt;/span&gt;/default.android.arm64/bin/hello.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Supported platforms
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;android.arm64&lt;/li&gt;
&lt;li&gt;android.x86_64&lt;/li&gt;
&lt;li&gt;ios.arm64&lt;/li&gt;
&lt;li&gt;ios.simulator.x86_64&lt;/li&gt;
&lt;li&gt;linux.musl.x86_64&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ok, so how it works?
&lt;/h2&gt;

&lt;p&gt;Mostly bad magic, and a lot of shell script hacked.&lt;/p&gt;

&lt;p&gt;Reads the &lt;code&gt;esy.lock&lt;/code&gt; generated by &lt;code&gt;esy&lt;/code&gt;, extract a lot of data using some low level commands from esy like &lt;code&gt;esy ls-build&lt;/code&gt; and &lt;code&gt;esy build-plan&lt;/code&gt;, duplicate every dependency adding a prefix to it, patch commands like &lt;code&gt;dune build&lt;/code&gt;, add some hand made patches for broken dependencies, add a shell script wrapper to remove &lt;code&gt;OCAMLLIB&lt;/code&gt; and &lt;code&gt;OCAMLPATH&lt;/code&gt; from the environment as these's are problematic with cross compilation.&lt;/p&gt;

&lt;p&gt;Then it generate a bunch of files inside &lt;code&gt;.mocks&lt;/code&gt; and a "package.json" for the specific platform, so you can do &lt;code&gt;esy @android.arm64&lt;/code&gt;, but that would still make your environment be broken so it has another hack, &lt;code&gt;esy @android.arm64 not-esy-setup &amp;lt;command&amp;gt;&lt;/code&gt; which will execute commands in the patched environment.&lt;/p&gt;

&lt;p&gt;Simple as that&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;I tried all supported platforms from Linux and Mac, I have no idea if it works on Windows, my bet is that it will not even on cygwin but feel free to try.&lt;/p&gt;

&lt;p&gt;And there will be some bugs, if you need help with it feel free to contact me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future and possibilities
&lt;/h2&gt;

&lt;p&gt;I started talking about Revery, yeah that was also maded and is &lt;code&gt;another post&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We also need a proper solution, integrated on &lt;code&gt;esy&lt;/code&gt;, ideally doing a lot of magic.&lt;/p&gt;

&lt;p&gt;Maybe Reason React Native Native? You know, RRNN, maybe RNRN, it need's a better name, but it's also something that I'm looking for.&lt;/p&gt;

</description>
      <category>reason</category>
      <category>ocaml</category>
      <category>mobile</category>
      <category>revery</category>
    </item>
  </channel>
</rss>
