phoenix 开发API种类(三语言)phoenix api 结合数据库

前言

做iOS开发的朋友们都通晓,近来流行的Xcode7,新建项目默许就开辟了bitcode设置.而且超过一半开发者都被那几个出人意表的bitcode成效给坑过造成项目编译败北,而这么些因为bitcode而编译退步的的门类都有一个共同点,就是链接了第三方二进制的库或者框架,而那么些框架或者库恰好没有包括bitcode的事物(暂且称为东西),从而造成品种编译不成功.所以每当遭逢这些景况时候一大半人都是平素设置Xcode关闭bitcode功能,全部不生成bitcode.也不去追究这一开关背后隐藏的原理.中枪的请点个赞.

LLVM是方今苹果采纳的编译器工具链,Bitcode是LLVM编译器的中间代码的一种编码,LLVM的前端可以知道为C/C++/OC/斯维夫特等编程语言,LLVM的后端可以领略为各类芯片平台上的汇编指令或者可举行机器指令数据,那么,BitCode就是位于这两边间接的高中级码.
LLVM的编译工作规律是前者负责把项目程序源代码翻译成Bitcode中间码,然后再依照不相同对象机器芯片平台转换为相应的汇编指令以及翻译为机械码.那样设计就足以让LLVM成为了一个编译器架构,可以一挥而就的在LLVM架构之上发明新的言语(前端),以及在LLVM架构上面帮助新的CPU(后端)指令输出,即便Bitcode仅仅只是一个中间码无法在其余平台上运行,可是它可以转正为其它被襄助的CPU架构,包涵现在还没被发明的CPU架构,也就是说现在开拓Bitcode成效交由一个App到利用集团,将来假若苹果新出了一款手机并CPU也是全新设计的,在苹果后台服务器一样可以从那么些App的Bitcode伊始编译转化为新CPU上的可执行程序,可供新手机用户下载运行这几个App.

概述

介绍了 api 的各个写法之后,下边介绍构建 api 时与数据库连接的法子。

上面选用的工程的总体代码已经了解在:
http://git.oschina.net/wangyubin/phoenix-api

历史回看

在黑莓出来以前,苹果主要的编译器技术是用经过多少立异的GCC工具链来把Objective-C语言编写的代码编译出所指定的机器处理器上原生的可举行程序.编译器发生的可执行程序叫做”Fat
Binaries”–类似于Windows下PE格式的exe和Linux下的ELF格式的二进制,不一致的是,一个”Fat
Binary”可以包涵同一个主次的洋洋本子,所以同一个可执行文件可以在分化的处理器上运行.紧要就是以此技能让苹果的硬件很不难的从PowerPC迁移到PowerPC64的电脑,以及后来再迁移到速龙和英特尔64处理器.这一个方案带来的负面影响就是同一个文本中存了多份可实施代码,除了当前机械可实施的那一份之外其他都是不行的,白占空间.
这么些在商海上被称呼”Universal
Binary”,在苹果从PowerPC迁移到AMD处理器的事体开头存在的(一个二进制文件既涵盖一份PowerPC版本和一份AMD版本).渐渐的新生又帮衬同时涵盖英特尔32bit和AMD 64bit. 在一个Fat
binary中,又操作系统运行时依照处理器类型动态接纳正确的二进制版本来运行,不过应用程序要援助不相同平台的微处理器的话,应用程序本身要多占用部分空间.当然也有部分瘦身的工具,比如lipo,能够用来移除fat
binary中那几个当前机械中不被协理的或者多余的可举行代码达到瘦身目的,lipo不会改变程序执行逻辑,仅仅只是文件的大小瘦身.

ecto 简介

ecto 其实是单身于 phoenix framework 的,它是 elixir
语言落成的用于访问数据库的框架,类似于 ORM 不过和价值观的 ORM
又有点不相同。 可以如此清楚,它是使用了 elixir
语言的动态性和函数式的特点,参考了观念的 ORM
的优势后而支出的新一代数据库访问层。

编译器现状

乘势移动装备移动互联网的递进发展,现在活动设备中的程序大小变得愈加紧要了,首即使因为运动设备中不会有电脑上那么大的一个硬盘驱动器.还有就是苹果已经从原本的ARM处理器迁移到自己设计的A4,A5,A5X,A6,A7,A8,A8X,A9,A9X以及继续的A10处理器,他们的指令集已经发生了改动和原始ARM设计的有所不同,所有的那些变迁都被iOS操作系统底层以及Xcode/LLVM编译工具向上层程序员一定程度的晶莹了,编译出来的次序会包罗众多举办代码版本.当面对那么些题目后,苹果投入大批量资金迁移到LLVM编译器架构并动用bitcode的须求性进一步大.从最伊始的把OPENGL编译为特定的GPU指令到把Clang编译器(LLCM的C/OC编译前端)辅助Objective-C的改良并视作Xcode的默认编译器.

LLVM提供了一个虚构指令集机制,它能够翻译出指定的所支撑的微处理器架构的施行代码(机器码).这几个就使得为iOS应用程序的编译开发一个完全基于LLVM架构的工具链成为可能.而LLVM的那几个编造的通用的指令集能够用很多种象征格式:

  • 何谓IR的公文表示的汇编格式(像汇编语言);
  • 转换为二进制数据表示的格式(像目标代码),那些二进制格式就是我们所说的bitcode.

Bitcode和观念的可实施命令集差别,他维护的是函数功能的类型和签字,比如,传统可实施命令集中,一比比皆是(<=8)的布尔值可以削减存储到单个字节中,不过在bitcode中他们是个别独立表示的.其余,逻辑运算操作(比如寄存器清零操作)也由他们相应的逻辑表示方法($R=0);当那些BitCode要更换为一定机器平台的指令集时,他可以用经过针对一定机器平台优化过的汇编指令来替代:xor eax, eax.(那几个汇编指令同样是寄存器<eax>清零操作).

然则bitcode他也不是全然独立于计算机平台和调用约定的.寄存器的尺寸在指令集中是一个一定紧要的特性,众所周知,64bit寄存器可以比32bit寄存器存储越多的数额,生成64bit平台的bitcode和32bit平台的bitcode是尽人皆知分歧的,还有,调用约定可以根据函数定义或者函数调用来定义,那么些可以规定函数的参数传递是传寄存器值吗仍然压栈.
一些编程语言还有一些像sizeof(long)这样的预处理指令,那一个将在bitcode生成在此之前前被翻译.一般情况下,对于支撑fastcc(fast
calling convention)调用的64bit平台会生成与其相同的bitcode代码.

ecto 的八个至关主要组件

  1. Ecto.Repo 数据库包装器, 通过它能够执行数据库的增删改查,
    通过它配备数据库连接
  2. Ecto.Schema 那是 ORM 的主导,定义了操作对象和尾部数据库表之间的映照
  3. Ecto.Changeset 那是 Ecto 的一个更新的地点,在 Changeset
    中,可以定义校验数据层合法性的法门,在真正写入数据库以前,对数码开展校验
  4. Ecto.Query 以 elixir 语法编写的询问,可以避免 SQL 注入等科普问题

苹果的渴求

到此,让大家思想一下,为何苹果默许须要watchOS和tvOS的App要上传bitcode?
因为把bitcode上传到他自己的要旨服务器后,他可以为对象安装App的设施举办优化二进制,减小安装包的下载大小,当然iOS开发者也可以上传多个版本而不是包裹到单个包里,可是这么会占据越多的囤积空间.
最关键的是允许苹果可以在后台服务器对应用程序进行签约,而不用导出任何密钥到巅峰开发者那.

上传到服务器的bitcode给苹果带来更便宜是:
以后新布署了新指令集的新CPU,可以三番五次从那份bitcode初阶编译出新CPU上实施的可执行文件,以供用户下载安装.
而是bitcode给开发者带来的孤苦之处就是:
没用bitcode从前,当应用程序奔溃后,开发者可以依照取得的的奔溃日志再配上上传到苹果服务器的二进制文件的调节符号表音讯可以回复程序运行进度到奔溃时后调用栈音讯,对问题展开固定排查.可是用了bitcode之后,用户安装的二进制不是开发者那边转移的,而是苹果服务器经过优化后变更的,其相应的调试符号音讯丢失了,也就无法进行前边说的苏醒奔溃现场找原因了.

当下,watchOS和tvOS应用公布必须上传带bitcode版本的包.iOS应用揭橥对bitcode的渴求是可选的,用户可以在Xcode的品种设置中关闭.
相当于在编译的时候加一个标志:embed-bitcode-marker(调试构建)
embed-bitcode(打包/真机构建).那些在clang编译器的参数是-fembed-bitcode,swift编译器的参数是-embed-bitcode.

ecto 使用示例

执行出真知

咱俩依旧应当实际弄八个测试代码进行实施和检查一下相比较好.做三次测试,第五回准备三个C语言源代码继续测试;第二次把内部一个变迁为汇编语言源代码后再一个C代码和一个汇编代码一起重复之前的测试步骤进行对照校验差距.

  • 1 . 如下八个百分之百是Objective-C代码:

test.m :

#import <Foundation/Foundation.h>
void greeting(void)
{
    NSLog(@"hello world!");
}

demo.m :

#import <Foundation/Foundation.h>
void demo(void)
{
    NSLog(@"demo func");
}

用Clang编译成 ARM64 格式且带bitcode的目的文件test.o demo.o:

wuqiong:~ apple$ xcrun -sdk iphoneos clang -arch arm64 -fembed-bitcode -c test.m demo.m

下一场把三个对象文件打包为一个静态库文件:

wuqiong:~ apple$ xcrun -sdk iphoneos ar  -r libTest.a test.o demo.o
ar: creating archive libTest.a

用Shell命令otool查看目的文件中是还是不是包蕴bitcode段:

wuqiong:~ apple$ otool -l test.o |grep bitcode
  sectname __bitcode
  sectname __bitcode

只要见到输出了2行sectname __bitcode,就是表明那静态库中的三个目的文件包蕴了bitcode.

  • 2.底下把其中一个demo.m换成汇编语言再加入编译:

用上边的授命把demo.m的C代码转换为ARM64汇编语言格式demo.s:

wuqiong:~ apple$ xcrun -sdk iphoneos clang -arch arm64 -S demo.m
wuqiong:~ apple$ cat demo.s
    .section    __TEXT,__text,regular,pure_instructions
    .ios_version_min 9, 2
    .globl  _demo
    .align  2
_demo:                                  ; @demo
    .cfi_startproc
; BB#0:
    stp x29, x30, [sp, #-16]!
    mov  x29, sp
Ltmp0:
    .cfi_def_cfa w29, 16
Ltmp1:
    .cfi_offset w30, -8
Ltmp2:
    .cfi_offset w29, -16
    adrp    x0, L__unnamed_cfstring_@PAGE
    add x0, x0, L__unnamed_cfstring_@PAGEOFF
    bl  _NSLog
    ldp x29, x30, [sp], #16
    ret
    .cfi_endproc

    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ; @.str
    .asciz  "demo func"

    .section    __DATA,__cfstring
    .align  4                       ; @_unnamed_cfstring_
L__unnamed_cfstring_:
    .quad   ___CFConstantStringClassReference
    .long   1992                    ; 0x7c8
    .space  4
    .quad   L_.str
    .quad   9                       ; 0x9

    .section    __DATA,__objc_imageinfo,regular,no_dead_strip
L_OBJC_IMAGE_INFO:
    .long   0
    .long   0


.subsections_via_symbol

然后删除demo.m这个C源代码,仅留下test.mdemo.s:

wuqiong:~ apple$ rm demo.m

近期,大家来把test.m其一C源代码和dmeo.s本条汇编源代码来共同带着-fembed-bitcode参数来生成靶子代码并打包为一个静态库:

wuqiong:~ apple$ xcrun -sdk iphoneos clang -arch arm64 -fembed-bitcode -c test.m demo.s
wuqiong:~ apple$ xcrun -sdk iphoneos ar -r libTest.a test.o demo.o

然后大家再运行otool工具来检查那一个新的静态库中带有的2个目的文件是不是都带有bitcode段:

wuqiong:~ apple$ ar -t libTest.a
__.SYMDEF SORTED
test.o
demo.o
wuqiong:~ apple$ otool -l libTest.a | grep bitcode
  sectname __bitcode

很意外,本次,唯有一行sectname __bitcode输出,那就印证那七个目的文件,有一个不带有bitcode段,哪怕大家在编译的时候指定了参数-fembed-bitcode也绝非用.至于具体是哪一个不带bitcode段,大家终将通晓就是越发从ARM64汇编语言编译过来的目标文件不带.

那么就查获一个结论,bitcode的浮动,是由汇编语言以上的上层语言编译而来,和最前头所说的那样,他是上层语言与汇编语言(机器语言)之间的一个中级码.

此时此刻我们常见的iOS应用开发中,一般不会须求用到汇编层面去优化的代码.所以我们第一关怀第三方(开源)C代码,更加是音视频编码解码那一个总结密集型项目代码,关键计算的代码针对一定平台都有对应平台的汇编版本完结,当然也有C的贯彻,然则默许编译一般都是用的汇编版本,那样就会导致大家在编译那一个开源代码的时候就是你带了-fembed-bitcode参数也仅仅只是让项目中的部分C代码的对象文件带了bitcode段,而那小数的汇编代码的目的文件一律不带bitcode段,那样编译出这一个库交给上层开发者使用的时候,就会冒出在包装上传或者真机调试的时候因为Xcode默认开了bitcode功效而链接败北,导致不可能真机调试或者不可能上传应用到AppStore.

创建示范工程

  • 新建工程

    $ mix new ecto_sample

  • 添加信赖 (mix.exs)

    defp deps do
    [

    {:postgrex, ">= 0.0.0"},
    {:ecto, "~> 2.0.0"}
    

    ]
    end

  • 设置使用新闻 (mix.exs)

    def application do
    [applications: [:logger, :postgrex, :ecto]]
    end

  • 获取看重包

    $ mix deps.get

此文之初衷

近些年在指导自己大卫(大卫(David))营战友们做手机音视频直播的App,调试的时候手机采集音视频,视频用h264编码,音频接纳aac编码,通过RTMP协和往斗鱼直播频道发表媒体流,项目须要用FFMPEGlibx264三个开源项目,在编译为iOS框架库提需求学生用的时候,他们碰着了bitcode的题材,纵然可以选用直接关闭bitcode来避免不当,不过战友的求知欲必须满意,格物致知,必须让其知其究竟.

libx264是VideoLan基金会保管的一个视频编解码的开源项目,其大气施用了逐一平台的多媒体汇编指令展开了优化,在编译为不带bitcode的库的时候,完全按官方autotools编译方法是一向不其余问题的;编译全带bitcode的库的时候大家只好关门汇编优化,在履行./configure等级可以添加--disable-asm参数来禁用汇编.不过,那一个选项在configure本子中的已毕机制有题目.导致其如故调用了汇编的函数,不过汇编的代码却未曾编译进去,从而会导致项目为真机构建和打包的链接阶段会揭发找不到符号的荒谬,那样就不能到位一石二鸟.出于轻微程度的性变态影响,故把前边的FFMPEGlibx264项目标编译脚本举行了立异和打补丁.近来已经得以完毕一键编译出带全部bitcode的FFMPEG和libx264的框架了.

FFmpeg亟待信赖libx264.

机关编译脚本项目地方放在github:
https://github.com/Diveinedu-CN/FFmpeg-iOS-build-script.git

由于时间和字数原因,关于其余更加多详细的音讯就不苗条道来了.

大卫(David)营教育Slogan: Dive in education!

更多iOS开发精品作品:大卫(David)营技术博客

数据库连接配置

# vi config/config.exs
config :ecto_sample, ecto_repos: [EctoSample.Repo]

config :ecto_sample, EctoSample.Repo,
  adapter: Ecto.Adapters.Postgres,
  database: "ecto_sample",
  username: "iotalab",
  password: "iotalab",
  hostname: "localhost"

配备好数据库连接之后,就可以在命令行下创造数据库了

$ mix ecto.create

创建 model 和 migration 代码

首先,通过命令行创设一个用来生成表的的 users module。

$ mix ecto.gen.migration users

本条命令会在 priv/repo/migrations 下自动生成 migration
脚本,只然而脚本是空的。 下边先创造 users 表的内容,然后填充 migration
脚本的情节

# vi lib/ecto_models.ex
defmodule EctoSample.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :password, :string
    field :age, :integer

    timestamps
  end
end

# vi priv/repo/migrations/20160912131700_users.exs  这个文件是由上一条命令产生的
defmodule EctoSample.Repo.Migrations.Users do
  use Ecto.Migration

  def up do
    create table(:users) do
      add :name, :string
      add :password, :string
      add :age, :integer
      timestamps
    end
  end

  def down do
    drop table(:users)
  end
end

成立数量库表

始建命令格外简单

$ mix ecto.migrate

接纳示例

创办了一个简便的表之后,就足以在指令行下测试是不是可以操作数据库了。
下边演示了增产一个 user 和 删除一个 user 的经过。

$ iex -S mix
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> u = %EctoSample.User{name: "wyb", password: "passwd", age: 33}
%EctoSample.User{__meta__: #Ecto.Schema.Metadata<:built, "users">, age: 33,
 id: nil, inserted_at: nil, name: "wyb", password: "passwd", updated_at: nil}


iex(2)> EctoSample.Repo.insert(u)

22:09:51.433 [debug] QUERY OK db=4.4ms
INSERT INTO "users" ("age","name","password","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" [33, "wyb", "passwd", {{2016, 9, 12}, {14, 9, 51, 0}}, {{2016, 9, 12}, {14, 9, 51, 0}}]
{:ok,
 %EctoSample.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, age: 33,
  id: 3, inserted_at: #Ecto.DateTime<2016-09-12 14:09:51>, name: "wyb",
  password: "passwd", updated_at: #Ecto.DateTime<2016-09-12 14:09:51>}}


iex(3)> u = %EctoSample.User{id: 3}
%EctoSample.User{__meta__: #Ecto.Schema.Metadata<:built, "users">, age: nil,
 id: 3, inserted_at: nil, name: nil, password: nil, updated_at: nil}


iex(4)> EctoSample.Repo.delete(u)

22:11:28.960 [debug] QUERY OK db=3.4ms
DELETE FROM "users" WHERE "id" = $1 [3]
{:ok,
 %EctoSample.User{__meta__: #Ecto.Schema.Metadata<:deleted, "users">, age: nil,
  id: 3, inserted_at: nil, name: nil, password: nil, updated_at: nil}}

补偿说明

除外修改下面的文本之外,还有上面2个地点须要修改,否则 Ecto山姆(Sam)ple
模块不会加载:

# vi lib/ecto_sample.ex
defmodule EctoSample do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(EctoSample.Repo, []),
    ]
    opts = [strategy: :one_for_one, name: EctoTest.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

def application do
  [applications: [:logger, :postgrex, :ecto],
   mod: {EctoSample, []}]   # <===  IMPORTANT !!!
end

api with postgresql

postgresql 安装与布置

以下安装配置是按照 CentOS7 的

# 安装 package
$ sudo yum install postgresql-server

# init db
$ sudo su - postgres
$ initdb -D /var/lib/pgsql/data

# start db
$ sudo systemctl start postgresql

# create user and database
$ sudo su - postgres
$ psql -U postgres -W       # password is also "postgres"
postgres=# CREATE USER iotalab WITH PASSWORD 'iotalab';
postgres=# CREATE DATABASE test OWNER iotalab ENCODING 'UTF8';

安装可以局域网内访问

$ sudo su - postgres 
$ cd /var/lib/pgsql/data

vim pg_hba.conf

host    all             all             0.0.0.0/0            md5

vim postgresql.conf

listen_addresses = '*'

长距离连接不上时试试禁用 iptables

$ sudo systemctl stop iptables

创建 数据库和表

  1. 给这几个工程加上 数据库的匡助其实制造的工程的时候,默许就是支撑数据库的。然则前边的演示不须求数据库,所以创设那几个工程的时候用了
    –no-ecto 的参数。
    重新创制工程,并将已写的代码复制进去即可,这一次成立工程时不加
    –no-ecto 参数。

    $ mix phoenix.new phoenix_api
    
  2. 布置数据库连接并创建数据库 修改文件 config/dev.exs

    # Configure your database
    config :phoenix_api, PhoenixApi.Repo,
      adapter: Ecto.Adapters.Postgres,
      username: "iotalab",
      password: "iotalab",
      database: "dev_db",
      hostname: "localhost",
      pool_size: 10
    

    始建数据库

    $ mix ecto.create
    
  3. 开创一张用来测试的表

    $ mix phoenix.gen.model User users name:string email:string age:integer
    * creating web/models/user.ex
    * creating test/models/user_test.exs
    * creating priv/repo/migrations/20160913230129_create_user.exs
    

    查看生成的文本,已经按照命令行的中参数,生成了对应的靶子,可以发现其间自动添加了
    timestamps 方法,这几个艺术是自行抬高一些 updated_at, inserted_at
    等通用时间字段。 然后通过命令行创制表:

    $  mix ecto.migrate
    
    07:10:52.527 [info]  == Running PhoenixApi.Repo.Migrations.CreateUser.change/0 forward
    
    07:10:52.527 [info]  create table users
    
    07:10:52.537 [info]  == Migrated in 0.0s
    

增删改查 示例

在测试代码中构造了 增删改查 的测试 case,然后用 mix test
命令来展开测试。
具体代码可以参见:http://git.oschina.net/wangyubin/phoenix-api/blob/master/test/models/user_test.exs

总结

应用 ecto 模块,操作数据库分外不难,不过,写岀杰出 api 的重点仍旧在于
api
的设计上,学习那些框架的意义是在于把有些通用繁琐的劳作交给框架来处理,可以让我们把首要的生命力放在工作代码的构建上。

迄今为止,phoenix framework api 种类的3篇也终结了。

来源:http://blog.iotalabs.io/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图