Building a standalone app¶
nativella build turns a project into a single executable: a copy of the nativella command, PHP included, with the project packed inside. Run it, and the application starts: the machine needs no PHP.
cd path/to/notes
composer install --no-dev --optimize-autoloader
cd ..
nativella build notes
Packaging Notes 1.2.0 into dist/notes…
Done: dist/notes
nativella build [<project-dir>] [-o <output>]
The project directory defaults to the current one. The executable goes to dist/ in the current directory, named after the name of the application, in lower case with dashes (.exe on Windows); -o picks another path.
Tip
Build from the parent directory, as above, so that dist/ lands outside the project. The executable being written is always left out of the archive, but other files of a dist/ inside the project, like the builds of other applications, would ship.
What ships¶
The whole project directory, vendor/ included, as a compressed archive, except:
| Left out | |
|---|---|
.git, .idea, node_modules, tests |
At the root of the project. |
.env.local, and every path ending with .local |
Local overrides, which tend to hold secrets. The build lists the ones it leaves out. |
| Shipped empty | |
|---|---|
var/cache, var/log |
Symfony's cache and logs. |
storage/framework/cache, storage/framework/sessions, storage/framework/views, storage/logs |
Laravel's caches, sessions and logs. |
The caches, logs and sessions of your machine stay behind, but the directories ship: the frameworks expect them to exist.
Symbolic links are followed, so the packages Composer links from path repositories ship as real files.
Warning
Everything else ships, and anyone who has the executable can read it: .env files, keys, credentials. A desktop application has no secrets from its users. Keep out of the project anything they should not see: Credentials says where each kind goes.
Preparing the project¶
- Install the dependencies without the development ones:
composer install --no-dev --optimize-autoloader. Whatever is invendor/ships. - Build the front-end assets, if you have any:
node_modulesstays behind,public/builddoes not. - Set the production environment. With Symfony,
composer dump-env prodwrites.env.local.php, which ships (its name does not end with.local) and wins over the.envfiles. - Avoid caches that hold absolute paths of your machine, like Laravel's
config:cache: once extracted, the project runs from another directory.
Credentials¶
The users of the application can read whatever ships: the project is extracted in clear into their cache directory, and no packaging hides it. Where a credential comes from decides where it goes:
| Credential | Where it goes |
|---|---|
The secret the framework signs and encrypts with: Symfony's APP_SECRET, Laravel's APP_KEY |
Nowhere: each installation has its own, NATIVELLA_SECRET. The Laravel integration gives it to the framework; with Symfony, a line of framework.yaml does. |
| The credentials of the user: a token, the password of an account, a key they bring | Asked for in the application, and kept in the keychain of the system with Secrets. |
| Your own credentials: the key of a paid API, a token with rights on your services | Not in the application: on a server of yours, which keeps them, does the calls, and authenticates the users of the application. |
| Keys made to be public: a Sentry DSN, a publishable Stripe key, a key restricted to one use | In the configuration that ships, like .env.local.php. |
A release built by a CI can write the .env.local.php of composer dump-env prod from the secrets of the CI, just before nativella build: what it holds still ships, in clear. Keep it for what may be public.
At startup¶
The executable finds the project it carries and extracts it, once per build, into the cache directory of the user:
| Platform | Extracted to |
|---|---|
| Linux | ~/.cache/<identifier>/<build> (or $XDG_CACHE_HOME) |
| macOS | ~/Library/Caches/<identifier>/<build> |
| Windows | %LOCALAPPDATA%\<identifier>\<build> |
The next launches of the same build start right away. A new build extracts again, next to the previous one, and removes it once it runs: when no other instance of the application can be running from there. The data directory stays. Extraction is safe when two instances start at once: each one extracts aside, and the first to finish wins.
Then the application runs exactly as with nativella run. Its command line belongs to the application: a second launch forwards it to the running instance as AppReopened.
The data directory is separate from the extracted project: the database and the settings survive updates, as long as the identifier does not change.
What the machine needs¶
The executable carries the project and PHP: the machine needs neither PHP nor Composer. On Linux, it needs, to run, what the nativella command needs: the webview of the system, WebKitGTK 4.1, the library of the tray if the application shows a tray icon, and a glibc as recent as the one of the machine that built the nativella command, 2.35 for the releases, built on Ubuntu 22.04. The users of your application install them too: Installation lists the packages of each distribution, to repeat in the instructions of your application. On macOS, the executable needs nothing.
The PHP inside¶
The executable carries the PHP of the nativella command that built it: for the releases, PHP 8.5, linked statically, built with static-php-cli. The Symfony demo makes a 91 MB executable.
It has the extensions a Symfony, Laravel or Doctrine application needs (bcmath, ctype, curl, dom, fileinfo, filter, iconv, intl, mbstring, opcache, openssl, pdo_sqlite, phar, session, simplexml, sodium, sqlite3, tokenizer, xml, xmlreader, xmlwriter, zip, zlib), and no php.ini: PHP runs with its defaults, plus the settings Nativella sets (sessions in the cache directory of the application, the time zone of the system). intl carries ICU and its data, for every locale: 36 MB of the executable.
Android and iOS applications carry the same PHP, with the same extensions, built for the phone: see PHP for the phone.
Note
Installers (.deb, .dmg, .msi), code signing and updates are not there yet. See Limitations and roadmap.
Licenses¶
The executable contains the software of others, under their licenses: PHP, the libraries it is linked with (OpenSSL, curl, ICU, libxml2, GNU libiconv, libsodium, libzip, SQLite, zlib) and the ones php-src bundles (PCRE2, libmagic, lexbor, uriparser…), and the Rust crates of Nativella (Tauri, wry, tao, ext-php-rs…). Most of these licenses ask that their copyright notices and texts go with every copy, and the PHP License that it says "This product includes PHP software, freely available from http://www.php.net/software/".
The nativella command of the releases carries these third-party notices, gathered when it is built: nativella licenses prints them, and nativella build writes them next to the executable it builds.
Packaging Notes 1.2.0 into dist/notes…
Wrote the licenses of the software the application contains to dist/THIRD_PARTY_NOTICES.txt: distribute them with it.
Done: dist/notes
To distribute the application:
- ship
THIRD_PARTY_NOTICES.txtwith the executable, in the same archive or installer, or show it in the application, in an "about" page:App::thirdPartyNotices()returns it; - add the licenses of what your project ships: the Composer packages of
vendor/(composer licenseslists them), the front-end libraries.
The libraries of the system the executable loads are not part of it, and need no notice: glibc, libstdc++ and WebKitGTK on Linux, the frameworks of macOS. The releases attach the notices of each platform too, THIRD_PARTY_NOTICES-<platform>.txt. A nativella built without them, by cargo build rather than castor nativella:build, says so, and nativella build warns.
Important
Some of the static PHP is under the GNU Lesser General Public License 2.1, linked statically: GNU libiconv, which the iconv extension and libxml2 use, and, inside php-src, libbcmath (bcmath) and libmbfl (mbstring). The notices give the version of each, and the URL of the source archive it was built from. Among other things, the LGPL asks that whoever gets the application can use it with a modified version of these libraries. What Nativella offers for that: it is open source, and builds from source, PHP included (castor static-php:build, then castor nativella:build); the project of an application is an archive appended to that executable, which it extracts in clear, and nativella build packs again. Nativella cannot tell you what your distribution needs: ask someone who knows these licenses.