設定方式和上一篇一樣:
把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
就可以看到各種編譯錯誤(如果有的話)
最近開近混用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
搞定收工
最近又頭腦發熱,想用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的位置了
把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名稱了
今天腦子發熱,想來用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移掉了(???)
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
先用瀏覽器打開伺服器的網頁
會出現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的網頁
如果沒問題,就可以看到app的404頁面了(咦?)
最近專案長的太肥了,應該要來瘦身一下。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那樣改完之後還要commit
、push
、pod install
。缺點是無法和其它的專案分享程式碼。如果要在不同的專案內使用同樣的pod,那private pod是唯一的選擇。
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就行啦
上傳ipa到testflight時出現
'Invalid Profile: distribution build entitlements must have get-task-allow set to false.'
到build settings->code signing->release選擇adhoc的provision file (不能用automatic)
程式閃退
- Crashlytics: 個人心中的第一名,創辦人是中輟生。已被Twitter收購
- Crittercism: 十幾個MIT高材生創辦的公司,方便程度不如Crashlytics
Logging 工具
- LogEntries: 穩定使用中,功能就是很陽春的記錄log。拿到了一千萬美金的投資,不知道錢都花去那了?
- BugFender: 還沒上線,功能比LogEntries強很多
- Crashlytics: 目前只有在閃退時才會傳送log到後台,0分