Rust on iOS

Porting process

Finally got working Rust cross-compiler for iOS so now it is possible to create static libraries which could be used from Objective C. For now only armv7 architecture is supported (although there are upcoming commits in “try” branch which will update LLVM version with ARM64 support right from Apple).

These were main pain points:

  • Slow full rebuild… Yep, I know, I know, 3 stage bootstrapping to be extremely optimized but still… it was especially painful on initial stage while experimenting with built options and LLVM patching.

  • TLS isn’t supported on armv7 so it should be emulated. Initially I’ve started adding it to LLVM and with help from Tim Northover and Dan Olson even got it working. (BTW, Dan knows a lot about this topic as he got a working D compiler for iOS, so if you’re interested in modern compiled language for iOS - you can try it too). Just to discover that actually Rust has built-in TLS “emulation” support (actually using the same technique as in LLVM patches)… Grr, hate myself for not checking this before messing with LLVM.

  • There were absolutely crazy crashes hard to debug because some kind linker errors/misconfiguration when functions were resolved correctly but all the data was relocated incorrectly and contained garbage.

  • There were mystical crashes in hash function which automagically disappeared once I’ve increased optimization level.

  • The final show-stopper was happening in runtime finalization routine - it always crashed on misaligned data during mutex locking. The reason was that mutex opaque data was copied as a plain data. It wasn’t the case on desktop OSes but seemed to be a big difference on iOS. There is a simple fix for native runtime and should be similar fix for green/rustuv.

What works

  • armv7 only (ARM64 port should be quite easy to introduce)

  • it is possible to compile standard libraries and use them

  • “native”-based runtime

  • creating static libraries which could be used from iOS applications

Known issues

  • green/rustuv runtime crashes because of incorrect mutex implementation

  • segmented stacks aren’t working

  • it might require additional manual linking

  • no support for simulator yet

  • it only works on common compiler flags. It is critical to have exactly –opt-level 2 (or -O) as both decreasing and increasing opt level may cause a lot of unexplainable issues

Shut up and take my money Build instructions

clone and create build dir

1
2
3
4
5
git clone git@github.com/vhbit/rust.git
cd rust
git checkout ios
mkdir build_ios
cd build_ios

configure

1
../configure --target=arm-apple-ios

build

1
make

or (for 4 core CPU)

1
make -j4

There is a sample project with instructions on how to integrate.

Thanks

Special thanks to Tim Northover (ARM TLS), Dan Olson (ARM TLS), Alex Crichton (Rust internals) and my wife for being patient.

Joe Armstrong об ООП, Concurrency

Две части замечательной беседы с Джо Армстронгом (создателем erlang’а) об объектно-ориентированном программировании и почему оно скоро упрется и вынуждено будет смещаться в сторону функционального.

Один из интересных тезисов - это то, что сейчас нас начинает поджимать железо, если раньше мощности росли в количестве гигагерц, то сейчас все идет за счет увеличения числа ядер. А это провоцирует на переход к concurrent-based программированию (есть, кстати, нормальный русский термин для этого?), где императивщина в чистом виде начинает загибаться из-за возрастающей сложности разнообразных локов и защит.

Материал 2007 года и этим вдвойне интересней, т.к. тренды, о которых говорит Джо, из гипотетических становятся все более и более ощутимыми.

Переопределяем метод класса в рантайме

В кои-то веки потребовалось в рантайме переопределять методы класса. В документации сразу нашлась подходящая функция:

1
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

единственный аргумент, который может смутить - это types, который задает типы аргументов и возвращаемого значения в закодированном текстовом виде. Нужные значения можно посмотреть либо в документации, либо исппользовать @encode.

Вторая тонкость оказалась в том, что эта функция добавляет (или переопределяет) метод экземпляра, а что же делать если нужно заменить метод самого класса?

Правильно, получить метакласс с помощью object_getClass(ourClass) и заменить его метод как обычно :)

Замена цветов с помощью CIColorCube

Несмотря на то, что фильтр достаточно простой и эффективный, найти примеры кода с его использованием удалось чисто случайно уже после того, как все заработало :-)

Куб предназначен для замены множества цветов. R, G, B компоненты исходного цвета являются трехмерными координатами нового цвета, который задается в виде 4 float’ов (RGBA).

В приведенном примере происходит хитрая замена цвета со всеми оттенками. Для удобства используется работа с цветом в формате HSV, т.к. в этом случае гораздо легче выцеплять схожие цвета - они будут попадать в сектор.

Dash - последний штрих документации

Во время испытания AppCode (это вообще отдельная тема для разговора) столкнулся с тем, что неудобно держать открытым еще и xCode для просмотра документации. Когда-то давно пробовал Ingredients, но как-то не зацепило + были проблемы со стабильностью. Набрел на Dash - утилитку, без которой уже не представляю свою ежедневную работу. Недавно как раз обновилась до 1.3 и появилась в Mac AppStore

Итоги 2011 года на встрече RADUG

К сожалению, сам не попаду, но всячески рекомендую подвести итоги 2011 года в компании Russian Apple Developer’ов.

Дата: 7 декабря Начало: 19.00 Место проведения: Москва, Digital October

Мы традиционно завершаем год встречей в формате блиц-докладов. Приглашаем девелоперов, дизайнеров, менеджеров и всех энтузиастов iOS и Mac OS X. Регистрация на встречу. Участие во встрече как всегда бесплатное.

Ключевые люди российской индустрии расскажут, чем запомнился 2011 год, что было важными событиями и кто были главные люди и какие планы на следующий год. Мы ждем, что Вы также поделитесь с сообществом своим опытом, достижениями и открытиями.

Предновогодняя встреча RADUG – самое правильное место, чтобы оставаться в курсе происходящего, заявить о себе и завязать контакты. После встречи как всегда After Party – планируйте свое время!

Обратите внимание, что в Digital October, перед встречей RADUG пройдет еще одно мероприятие, посвященное мобильной разработке - Mobile Developer Day. Конференция платная, но в ее рамках есть бесплатная секция Developer Garage, включающая два мастер-класса по разработке приложений под iOS. Если есть желание – перед встречей RADUG можно заглянуть также и туда.

sParking 1.0

Выпустили наконец-то первую версию. Процесс очень простой - ставите на стены гаража маркер (или 2 - на вход и на стоп), настраиваете и проверяете, чтобы они опознавались. После этого при каждом въезде iPhone будет подсказывать где самое время остановиться :)

Вот как это выглядит:

Пока что iPhone 4 only. Ах да :) Ссылочка

Волшебник страны Xcode

wox (Wizard Of Xcode) - восхительно удобная штучка для сборки iOS проектов из консоли, что весьма актуально для всяких автоматизаций.

Написана на ruby, установка

1
gem install wox

После этого создаем Rakefile, самый навороченный на данный момент пример:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require 'wox'

Wox::Tasks.create :info_plist => 'project-Info.plist', :sdk => 'iphoneos' do
    build :debug, :configuration => 'Debug - Local Server'
    build :release, :developer_certificate => 'iPhone Developer: Valerii Hiora (8GA39LD1DZ)', :configuration => 'Release' do
        ipa :app_store, :provisioning_profile => 'App Store'
        ipa :adhoc, :provisioning_profile => 'Ad Hoc' do
            testflight :publish, :api_token => 'your_token',
                :team_token => 'your_testers_team_token',
                :notes => proc { File.read("CHANGELOG") },
                :distribution_lists => %w[AlphaTesters],
                :notify => true
        end
    end
end

Код в принципе понятен без особых комментариев, настроить можно абсолютно все - сертификаты, какие provisioning profiles использовать, можно даже сразу публиковать на Testflight (о нем писал раньше). Вложенные таски наследуют настройки родителей, т.е. testflight:publish будет собирать с использованием provisioning profile из ipa:adhoc и подписываться это будет сертификатом, указанным в build:release. В случае чего любую настройку можно переопределять.

Примеры использования:

Собрать дебажную версию:

1
rake build:debug

Подготовить ipa для заливки в AppStore:

1
rake ipa:appstore

Подготовить adhoc ipa и залить его на Testflight

1
rake testflight:publish

Посмотреть список всех доступных тасков:

1
2
3
4
5
6
7
8
9
$ rake -T
rake build:debug          # Build customiphone 1.0 with Debug - Local Server configuration
rake build:release        # Build customiphone 1.0 with Release configuration
rake info:configurations  # List available configurations
rake info:sdks            # List available sdks
rake info:targets         # List project targets
rake ipa:adhoc            # Creates build/project-1.0-Release-adhoc.ipa
rake ipa:appstore         # Creates build/project-1.0-Release-app_store.ipa
rake testflight:publish   # Publishes build/project-1.0-Release-adhoc.ipa to testflight

По умолчанию версия продукта берется из Info.plist, но ее можно переопределить с помощью

1
:version => 1.0.3

Последний штрих - генерация правильного changelog’а для Testflight-публикации - остается домашним заданием :)

[Перевод] Усовершенствуйте свой Git Workflow

Настраиваем git-flow

Установить git-flow на OS X проще простого с помощью homebrew

brew install git-flow

На страничке проекта git-flow Вы можете найти инструкции по установке на Linux и Windows.

Установка git-flow добавляет несколько очень удобных git-команд для создания и управления ветками фич и релизов. Новый git репозиторий создается с веткой master. По умолчанию в git-flow эта ветка используется для production-а. В свою очередь основная разработка происходит в ветке develop. Следует отметить, что git-flow не более чем серия удобных “сокращений” для переключения между этими ветками и перебрасывания изменений из одной в другую.

Кнопка “Follow Us on Twitter”

Код для запуска уже установленного на iOS твиттер-клиента:

Идея взята отсюда, добавлен один клиент и удалено много копипаста :-)

Если устраивает открытие в Safari - можно откомментировать последний элемент, на этом кастомизация заканчивается.

Вообще поскольку URL в данный момент - это единственный способ для приложений взаимодействовать между собой, рекомендую поглядывать на handleOpenUrl: и подборку схем от Адриана Космачевского