Mac SOIL踩坑记

SOIL即Simple OpenGL Image Library,是一个跨平台的支持多个格式图片加载的库,主要作用是加载图片成为OpenGL的texture。该库最后的更新时间是2008年7月7日,因此现在Mac上使用又踩到了几个坑。

http://www.lonesock.net/soil.html下载源文件,在src和lib目录下分别已经存在了用于编译链接的SOIL.h头文件和libSOIL.a静态库文件,将它们加入工程编译链接时Xcode报错:

Undefined symbols for architecture x86_64

可见libSOIL.a并不是x86_64的库文件,需要重新编译生成。cd进入SOIL/projects/makefile目录,运行make命令编译报错:

error: unable to open output file ‘obj/image_helper.o’: ‘No such file or directory’

在makefile目录下新建obj目录重新make可以重新编译生成libSOIL.a库文件了,但此时库文件仍是32位的,修改makefile文件,加入编译选项-m64,重新编译生成即可。

Mac OpenGL踩坑记

在Mac上尝试写OpenGL程序,结果踩了一堆坑,在此记录下来,以备后用。

Mac上已经带了GLUT,使用时只需#include <GLUT/GLUT.h>即可。但使用GLUT函数编译时,Xcode会警告相关函数已经在OS X 10.9中废弃:

‘glutInit’ is deprecated: first deprecated in OS X 10.9

消除该警告的方法是在Build Settings中将OS X Deployment Target改为OS X 10.8,但这显然不是Apple认可的解决方案,更好的方案是使用GLFW和GLEW替代GLUT。

http://stackoverflow.com/questions/24095931/glut-deprecation-in-mac-osx-10-9-ide-qt-creator

使用GLFW和GLEW的问题是OS X默认并没有带上这两个库,需要我们自己安装。

从GLFW官网上下载源码,使用CMake编译:

http://www.glfw.org/docs/latest/compile.html#compile_compile

编译出的静态库路径在用CMake新建的工程文件夹下:

glfw-3.1.2/src/Debug/libglfw3.a

#include头文件路径在源码文件夹下:

glfw-3.1.2/include/GLFW/glfw3.h

在Build Settings中设置好Header Search Paths和Library Search Paths,在Build Phases的Link Binary With Libraries将libglfw2.a设置好,此时编译Xcode会报很多Undefined symbols的错误:

Undefined symbols for architecture x86_64:

“_CFArrayAppendValue”, referenced from:

__glfwInitJoysticks in libglfw3.a(iokit_joystick.o)

_addJoystickElement in libglfw3.a(iokit_joystick.o)

这是因为libglfw3.a在Mac OS X上使用了Cocoa,依赖了几个其它的库:Cocoa、IOKit和CoreVideo。将这3个库也在Link Binary With Libraries中设置好,编译就能通过了。

http://stackoverflow.com/questions/18391487/compiling-with-glfw3-linker-errors-undefined-reference

使用GLEW先从它的官网上下载源码,然后依次使用3个make命令编译安装:

1、make,编译。

2、sudo make install,安装,将头文件和库文件拷贝到系统头文件和库文件存放目录。

3、make clean,清除编译安装过程中留下来的垃圾文件。

https://github.com/nigels-com/glew

在Mac OS X EI Capitan上sudo make install时遇到了以下问题:

install -d -m 0755 “/usr/include/GL”

install: mkdir /usr/include: Operation not permitted

make: *** [install.include] Error 71

这是因为从EI Capitan开始,Mac OS X启用了System Integrity Protection,不再允许直接操作/usr下的目录,但/usr/local除外,所以需要将GLEW安装在/usr/local下。这里只需要修改GLEW的Makefile即可,将GLEW_DEST ?= /usr修改为GLEW_DEST ?= /usr/local,再执行sudo make install。

http://stackoverflow.com/questions/33309005/sudo-mkdir-in-usr-operation-not-permitted-el-capitan

同样需要配置好Header Search Paths、Library Search Paths和Link Binary With Libraries。此时编译报错:

/usr/local/include/GL/glew.h:16426:17: Declaration of ‘PFNGLCOPYTEXSUBIMAGE3DPROC’ must be imported from module ‘OpenGL.GL3’ before it is required

这里需要将Build Settings里的Enable Modules(C and Objective-C)设为No即可。最后别忘了Link OpenGL库本身。

Beginning iOS 7 Development Exploring the iOS SDK 1-4

iOS编程的一些区别:
1、任何时候只有一个应用处于active状态并显示在屏幕上;
2、每个应用都只有一个window;
3、每个应用都只能访问自己的sandbox目录;
4、每个应用都要在限定的时间内做出响应(用户按下home键,应用保存数据等操作的时长超过5s就会被系统kill掉);
5、有限大小的屏幕;
6、有限的系统资源。

Xcode navigator从左到右依次为:
Project navigator
Symbol navigator
Find navigator
Issue navigator
Test navigator
Debug navigator
Breakpoint navigator
Log navigator
快捷键依次为command + 1/2/3/4/5/6/7/8

Xcode快捷键:
shift+command+O: Open Quickly

Interface Builder支持.nib、.xib和.storyboard文件。
.nib:最早的二进制格式
.xib:XML格式,.nib和.xib通称nib file
.storyboard:meta-nib file
nib file和storyboard还有一个区别:nib file通常一个文件只包含一个single view及其里面的控件,当这个view需要显示时只需加载这个nib节约内存;而storyboard可以包含所有界面但只加载其中特定的部分。

按住Option键移动鼠标到类名上可以查看类的描述
选中Image View使用快捷键Command+=或者使用菜单Editor->Size to Fit Content可以将Image View调整为设置的图片大小
为UI添加约束:Editor->Resolve Auto Layout Issues->Add Missing Constraints

git

git add不仅用于新增文件,改动的文件也需要使用它加入commit队列

git commit -m “这里是提交注释”

git push

Objective-C

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html

Protocol的定义形式:
@protocol ProtocolName
// list of methods and properties
@end

通过属性引用一个实现了Protocol的对象:
@property (weak) id <XYZPieChartViewDataSource> dataSource;

Protocol中可以定义必须实现的方法和可选实现的方法,默认是必须实现的。使用关键字@optional和@required可以声明它们以下的方法是可选或必须实现的:
@protocol XYZPieChartViewDataSource
– (NSUInteger)numberOfSegments;
– (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
– (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
– (BOOL)shouldExplodeSegmentAtIndex:(NSUInteger)segmentIndex;
@required
– (UIColor *)colorForSegmentAtIndex:(NSUInteger)segmentIndex;
@end

调用Protocol中的可选方法时需要通过respondsToSelector:和@selector()先检查对象是否实现了该方法:
NSString *thisSegmentTitle;
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}

Protocol可以继承:
@protocol MyProtocol <NSObject>

@end

类实现多个协议:
@interface MyClass : NSObject <MyProtocol, AnotherProtocol, YetAnotherProtocol>

@end
注意:编译器不会合成协议中声明的属性。

Block也是OC对象,其定义形式为:
^{
NSLog(@”This is a block”);
}
^ double (double firstValue, double secondValue) {
return firstValue * secondValue;
}

同C语言里函数指针可以指向一个函数一样,OC里可以使用Block Pointer:
void (^simpleBlock)(void);

Block能抓住闭包范围内的值,但它不能改变值。如果Block要改变一个被Block抓住的变量的值,需要对该变量使用__block修饰符。
注意:Block若抓住了self时,可能引起强引用循环引用的问题。
解决循环引用的问题可以在Block内部使用__weak的self:
– (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}

Class中使用属性引用Block时要使用copy属性修饰符:
@interface XYZObject : NSObject
@property (copy) void (^blockProperty)(void);
@end

Operation Queues是Cocoa进行任务调度的一个途径。可以创建一个NSOperation实例将一个任务及其需要的数据封装起来,然后将它加入一个NSOperationQueue来执行。
使用NSBlockOperation创建一个使用Block的Operation:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

}];

// schedule task on main queue:
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperation:operation];

// schedule task on background queue:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];

Block也可以使用Grand Central Dispatch (GCD)控制的Dispatch Queues来执行。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{
NSLog(@”Block for asynchronous execution”);
});

解决更新Mac OS X后MacVim无法使用的问题

前段时间更新了Mac OS X到Yosemite 10.10.1,今天要用到MacVim时突然发现不能用了,表现为通过GUI打开时只有MacVim的菜单却没有窗口,通过终端打开时提示:

dyld: Library not loaded: /System/Library/Perl/5.12/darwin-thread-multi-2level/CORE/libperl.dylib
Referenced from: /Applications/MacVim.app/Contents/MacOS/Vim
Reason: image not found
Trace/BPT trap: 5

查到问题是由于新系统里Perl 5.12的动态库也升级了,解决办法是下载MacVim最新的Release版本或者下载源码在新系统上编译即可。

这里有关于该问题的讨论:https://code.google.com/p/macvim/issues/detail?id=484&q=Mavericks

这里有MacVim的源码和Release:https://github.com/b4winckler/macvim

mount坑爹记

在Mac又遭遇了一次mount坑爹记,想挂载一个FAT12格式的软驱,以前在Linux下使用如下命令:
sudo mount -o loop a.img /mnt/floppy
将a.img这个FAT12的软驱镜像挂载到/mnt/floppy目录下。

Mac上mount需要指定-t(文件系统)参数,man了但E文不好,看不太懂,但好歹找到了FAT12应该用-t msdos参数。可是mount -t msdos a.img /xxx/floppy却报错:Block device required。Google了大半天终于找到了解决方案:
$ hdid -nomount a.img
/dev/disk1
$ mount -t msdos /dev/disk1 /xxx/floppy

hdid的命令还不太清楚,后面了解了再补上。

另外一个方法是使用实用工具里的磁盘工具, File—> Open Disk Image—> a.img。

附上好不容易google到的两篇参考资料:
mounting dos floppy image
Create a blank floppy image in Mac OSX 10.6

Bochs on Mac

Win上使用Bochs应该是最方便的了,但Win上使用的命令行工具没Linux上的多,或者Win上已经没有使用命令行工具的氛围了。之前在Ubuntu上折腾过Bochs的编译和安装:Ubuntu编译Bochs,这次又在Mac上折腾了遍。

首先是使用./configure –with-x11 –enable-debugger –enable-disasm –disable-debugger-gui生成makefile时显示缺少gcc。机器上装有Xcode,怎么会缺少gcc呢?原来是没安装Xcode命令行工具,打开Xcode—>Preference—>Downloads中安装Command Line Tools。

完成后configure OK,但是make会找不到很多函数。原来Bochs需要X11,安装完X11后make OK,make install完成安装。

在终端中输入bochs可启动Bochs,但是会报错,原因是Bochs的隐藏配置文件.bochsrc中的配置不太兼容,自己新建个简单的配置即可。

svnX坑爹使用记

Mac上需要使用SVN,百度了一下说是Mac自带了SVN功能,看了不少资料,都是如何配置SVN服务端的,不是我想要的只使用SVN客户端的功能。于是,用上了svnX。

百度上svnX有图文教程,但都忽视了一个细节点,导致了我的坑爹使用记——那就是Output窗口。

默认情况下Repository和Working Copy里的Output窗口都是隐藏的,如果不打开,一个正在进行中的SVN操作很难看出它的进度,而svnX又不会禁用SVN的相关功能,这就会导致各种坑爹的问题。比如我这里遇到的:在Repository中Checkout未完成的情况下进行了Working Copy中的SVN Add操作,结果就是Commit的时候总提示我本地目录被Lock住了需要Cleanup,但无论怎么Cleanup后再Commit还是一样。

通常遇到这种情况我的第一想法是重新Checkout一份,但如果你还想Checkout到原目录怎么办?这是个坑爹的问题!因为SVN会在每个目录下生成一个.svn的隐藏文件夹保存SVN的相关信息,要实现我的想法不得不全删掉它,这是个体力活,也极度考验耐心。

想到Mac是类Linux系统,于是百度Linux命令,又被自己坑爹了,先是有如下命令:
find . -name .svn -type d -exec rm -fr {} ;
它的坑爹之处在于它让我以为只要cd到原目录下即可成功执行(没注意到find后面的点),没有提到find命令还要path,对于我这Linux菜鸟来说害苦我了,会被系统报错:
find: illegal option — n
后面又找到一份资料,里面有path,但是却没有”;”中的””又折腾了好久:
find: -exec: no terminating “;” or “+”
原来find的-exec参数要以”;”结束,而且是要转义的,最终被我摸索对了:

find /Users/***/Documents/HelloWorld -name .svn -type d -exec rm -rf {} ;

Finder显示隐藏文件

Finder显示隐藏文件的命令:
defaults write com.apple.finder AppleShowAllFiles -bool true

defaults write com.apple.finder AppleShowAllFiles YES

相反,隐藏的命令:
defaults write com.apple.finder AppleShowAllFiles -bool false

defaults write com.apple.finder AppleShowAllFiles NO

命令需要强制退出并重启Finder后生效,呼出强制退出command+alt+esc。