about 6 years ago

設定方式和上一篇一樣:
clang_complete裡的cindex.py、init.py、enumerations.py抓下來放在./clang的資料夾下,再指定libclang.dylib的位置(下面的path變數),就可以開始玩了

import sys
from clang.cindex import Index, SourceLocation, Cursor, File, CursorKind, TypeKind, Config, LibclangError

def getQuickFix(diagnostic):
  # Some diagnostics have no file, e.g. "too many errors emitted, stopping now"

  if diagnostic.location.file:
    filename = diagnostic.location.file.name
  else:
    filename = ""

  if diagnostic.severity == diagnostic.Ignored:
    type = 'I'
  elif diagnostic.severity == diagnostic.Note:
    type = 'I'
  elif diagnostic.severity == diagnostic.Warning:
    type = 'W'
  elif diagnostic.severity == diagnostic.Error:
    type = 'E'
  elif diagnostic.severity == diagnostic.Fatal:
    type = 'E'
  else:
    return None

  res =  dict({ 'buf' :  filename,
    'lnum' : diagnostic.location.line,
    'col' : diagnostic.location.column,
    'text' : diagnostic.spelling,
    'type' : type})
  return res

def getQuickFixList(tu):
  return filter (None, map (getQuickFix, tu.diagnostics))

def init():
  conf = Config()

  # here we use the libclang.dylib from the vim plugin -- YouCompleteMe


  path = "/Users/<UserName>/.vim/bundle/YouCompleteMe/third_party/ycmd"
  Config.set_library_path(path)
  conf.set_library_path(path)
  try:
    conf.get_cindex_library()
  except LibclangError as e:
    print "Error: " + str(e)

def main():
    init()
    index = Index.create()
    print sys.argv[1]
    tu = index.parse(sys.argv[1], args=['-x', 'objective-c'])

    print getQuickFixList(tu)

if __name__ == '__main__':
    main()

玩法:

python xxx.py MyObject.m

就可以看到各種編譯錯誤(如果有的話)

 
over 6 years ago

最近開近混用swift和objective-c了, 但是一遇到swift的程式碼,YouComplete就開始出現各種錯誤。
只好再重新設定.ycm_extra_conf.py
先從簡單的範例程式開始

#import "ViewController.h"
#import "objcVim-swift.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    hi* a = [[hi alloc] init];
}

@end

要在objective-c中使用的swift程式碼

import Foundation

@objc class hi: NSObject {
     override init(){
        super.init()
    }
}

YouCompleteMe出現錯誤訊息

objcVim/objcVim-swift.h|9 col 10 error| could not build module 'ObjectiveC'
objcVim/ViewController.m|18 col 6 error| 'ViewController' cannot use 'super' because it is a root class
objcVim/ViewController.m|20 col 18 error| no known class method for selector 'alloc'
objcVim/ViewController.m|24 col 6 error| 'ViewController' cannot use 'super' because it is a root class
objcVim/ViewController.h|11 col 12 warning| class 'ViewController' defined without specifying a base class

經過上次的教訓,決定先看YouComplete是不是又動了什麼手腳
:YcmDebug

-- ['-isystem', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1',
 '-isystem', '/Library/Developer/CommandLineTools/usr/include/c++/v1', ...]

果然又出現一堆莫名其妙的flags

經過上次的教訓,直接找到罪魁禍首
~/.vim/bundle/YouCompleteMe/third_party/ycmd/ycmd/completers/cpp/flags.py

def _ExtraClangFlags():
  flags = _SpecialClangIncludes()
   if OnMac():
     for path in MAC_INCLUDE_PATHS:
       flags.extend( [ '-isystem', path ] )

YouCompleteMe果然又偷加clang flags.
把這一段程式直接移掉

:YcmDiag

objcVim/ViewController.h|9 col 9 error| could not build module 'UIKit'
objcVim/ViewController.m|18 col 6 error| 'ViewController' cannot use 'super' because it is a root class
objcVim/ViewController.h|11 col 12 warning| class 'ViewController' defined without specifying a base class

錯誤訊息變了,但還是不行
.ycm_extra_conf.py裡的flags砍到剩下

flags = [
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
]

再試一次:YcmDiag
出現

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.h |12 col 10 error| 'stdarg.h' file not found

用clang直接測試一下

clang -c -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk ViewController.m

沒問題呀
查一下上次寫的文章,發現少了

'-I/Library/Developer/CommandLineTools/usr/bin/../lib/clang/7.0.2/include',

加入這一行之後

flags = [
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
'-I/Library/Developer/CommandLineTools/usr/bin/../lib/clang/7.0.2/include',
]

:YcmDiag

No warnings or errors detected 

搞定收工

 
over 6 years ago

最近又頭腦發熱,想用Kong來做一個proxy的管理工具。
本來是想用Varnish或是Squid來做的,但是在看到api-umbrella的分析之後,覺得lua+nginx真是效能神器呀。可惜api-umbrella還沒完成ruby -> lua的改版。看了他們的競爭對手名單之後,發現Kong一開始就是用lua來做的。

那就用Kong就好啦。

折騰開始

Kong是使用cassandra來存放plugin的資料和其它開發人員的設定參數,所以一開始要先安裝cassandra。
參考這一篇的教學,把cassandra裝在OS X上。

一開始要先安裝java 7:brew install java
再來就是從source code 自己build cassandra。

mkdir -p ~/opt/packages && cd $_

curl -O http://ftp.mirror.tw/pub/apache/cassandra/2.2.4/apache-cassandra-2.2.4-bin.tar.gz

gzip -dc apache-cassandra-2.2.4-bin.tar.gz | tar xf -

ln -s ~/opt/packages/apache-cassandra-2.2.4 ~/opt/cassandra

mkdir -p ~/opt/cassandra/data/data

mkdir -p ~/opt/cassandra/data/commitlog

mkdir -p ~/opt/cassandra/data/saved_caches

mkdir -p ~/opt/cassandra/logs

不能用brew install cassandra,因為brew的cassandra版本只有2.0和3.0版,但是Kong一定要用2.1版以上、3.0版未滿。

執行 cassandra

~/opt/packages/apache-cassandra-2.2.4/bin/cassandra -f

用cqlsh測試安裝是否成功(在~/opt/packages/apache-cassandra-2.2.4/bin)。

注意memory要有1G以上,不然cassandra在執行的時候會因為out of memory直接關閉。
可以看log file (在~/opt/cassandra/logs)

不用另外安裝cqlsh (已經在bin/資料夾內) 或cassandra driver (用不到)。

如果cassandra安裝失敗的話,KongDB有提供一個免費的cassandra db可以使用

安裝Kong

Kong (金剛)是個菜市場名,放在google只會得到Hong Kong。所以要用GetKong來Google。
經過Google幫忙,發現OS X安裝指南
如果不想折騰,可以用pkg installer快速安裝。
只是我們的目的是盡量折騰(為了能夠取得kong_DEVELOPMENT.yml),所以只能

git clone https://github.com/Mashape/kong
sudo make dev

執行Kong

切換到Kong的下載目錄
執行 (要先確定cassandra -f已經跑起來了)

kong start -c kong_DEVELOPMENT.yml

如果要停止Kong

kong stop -c kong_DEVELOPMENT.yml

如果要重啟(改完Kong的source code或是修改plugin)

kong restart -c kong_DEVELOPMENT.yml

修改Kong

Kong是nginx的lua外卦。在Kong啟動時,會覆寫/usr/local/kong/nginx.conf的設定,所以要修改nginx的設定,必須在kong_DEVELOPMENT.yml裡面修改(production的設定要改kong.yml)。

Kong改爛了

Kong的錯誤訊息放在 kong/nginx_tmp/logs/error.log
另外可以用ngx.log(ngx.ERR, "Hello World!")輸出錯誤訊息到error.log (只能在.lua程式裡使用)

不想用hello world debug法的話

可以用ZeroBrane Studio來設breakpoints

把ZeroBrane裝好之後,在要debug的.lua scripts上面的地方,指定mobdebug的路徑:

package.path = "/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/lualibs/?/?.lua;/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/lualibs/?.lua;" .. package.path
package.cpath = "/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/clibs/?.dylib;/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/clibs/?/?.dylib;" .. package.cpath

注意不要用luarocks install mobdebug來安裝,因為luarocks的mobdebug版本比ZeroBrane內附的舊,和ZeroBrane Studio一起使用會出現

 [error] 14757#0: *1 lua entry thread aborted: runtime error: attempt to yield across C-call boundary

(在kong/nginx_temp/logs/error.log可看到)

在要debug的函數裡加上require('mobdebug').start("127.0.0.1")
如下圖:

把ZeroBrane打開,選擇File->Open,打開kong_Development.yml
然後Project->Project Directory->Set From Current File
如果沒有把Project Directory設在Kong的目錄,會出現Step in/out等debug功能無法使用的情況

啟動debug server:Project->Start Debugger Server

設置breakpoint:Project->Toggle Breakpoint把breakpoint設在require('mobdebug').start("127.0.0.1")的下一行

啟動Kong:

kong start -c kong_DEVELOPMENT.yml

ZeroBrane就會把Kong停在breakpoint的位置了

 
almost 7 years ago

clang_complete裡的cindex.py、init.py、enumerations.py抓下來放在./clang的資料夾下,再指定libclang.dylib的位置(下面的path變數),就可以開始玩了

import sys
from clang.cindex import Index, SourceLocation, Cursor, File, CursorKind, TypeKind, Config, LibclangError

def dumpnode(node, indent):
    print ' ' * indent, node.kind, node.spelling
    for i in node.get_children():
        dumpnode(i, indent+2)

def srcrangestr(x):
    return '%s:%d:%d - %s:%d:%d' % (x.start.file, x.start.line, x.start.column, x.end.file, x.end.line, x.end.column)

def dumptoken(node):
    for x in node.get_tokens():
        print x.kind
        print "  " + srcrangestr(x.extent)
        print "  '" + str(x.spelling) + "'"

def init():
  conf = Config()
  
  # here we use the libclang.dylib from the vim plugin -- YouCompleteMe

  path = "/Users/<UserName>/.vim/bundle/YouCompleteMe/third_party/ycmd"
  Config.set_library_path(path)
  conf.set_library_path(path)
  try:
    conf.get_cindex_library()
  except LibclangError as e:
    print "Error: " + str(e)

def main():
    init()
    index = Index.create()
    print sys.argv[1]
    tu = index.parse(sys.argv[1], args=['-x', 'objective-c'])

    dumpnode(tu.cursor, 0)
    dumptoken(tu.cursor)

if __name__ == '__main__':
    main()
    

玩法:

python xxx.py MyObject.m

就可以看到parse後的node和token名稱了

 
about 7 years ago

今天腦子發熱,想來用vim達成類似XCode的自動補完功能(auto-completion).
先從國外網友提供的.ycm_extra_conf.py開始折騰。

import os
import ycm_core

flags = [
'-resource-dir',
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0',
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk',
'-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include',
'-F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks',
'-fblocks',
'-fobjc-runtime=macosx-10.10.0',
'-fencode-extended-block-signature',
'-fobjc-arc',
'-fobjc-exceptions',
'-fexceptions',
'-x',
'objective-c'
]

SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]

def FlagsForFile( filename, **kwargs ):
  return {
    'flags': flags,
    'do_cache': True
  }

先把YouCompleteMe安裝好,再把這個檔案放在專案的根目錄下面
用VIM打開.m檔的時候,就會出現一個對話框,問要不要執行.ycm_extra_conf.py這個程式,這時候選Load就能載入了

如果沒意外的話,配合國外網友提供的測試檔案

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
  int retVal;
  @autoreleasepool {
    NSString *string = @"hihi";
    NSLog(@"%@", string);
    retVal = 0;
  }
  return retVal;
}

就能看到auto completion的功能了

等等,UIKit去那了…

國外網友提供的是Mac app的設定,如果是iOS的話
要改成iOS的SDK

import os
import ycm_core

flags = [
'-arch i386',
'-fblocks',
'-fobjc-runtime=ios-8.0.0',
'-fencode-extended-block-signature',
'-fobjc-arc',
'-fobjc-exceptions',
'-fexceptions',
'-x',
'objective-c',
]

SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]

def FlagsForFile( filename, **kwargs ):
  return {
    'flags': flags,
    'do_cache': True
  }

在VIM輸入:YcmDiag,就能看到

'UIKit/UIKit.h' file not found

找不到UIKit是吧?
flags加入
'-mios-simulator-version-min=7.0'
指定deployment target是ios simulator 7.0

再試一次:YcmDiag

/System/Library/Frameworks/Security.framework/Versions/A/Headers/cssmtype.h|142 col 5 error| 'CSSM_GUID' is unavailable: not available on iOS
/System/Library/Frameworks/Security.framework/Versions/A/Headers/cssmtype.h|143 col 5 error| 'CSSM_VERSION' is unavailable: not available on iOS

出現了一大堆看不懂的東西
沒關係,再繼續trial-and-error
在flags裡加入

'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',

指定system root directory (這啥?)

繼續:YcmDiag
看不懂的東西不見了,但是出現其它更看不懂的東西

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFNumberFormatter.h|29 col 32 error| missing ',' between enumerators (FixIt available)
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFNumberFormatter.h|30 col 40 error| missing ',' between enumerators (FixIt available)
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFNumberFormatter.h|30 col 41 error| redefinition of enumerator '__AVAILABILITY_INTERNAL__IPHONE_9_0'

沒關係,再繼續trial-and-error
在flags裡加入

'-MMD',

這個-MMD是什麼呢?
看一下說明:

-MMD
    Like -MD except mention only user header files, not system header files. 

說明上寫和-MD很像
-MD又是什麼東東?

-MD
    -MD is equivalent to -M -MF file, except that -E is not implied. The driver determines file based on whether an -o option is given. If it is, the driver uses its argument but with a suffix of .d, otherwise it takes the name of the input file, removes any directory components and suffix, and applies a .d suffix. 

說明上寫和-M是幾乎一樣的東西
-M又是什麼東東?

-M
    Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from -include or -imacros command-line options.

    Unless specified explicitly (with -MT or -MQ), the object file name consists of the name of the source file with any suffix replaced with object file suffix and with any leading directory parts removed. If there are many included files then the rule is split into several lines using ‘\’-newline. The rule has no commands. 

好…還是看不懂

自己動手試試吧
找一個.m
執行

clang -M hello.m  

出現了

hello.o: hello.m \
  /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h \
  /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h \
  /usr/include/sys/types.h /usr/include/sys/appleapiopts.h \
  /usr/include/sys/cdefs.h /usr/include/sys/_symbol_aliasing.h \
  /usr/include/sys/_posix_availability.h /usr/include/machine/types.h \
  /usr/include/i386/types.h /usr/include/i386/_types.h \
  /usr/include/sys/_types/_int8_t.h /usr/include/sys/_types/_int16_t.h \
  /usr/include/sys/_types/_int32_t.h /usr/include/sys/_types/_int64_t.h \
  /usr/include/sys/_types/_intptr_t.h \
...

從結果判斷,-M的功能是把所有這個.m檔出現的header files都列出來
-MD-MMD呢?
執行

clang -MD hello.m  

出現

Undefined symbols for architecture x86_64:
  "___CFConstantStringClassReference", referenced from:
      CFString in hello-eb80c0.o
  "_objc_autoreleasePoolPop", referenced from:
      _main in hello-eb80c0.o
  "_objc_autoreleasePoolPush", referenced from:
      _main in hello-eb80c0.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

出現link error
搞不懂,放棄

繼續:YcmDiag
之前的看不懂的東西都不見了,但是出來一個新的stdarg.h找不到

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h|12 col 10 error| 'stdarg.h' file not found

這怎麼辦呢?

去問Google大神

I get errors about some headers being missing (stddef.h, stdarg.h)

Some header files (stddef.h, stdarg.h, and others) are shipped with Clang — these are called builtin includes. Clang searches for them in a directory relative to the location of the clang binary. If you moved the clang binary, you need to move the builtin headers, too.

More information can be found in the Builtin includes section.

上面說Clang有自己的stdarg.h
所以加入在flag裡加入

'-I/Library/Developer/CommandLineTools/usr/bin/../lib/clang/7.0.0/include',

再來:YcmDiags,結果stdarg.h找不到的問題解決了,但是之前更看不懂的問題又出現了…

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFNumberFormatter.h|29 col 32 error| missing ',' between enumerators (FixIt available)
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFNumberFormatter.h|30 col 40 error| missing ',' between enumerators (FixIt available)

看起來是clang看不懂ios9特有的macro
那就不用YouCompleteMe的libclang,改用XCode的clang好了

執行

cd ~/.vim/bundle/YouCompleteMe
./install.py --clang-completer --system-libclang

繼續:YcmDiag
之前的錯誤訊息幾乎不見了,只剩下最後一個

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h|92 col 10 error| 'CoreFoundation/CFUserNotification.h' file not found

訊息說問題出在CoreFoundation.h第92行
就去那邊看看

#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
#include <CoreFoundation/CFUserNotification.h>
#include <CoreFoundation/CFXMLNode.h>
#include <CoreFoundation/CFXMLParser.h>
#endif

原來是include了CFUserNotification.h
但是iOS的framework裡面根本沒有這個檔案呀

問題可能是出在TARGET_OS_MAC有被定義,也可能是TARGET_OS_IPHONE沒有被定義

來寫一個簡單的測試程式,來看看那些MACRO有被定義

#import <Foundation/Foundation.h>

int foo() {
  return TARGET_OS_MAC;
  return TARGET_OS_EMBEDDED;
  return TARGET_OS_IPHONE;
}

執行:w z.m
回到command line,執行

clang -E z.m

出現

int foo() {
  return 1;
  return 0;
  return 0;
}

所以TARGET_OS_MAC的值是1,其它的是0

那我們直接把TARGET_OS_MAC設成0就好了

執行

clang -DTARGET_OS_MAC=0 -E z.m 

出現

int foo() {
  return 1;
  return 0;
  return 0;
}


還是沒變
所以是有別的地方改了這個MACRO的值

用silver searcher來找一下元兇是誰

cd /Applications/Xcode.app/Contents
ag 'define TARGET_OS_MAC'

出現

Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/TargetConditionals.h
92:    #define TARGET_OS_MAC               1
213:    #define TARGET_OS_MAC               1
339:    #define TARGET_OS_MAC                1
Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/TargetConditionals.h
92:    #define TARGET_OS_MAC               1
213:    #define TARGET_OS_MAC               1
339:    #define TARGET_OS_MAC                1

不對呀,有好幾個SDK,該用那一個?
應該來指定要使用的SDK

執行

clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -E z.m

出現

int foo() {
  return 1;
  return 0;
  return 1;
}

TARGET_OS_IPHONE變成1了
問題解決

回去:YcmDiag,看看是不是行了

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h|92 col 10 error| 'CoreFoundation/CFUserNotification.h' file not found

...
問題還在
來Debug一下,輸入:YcmDebugInfo

Printing YouCompleteMe debug information...
-- Server has Clang support compiled in: True
-- Clang version: Apple LLVM version 7.0.0 (clang-700.0.72)
-- Flags for /Users/Lono/tmp/a/z.m loaded from /Users/Lono/tmp/a/.ycm_extra_conf.py:
-- ['-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.0/include', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk', '-isystem', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1', '-isystem', '/usr/local/include', '-isystem', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include', '-isystem', '/System/Library/Frameworks', '-isystem', '/usr/include','-isystem', '/Library/Frameworks']

咦! 出現一些在.ycm_extra_conf.py裡沒有的flags
這可能是YouCompleteMe自己設的flags
再來ag一下

cd ~/.vim/bundle/YouCompleteMe
ag /usr/local/include

找到可疑檔案

~/.vim/bundle/YouCompleteMe/third_party/ycmd/ycmd/completers/cpp/flags.py

原來YouCompleteMe自己有放一些default的flags進去
把這些flags移掉

繼續:YcmDiag

出現

Forcing compilation, this will block Vim until done.
No warnings or errors detected


終於設定完成(淚~~)

最後的.ycm_extra.conf.py

import os
import ycm_core

flags = [
'-D__IPHONE_OS_VERSION_MIN_REQUIRED=70000',
'-resource-dir',
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.0',
'-mios-simulator-version-min=7.0',
'-arch i386',
'-fblocks',
'-fobjc-runtime=ios-7.0.0',
'-fencode-extended-block-signature',
'-fobjc-arc',
'-fobjc-exceptions',
'-fexceptions',
'-x',
'objective-c',
'-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks',
'-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/Foundation.framework/Headers',
'-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include',
'-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.0/include',
'-I/Library/Developer/CommandLineTools/usr/include',
'-isysroot',
'/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
'-MMD',
]

SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]

def FlagsForFile( filename, **kwargs ):
  return {
    'flags': flags,
    'do_cache': True
  }

2015/11/08
今天:YcmDiag竟然出現

unknown argument: '-fencode-extended-block-signature'

真奇怪,之前都沒問題
可能和clang的版本有關(clang-700.0.72)
只好把這個argument移掉了(???)

 
over 7 years ago

Docker上出現了一個好用的套件,叫做Dokku
利用這個套件可以在任何IaaS的平台上建立類似Heroku的PaaS服務
看來Heroku的末日快到了

在比較過AWS、Linode、和DigitalOcean的IaaS平台的價格之後
發現DigitalOcean的價格是最實惠的($5/month),所以我們就從DigitalOcean開始吧
用以下連結註冊可以拿到$10的儲值金,等於免費試用2個月
https://www.digitalocean.com/?refcode=810a7d07e0c2

註冊DigitalOcean的帳號

屌絲們選擇最便宜的方案就對了。剩下的伺服器位置和額外功能就看自己的需求吧

創建Dokku

而來選擇Applications下的Dokku。最後填入ssh keys
沒有的話,用

ssh-keygen -t rsa

產生一組keys,把id_rsa.pub的內容複製上去就行了。
按下Create,等伺服器開完機就可以使用了

升級Dokku的版本

用ssh登入伺服器

ssh root@your_droplet_ip_address

更新Dokku的版本

cd ~/dokku
git pull origin master
make install

更新Buildstep的版本,這東東是Docker版的Heroku Buildpacks

docker pull progrium/buildstep:latest

加入dokku要使用的public key

先用瀏覽器打開伺服器的網頁

open http://your_ip_address

會出現Droplet的設定頁面。貼上dokku的public key,按下Finish就行了

創建App

找到要上傳的git project
把dokku加入remote repository裡面

git remote add dokku dokku@your_droplet_ip_address:app_name

如果之前沒進去Droplet的設定頁面按Finish的話,這裡git會要求輸入密碼(但是我們是ssh keys登入,根本沒密碼呀)
接下來把程式碼push到dokku

git push dokku master

push完畢之後,再次登入

ssh root@your_droplet_ip_address

用ps查詢app的port

docker ps

會出現

CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
d96737fbaaa3 dokku/hello:latest "/start web" Up 3 minutes 0.0.0.0:32768->5000/tcp angry_wozniak

上面的32768就是app對應的external port (5000是internal port)
用瀏覽器打開app的網頁

open http://your_ip_address:32768

如果沒問題,就可以看到app的404頁面了(咦?)

 
over 7 years ago

最近專案長的太肥了,應該要來瘦身一下。CocoaPods是一個很方便的管理工具,可以把專案分成幾個小的模組(Pods)方便日後的管理。如果不想把程式碼放在Github上給別人看光光怎麼辦?很簡單,用bitbucket就好了,private repository不用錢,想開幾個就開幾個。不過私有的程式碼是沒辦法放在CocoaPods官方的spec裡面的。所以該怎麼辦呢?

解法1:使用development pod

產生development pod

用cocoapods內建的小工具來建立一個新的pod

pod lib create myDevelopmentPod

修改myDevelopmentPod.podspec
然後把.m、.h、.swift複製進去就行啦

把development pod加入專案

修改專案的Podfile,加入development pod

pod 'myDevelopmentPod', :path => '~/MyProjects/myDevelopmentPod'

然後執行

pod install

解法2:使用private pod

產生一個新的spec

要先創造一個private spec repository

mkdir MYSpecs
cd MYSpecs
git init
git remote add origin git@bitbucket.org:my_account/my_specs.git
git commit -m 'Initial commit'
git push -u origin master

上傳到bitbucket之後,就能把MYSpecs的資料夾給砍了

rm -rf MYSpecs

告訴CocoaPods我們要新增一個自己的spec

pod repo add MYSpecs git@bitbucket.org:my_account/my_specs.git

CocoaPods會把這個spec複製一份下來,放在~/.cocoapods/repos裡面

創建private pod

用內建的指令幫我們創建一個新的pod

pod lib create myPrivatePod

回答幾個問題就建好了

myPrivatePod.podspec的內容如下

Pod::Spec.new do |s|
  s.name             = "myPrivatePod"
  s.version          = "0.1.0"
  s.summary          = "A short description of myPrivatePod."
  s.description      = <<-DESC
                       An optional longer description of myPrivatePod

                       * Markdown format.
                       * Don't worry about the indent, we strip it!
                       DESC
  s.homepage         = "https://github.com/<GITHUB_USERNAME>/myPrivatePod"
  # s.screenshots     = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
  s.license          = 'MIT'
  s.author           = { "" => "" }
  s.source           = { :git => "https://github.com/<GITHUB_USERNAME>/myprivatepod.git", :tag => s.version.to_s }
  # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

  s.platform     = :ios, '7.0'
  s.requires_arc = true

  s.source_files = 'Pod/Classes/**/*'
  s.resource_bundles = {
    'myPrivatePod' => ['Pod/Assets/*.png']
  }

  # s.public_header_files = 'Pod/Classes/**/*.h'
  # s.frameworks = 'UIKit', 'MapKit'
  # s.dependency 'AFNetworking', '~> 2.3'
end

把要改的東西改一改吧
要注意預設的license是MIT,既然我們不想開源,就改成

  s.license          = 'proprietary'

改完之後存檔

另外LICENSE檔案也要改掉,在命令列下輸入

  echo -e "Copyright (c) 2015, MyCompany\nAll right reserved." > LICENSE

最後驗證podspec的內容是否正確

pod lib lint --allow-warnings

Cocoapods很龜毛,有可能產生一些警告訊息。但是我們是自己用,不用這麼麻煩,加入--allow-warnings讓驗證程式忽略這些錯誤

測試private pod

找一個專案修改它的Podfile,把創建出來的pod以development pod的形式加進去

pod 'myPrivatePod', :path => '~/MyProjects/myPrivatePod'

測試pod和專案的整合有沒有遇到問題

上傳private pod

測試通過之後,把private pod上傳到bitbucket

git tag -m "first release" 0.1.0
git push --tags

再把private pod加入到我們的spec裡面

pod repo push --allow-warnings MYSpecs myPrivatePod.podspec

安裝pod

簡單,指定private spec的位置,再把private pod加到專案的Podfile

source 'git@bitbucket.org:my_account/my_specs.git'
pod 'myPrivatePod'

再執行pod install

pod更新

別忘了myPrivatePod.podspec的版本編號也要修改
在把修改過的程式push之後,執行

git tag -m "second release" 0.2.0
git push --tags
pod repo push --allow-warnings MYSpecs myPrivatePod.podspec

刪除private spec

如果不想要再用private spec的話,用以下命令移除spec

pod repo remove MYSpecs

總結:該用那個呢?

development pod的好處是方便管理,想改code就直接在Xcode裡面改好。不必像private pod那樣改完之後還要commitpushpod install。缺點是無法和其它的專案分享程式碼。如果要在不同的專案內使用同樣的pod,那private pod是唯一的選擇。

 
over 7 years ago

Ship.io是一個持續整合(continous integration)的服務
能夠在app的程式碼變更之後自動測試程式的功能是否正常
確定沒有人上傳爛掉的程式碼到git repository去

一開始先註冊帳號,登入之後


點選左上角的"+",加入新的app

Bitbucket的設定方式

選擇最左邊的SSH
在URL填入git@bitbucket.org:your_account/your_project.git

需要一組ssh key讓Ship.io可以存取Bitbucket的repository
點選Key右邊的"+"


再來點選"generate key pair"來產生一組新的ssh key


複製產生出來的public key

登入Bitbucket
在project setting的地方,把剛才產生出來的public key加入deploy keys
(https://bitbucket.org/your_account/your_project/admin/deploy-keys)

回到Ship.io
按下Scan,讓Ship.io分析程式設定

分析完了之後,還有一堆雜七雜八的東西要設定


在schedule的地方,選擇commit hook
commit hook可以讓Ship.io在程式碼push到Bitbucket的repository之後,自動執行測試
不過這個選項還需要在Bitbucket裡做一個額外的設定

回到Bitbucket,在project setting的地方,找到Hooks


選擇Add hook
類型選"Post",URL填入https://ship.io/commit_hook

回到Ship.io,把剩下雜七雜八的東西設定完之後
測試工作就會開始執行了
之後只要有人push新的code到Bitbucket repository
Ship.io就會自動開始測試,並且把測試結果寄到你的信箱

Github的設定方式

Ship.io有內建支援github
在新建app的地方,選擇Github
按下connect就行啦

 
over 7 years ago

上傳ipa到testflight時出現

'Invalid Profile: distribution build entitlements must have get-task-allow set to false.'

到build settings->code signing->release選擇adhoc的provision file (不能用automatic)

 
almost 8 years ago

程式閃退

  • Crashlytics: 個人心中的第一名,創辦人是中輟生。已被Twitter收購
  • Crittercism: 十幾個MIT高材生創辦的公司,方便程度不如Crashlytics

Logging 工具

  • LogEntries: 穩定使用中,功能就是很陽春的記錄log。拿到了一千萬美金的投資,不知道錢都花去那了?
  • BugFender: 還沒上線,功能比LogEntries強很多
  • Crashlytics: 目前只有在閃退時才會傳送log到後台,0分

使用者行為分析

  • 友盟: 創新工場孵化(山寨)的項目,已經被百度收購了。功能比Flurry強
  • Flurry: 國外最知名的平台,已被Yahoo收購
  • Mixpanel: 高大上的平台,等變成了高帥富再試