Apple

The following is a guide for building apps on Apple's MacOS and iOS operating systems.

Prerequisites

  1. Sign up for a (free) Apple Developer account.
  2. Register your devices for testing. You can use ssc list-devices command to get your Device ID (UDID). Device should be connected to your mac by wire.
  3. Create a wildcard App ID for the application you are developing.
  4. Write down your Team ID. It's in the top right corner of the website. You'll need this later.

MacOS

  • Xcode Command Line Tools. If you don't have them already, and you don't have xcode, you can run the command xcode-select --install.

iOS

Code Signing Certificates

  • Open Keychain Access application on your mac (it's in Applications/Utilities).
  • In the Keychain Access application choose Keychain Access -> Certificate Assistant -> Request a Certificate From a Certificate Authority...
  • Type you email in the User Email Address field. Other form elements are optional.
  • Choose Request is Saved to Disc and save your certificate request.

MacOS

Signing software on MacOS is optional but it's the best practice. Not signing software is like using http instead of https.

  • Create a new Developer ID Application certificate on the Apple Developers website.
  • Choose a certificate request you've created 2 steps earlier.
  • Download your certificate and double click to add it to your Keychain.

iOS

To run software on iOS, it must be signed by Xcode using the certificate data contained in a "Provisioning Profile". This is a file generated by Apple and it links app identity, certificates (used for code signing), app permissions, and phystical devices.

  • Create a new iOS Distribution (App Store and Ad Hoc) certificate on the Apple Developers website.
  • Choose a certificate request you've created 2 steps earlier.
  • Download your certificate and double click to add it to your Keychain.

When you run ssc compile --target=ios . on your project for the first time, you may see the following because you don't have a provisioning profile:

ssc compile --target=ios .
• provisioning profile not found: /Users/chicoxyzzy/dev/socketsupply/birp/./distribution.mobileprovision. Please specify a valid provisioning profile in the ios_provisioning_profile field in your `ssc.config`
  • Create a new Ad Hoc profile. Use the App ID you created with the wildcard.
  • Pick the certificate that you added to your Keychain two steps earlier.
  • Add the devices that the profile will use.
  • Add a name for your new distribution profile (we recommend to name it "distribution").
  • Download the profile and double click it. This action will open Xcode. You can close it after it's completely loaded.
  • Place your profile to your project directory (same directory as ssc.config). The profiles are secret, add your profile to .gitignore.

Configuration

MacOS

You will want to ensure the following fields are filled out in your ssc.config file. They will look something like this...

mac_team_id: Z3M838H537
mac_sign: Developer ID Application: Operator Tools Inc. (Z3M838H537)

iOS

  1. Set the ios_distribution_method value in ssc.config to the ad-hoc
  2. Set the ios_codesign_identity value in ssc.config to the certificate name as it's displayed in the Keychan or copy it from the output of security find-identity -v -p codesigning
  3. Set the ios_provisioning_profile value in ssc.config to the filename of your certificate (i.e., "distribution.mobileprovision").

Development

Create a simulator VM and launch the app in it

ssc compile --target=iossimulator -r .

Distribution And Deployment

ssc compile --target=ios -c -p -xd .

To your device

Install Apple Configurator, open it and install Automation Tools from the menu.

Connect your device and run ssc install-app <path> where path is the root directory of your application (the one where ssc.config is located).

Alternative way to install your app is to open the the Apple Configurator app and drag the inner /dist/build/[your app name].ipa/[your app name].ipa file onto your phone.

To the Apple App Store

xcrun altool --validate-app \
  -f file \
  -t platform \
  -u username [-p password] \
  [--output-format xml]
xcrun altool --upload-app \
  -f file \
  -t platform \
  -u username [-p password] \
  [—output-format xml]

Debugging

Check the [troubleshooting guide][/troubleshooting] first. You can also run lldb and attach to a process, for example...

process attach --name TestExample-dev

Logging

To see logs on either platform, open Console.app (installed on MacOS by default) and in the right side panel pick the device or computer name.

Working with the file system on iOS

iOS Application Sandboxing has a set of rules that limits access to the file system. Apps can only access files in their own sandboxed home directory.

Directory Description
Documents The app’s sandboxed documents directory. The contents of this directory is backed up by iTunes and may be set as accessable to the user via iTunes when UIFileSharingEnabled is set to true in application's info.plist.
Library The app’s sandboxed library directory. The contents of this directory are synchronised via iTunes (except the Library/Caches subdirectory, see below), but never exposed to the user.
Library/Caches The app’s sandboxed caches directory. The contents of this directory are not synchronised via iTunes, and may be deleted by the system at any time. It's a good place to store data which provides a good offline-first experience for the user.
Library/Preferences The app’s sandboxed preferences directory. The contents of this directory are synchronised via iTunes. It's purpose is to be used by the Settings app. Avoid creating your own files in this directory.
tmp The app’s sandboxed temporary directory. The contents of this directory are not synchronised via iTunes, and may be deleted by the system at any time. Although, it's recommended that you delete data which is not necessary anymore manually to minimize the space your app takes up on the file system. Use this directory to store data which is only useful during the app runtime.

Desktop Guide

Getting Started

Open a terminal, navigate to where you keep your code. Create a directory and initilaize it.

ssc init

Mobile Guide

Getting Started

Open a terminal, navigate to where you keep your code. Create a directory and initilaize it.

ssc init

This will create an ssc.config file as well as a src directory with an index.html file in it. First, open the config file in your editor and replace some of the example values with your own. Here's an example.

<!doctype html>
<html>
  <head>
    <script src="index.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <meta http-equiv="Content-Security-Policy" content="connect-src child-src 'none';">
    <link rel="stylesheet" href="index.css">
  </head>
  <body>
    <h1>Hello, World</h1>
  </body>
</html>

Note! Don't use <script type="module"></script>, iOS doesn't support it.

Coding a UI

UI is written in HTML, JS and CSS. Of course you can bring whatever tools you want to the party. But let's start simple. The easiest way to see your UI is to build this as a desktop app and show a window that runs the code.

ssc init

Development Cycle

You'll probably want to write some code, see it, change it, and repeat this flow. The typical approach is to create a watch script that rebuilds your files when there are changes. If you provide a port, the ssc command will try to load http://localhost.

ssc compile -r --port=8000 .

You'll need to tell your build script the output location. The ssc command can tell you the platform specific build destination. For example.

./myscript `ssc list-build-target .`

Building for and launching the mobile simulator

After you get your UI looking how you want. The next step is to try it out on the simulator. At this point we can use either the -ios or -android flags as well as the -simulator flag. This will createa a platform specific bundle, create and boot a simulator VM and then run your app in simulator if -r flag is provided.

ssc compile --target=iossimulator -r .

Debugging on the simulator

You can use Safari to attach the Web Inspector to the Simulator. In the Safari menu, navigate Develop -> Simulator -> index.html. This will be the exact same inspector you get while developing desktop apps.

Next Steps

API Reference

The JavaScript APIs are the same on iOS and Android. To see which methods and properties are available, check out the Mobile API docs.

Production

For specifics about production builds and deploying to devices and app stores, see either the iOS or Android guides.

Troubleshooting

macOS

Cashes

To produce a meaningful backtrace that can help debug the crash, you'll need to resign the binary with the ability to attach the lldb debugger tool. You'll also want to enable core dumps in case the analysis isn't exaustive enough.

sudo ulimit -c unlimited # enable core dumps (`ls -la /cores`)
/usr/libexec/PlistBuddy -c "Add :com.apple.security.get-task-allow bool true" tmp.entitlements
codesign -s - -f --entitlements tmp.entitlements ./path/to/your/binary
lldb ./path/to/your/binary # type `r`, then after the crash type `bt`

Clock Drift

If you're running from a VM inside MacOS you may experience clock drift and the signing tool will refuse to sign. You can set sntp to refresh more frequently with the following command...

sudo sntp -sS time.apple.com

macOS asks for password multiple times on code signing

Open Keychain Access and find your developer certificate under the My Certificates section. Expand your certificate and double click on a private key. In the dialog click Access Control tab.

codesign utility is located in the /usr/bin/codesign. To add it to the allowed applications list click the "+" button to open File Dialog, then press ⌘ + Shift + G and enter /usr/bin. Select codesign utility fom Finder.

Build or compile failures

aclocal / automake: command not found

To build ssc for ios you need automake / libtool installed.

brew install automake
brew install libtool

unable to build chain to self-signed root for signer (...)

You need the intermediate certificate that matches your code signing certificate. To find which "Worldwide Developer Relations" matches you certificate, open the signing certificate in your keychain, open this page and find the certificate that matches the details in the "Issuer" section of your certicicate.

xcrun: error: SDK "iphoneos" cannot be located

You have to configure the xcode command line tools, to do this you can run the following command

sudo xcode-select --switch /Applications/Xcode.app

fatal error: 'lib/uv/include/uv.h' file not found

Make sure your local ssc binary has been compiled with ios parameter in ./bin/install.sh ios, otherwise the uv.h does not exist.

unable to find utility simctl

You need to have XCode installed on your macbook.

You have not agreed to the Xcode license agreements, please run 'sudo xcodebuild -license' from within a Terminal window to review and agree to the Xcode license agreements.

You can run sudo xcodebuild -license to agree to the license.

Multiple Password Prompts

If macOS is asking you a password every time you run the command with -c flag, follow these instructions

Application crashes on start

If you use iTerm2 you can get your app crashing with

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSBluetoothAlwaysUsageDescription key with a string value explaining to the user how the app uses this data.

Command line apps inherit their permissions from iTerm, so you need to grant Bluetooth permission to iTerm in macOS system preferences. Go to Security & Privacy, open the Privacy tab and select Bluetooth. Press the "+" button and add iTerm to the apps list.

Windows

Development Environment

clang++ version 14 required for building.

You will need build tools

The WebView2LoaderStatic.lib file was sourced from this package.

Cannot Run Scripts

If the app cannot be loaded because running scripts is disabled on this system.

./bin/bootstrap.ps1 : File C:\Users\user\sources\socket-sdk\bin\bootstrap.ps1 cannot be loaded because running scripts is
disabled on this system. For more information, see about_Execution_Policies at
https:/go.microsoft.com/fwlink/?LinkID=135170.

Then you can follow https://superuser.com/a/106363

  1. Start Windows PowerShell with the "Run as Administrator" option.
  2. set-executionpolicy remotesigned

MSVC

Setting up the MSVC build environment from Git Bash

You can leverage the MSVC build tools (clang++) and environment headers directly in Git Bash by loading it into your shell environment directly. This is possible by running the following command:

source bin/mscv-bash-env.sh

The bin/install.sh shell script should work for compiling the ssc tool. It is also recommneded to initialize this environment when building applications with ssc from the CLI so the correct build tools can be used which ensures header and library paths for the compiler

Linux

Build failures

If you are getting a failure that the build tool cant locate your compiler, try making sure that the CXX environment variable is set to the location of your C++ compiler (which g++, or which c++).

The latest version of MacOS should have installed C++ for you. But on Linux you may need to update some packages. To ensure you have the latest clang compiler and libraries you can try the follwing...

For debian/ubuntu, before you install the packages, you may want to add these software update repos here to the software updater.

Note that clang version 14 is only available on Ubuntu 22.04. Use clang 13 for prior versions of Ubuntu.

Ubuntu

sudo apt install \
  build-essential \
  clang-14 \
  libc++1-14-dev \
  libc++abi-14-dev \
  libwebkit2gtk-4.1-dev

Arch/Manjaro

arch uses the latest versions, so just install base-devel

sudo pacman -S base-devel

Multiple g++ versions

If you've tried running the above apt install and you get an error related Unable to locate package then you can also install multiple versions of G++ on your system.

sudo apt install software-properties-common
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt install gcc-9 g++-9 gcc-10 g++-10 gcc-11 g++-11 gcc-12 g++-12

Then you can set your C++ compiler as g++-12

# Add this to bashrc
export CXX=g++-12

Can't find Webkit

If you run into an error about not finding webkit & gtk like this:

Package webkit2gtk-4.1 was not found in the pkg-config search path.
Perhaps you should add the directory containing `webkit2gtk-4.1.pc'
to the PKG_CONFIG_PATH environment variable
No package 'webkit2gtk-4.1' found
In file included from /home/runner/.config/socket-sdk/src/main.cc:9:
/home/runner/.config/socket-sdk/src/linux.hh:4:10: fatal error: JavaScriptCore/JavaScript.h: No such file or directory
    4 | #include <JavaScriptCore/JavaScript.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

Then you will want to install those dependencies

sudo apt-get install libwebkit2gtk-4.1-dev

FAQ

What is a Modern Runtime for Web Apps?

Modern does not refer to how recently any component of the software was written. For example we use libuv which certainly isn't new. In fact, it's considered boring and stable. It's the approach that's modern.

The client-server model was more relevant when computers were fewer and less powerful. Now we are surrounded by billions of computers that can connect directly to each other, so servers are becoming less relevant no mater how fast they are.

How can a peer replace a server?

A peer should not be asked to handle the same kind of work-loads as a server. If you develop an app that monopolizes a user's device, they will be unhappy, regardless of what architecture you are using. Peers should handle smaller work-loads in shorter bursts.

With Peer To Peer networks, growth increases availability and compute capacity. Despite how many peers join your network, you should continue to design with the assumption that peers are unreliable and infrequently online.

Why not Electron?

Electron's binary size and memory footprint are far from acceptable for most developers. The bulk of the weight comes from the decision to build-in V8 and a custom distribution of node.js.

Why not Tauri?

Tauri is a project for people who want to write Rust. Socket SDK is for Web Developers who want to create connected apps with HTML, CSS and JavaScript.

Why not Rust?

Webview is C++, so are the platforms that it runs on. The memory safety offered by Rust is great but becomes irrelevant when it's just a thin wrapper around a world of C++. It is possible to write C++ that is as safe as Rust, it's just a hell of a lot harder.

Does Webview render consistently across platforms?

Historically it did not. Now it does.

Is it secure?

Yes. As much as anything else. Just NEVER try to build a browser. NEVER evaluate arbitrary code. ALWAYS use a strong CSP. ALWAYS sanitize any data that will be rendered in a UI.

Will you support a specific feature?

Possibly, create a PR and make an argument for why the feature is relevant to everyone who would use this project.

How can Webview based apps compete with the quality of native apps?

Native apps require an enormous amount of developer effort if the developer wants their app to run across multiple platforms. Socket lowers the barrier to entry and lets in the worlds largest developer community. With care, avoiding bloated frameworks, a web-based app can run as well as any native app.

Why should I care that P2P is free? AWS is almost free!

AWS is nearly free (until you have any kind of growth). But they still require your credit card and a lot of personally identifiable information. P2P is the only free and permissionless way to build networked software.

How effective are distributed networks at hosting the long tail of rarely-accessed content?

In networks like BitTorrent, rarely-accessed content (content accessed less frequently than 72 hours) becomes unavailable as the few peers hosting that content drop offline.

For this case, we enable developers to build hybrid networks. In hybrid networks, developers can choose to keep a centralized copy of all content. This keeps rarely-accessed content always available. For popular content, a distributed swarm of users’ devices also assist in distribution, reducing the cost of serving that content from a central location.