2013年9月28日星期六

Access hidden user library files

http://helpx.adobe.com/x-productkb/global/access-hidden-user-library-files.html

Apple made the user library folder hidden by default with the 10.7 and later releases of Mac OS. If it's necessary to access these files for Adobe-related troubleshooting, use one of the following methods to make the user library content visible.

Method 1

  1. In the Finder, choose Go > Go To Folder.
  2. In the Go To Folder dialog, type ~/Library
  3. Click Go.

Method 2

Hold down the Alt (Option) key when using the Go menu. The user library folder is listed below the current user's home directory.
Note: After you open the Library folder, you can drag the Library icon from the top of that window to the Dock, Side Bar, or toolbar. That way, it's readily accessible.

Method 3

The following method makes the user library folder permanently visible. 

Note: Adobe recommends that only advanced users use this method.
  1. Launch Terminal from Mac HD > Applications > Utilities.
  2. From within Terminal type the following command and press Return:

    chflags nohidden ~/Library
  3. Enter the system administrator password, if prompted, and press Return.
Note: The System administrator password is not visible as you type it.  
Close Terminal for this change to take effect.

2013年9月27日星期五

使用 LLVM 创建工作编译器


LLVM(之前称为低级虚拟机)是一种非常强大的编译器基础架构框架,专门为使用您喜爱的编程语言编写的程序的编译时、链接时和运行时优化而设计。LLVM 可运行于若干个不同的平台之上,它以能够生成快速运行的代码而著称。
LLVM 框架是围绕着代码编写良好的中间表示 (IR) 而构建的。本文(由两部分组成的系列文章的第一部分)将深入讲解 LLVM IR 的基础知识以及它的一些微妙之处。在这里,您将构建一个可以自动为您生成 LLVM IR 的代码生成器。拥有一个 LLVM IR 生成器意味着您所需要的是一个前端以供插入您所喜爱的编程语言,而且这还意味着您拥有一个完整的流程(前端解析器 + IR 生成器 + LLVM 后端)。创建一个自定义编译器会变得更加简单。
在开始之前,在您的开发计算器上必须已经拥有已编译好的 LLVM(参阅 参考资料 获取相关链接)。本文中的示例均基于 LLVM V3.0。对于 LLVM 代码的后期生成和安装,最重要的两个工具是 llc 和 lli
因为 LLVM 是一个虚拟机,所以它可能应该拥有自己的中间字节代码表示,不是吗?最后,您需要将 LLVM 字节代码编译到特定于平台的汇编语言中。然后您才能通过本机汇编程序和链接器来运行汇编代码,从而生成可执行的共享库等。您可以使用 llc 将 LLVM 字节代码转换成特定于平台的汇编代码(请参阅 参考资料,获取关于此工具的更多信息的链接)。对于 LLVM 字节代码的直接执行部分,不要等到在本机执行代码崩溃后才发现您的程序中有一个或两个 bug。这正是 lli 的用武之地,因为它可以直接执行字节代码。lli 可以通过解释器或使用高级选项中的即时 (JIT) 编译器执行此工作。请参阅 参考资料,获取关于 lli 的更多信息的链接。
llvm-gcc 是 GNU Compiler Collection (gcc) 的修改版本,可以在使用 -S -emit-llvm 选项运行时会生成 LLVM 字节代码。然后您可以使用 lli 来执行这个已生成的字节代码(也称为 LLVM 汇编语言)。有关 llvm-gcc 的更多信息,请参阅 参考资料。如果您没有在自己的系统中预先安装 llvm-gcc,那么您应该能够从源代码构建它,请参阅 参考资料,获取分步指南的链接。
要更好地理解 LLVM,您必须了解 LLVM IR 及其微妙之处。这个过程类似于学习另一种编程语言。但是,如果您熟悉 C 语言和 C++语言以及它们的一些语法怪现象,那么在了解 LLVM IR 方面您应该没有太大的障碍。清单 1 给出了您的第一个程序,该程序将在控制台输出中打印 "Hello World"。要编译此代码,您可以使用 llvm-gcc。

清单 1. 看起来非常熟悉的 Hello World 程序
    
#include 
int main( )
{ 
  printf("Hello World!\n");
}

要编译此代码,请输入此命令:
Tintin.local# llvm-gcc helloworld.cpp -S -emit-llvm 

完成编译后,llvm-gcc 会生成 helloworld.s 文件,您可以使用 lli 来执行该文件,将消息输出到控制台。lli 的用法如下:
Tintin.local# lli helloworld.s
Hello, World

现在,先看一下 LLVM 汇编语言。清单 2 给出了该代码。

清单 2. Hello World 程序的 LLVM 字节代码
    
@.str = private constant [13 x i8] c"Hello World!\00", align 1 ;

define i32 @main() ssp {
entry:
  %retval = alloca i32
  %0 = alloca i32
  %"alloca point" = bitcast i32 0 to i32
  %1 = call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @.str, i64 0, i64 0))
  store i32 0, i32* %0, align 4
  %2 = load i32* %0, align 4
  store i32 %2, i32* %retval, align 4
  br label %return
return:
  %retval1 = load i32* %retval
  ret i32 %retval1
}

declare i32 @puts(i8*)

LLVM 提供了一个详细的汇编语言表示(参阅 参考资料 获取相关的链接)。在开始编写我们之前讨论的自己的 Hello World 程序版本之前,有几个需知事项:
  • LLVM 汇编语言中的注解以分号 (;) 开始,并持续到行末。
  • 全局标识符要以 @ 字符开始。所有的函数名和全局变量都必须以 @ 开始。
  • LLVM 中的局部标识符以百分号 (%) 开始。标识符典型的正则表达式是 [%@][a-zA-Z$._][a-zA-Z$._0-9]*
  • LLVM 拥有一个强大的类型系统,这也是它的一大特性。LLVM 将整数类型定义为 iN,其中 N 是整数占用的字节数。您可以指定 1 到 223- 1 之间的任意位宽度。
  • 您可以将矢量或阵列类型声明为 [no. of elements X size of each element]。对于字符串 "Hello World!",可以使用类型 [13 x i8],假设每个字符占用 1 个字节,再加上为 NULL 字符提供的 1 个额外字节。
  • 您可以对 hello-world 字符串的全局字符串常量进行如下声明:@hello = constant [13 x i8] c"Hello World!\00"。使用关键字 constant 来声明后面紧跟类型和值的常量。我们已经讨论过类型,所以现在让我们来看一下值:您以 c 开始,后面紧跟放在双引号中的整个字符串(其中包括 \0 并以 0 结尾)。不幸的是,关于字符串的声明为什么需要使用 c 前缀,并在结尾处包含 NULL 字符和 0,LLVM 文档未提供任何解释。如果您有兴趣研究更多有关 LLVM 的语法怪现象,请参阅 参考资料,获取语法文件的链接。
  • LLVM 允许您声明和定义函数。而不是仔细查看 LLVM 函数的整个特性列表,我只需将精力集中在基本要点上即可。以关键字 define 开始,后面紧跟返回类型,然后是函数名。返回 32 字节整数的 main 的简单定义类似于:define i32 @main() { ; some LLVM assembly code that returns i32 }
  • 函数声明,顾名思义,有着重大的意义。这里提供了 puts 方法的最简单声明,它是 printfdeclare i32 puts(i8*) 的 LLVM 等同物。该声明以关键字 declare 开始,后面紧跟着返回类型、函数名,以及该函数的可选参数列表。该声明必须是全局范围的。
  • 每个函数均以返回语句结尾。有两种形式的返回语句:ret  或 ret void。对于您简单的主例程,使用ret i32 0 就足够了。
  • 使用 call  来调用函数。注意,每个函数参数都必须放在其类型的前面。返回一个 6 位的整数并接受一个 36 位的整数的函数测试的语法如下:call i6 @test( i36 %arg1 )
这只是一个开始。您还需要定义一个主例程、一个存储字符串的常量,以及处理实际打印的 puts 方法的声明。清单 3 显示第一次尝试创建的程序。

清单 3. 第一次尝试创建手动编写的 Hello World 程序
    
declare  i32 @puts(i8*) 
@global_str = constant [13 x i8] c"Hello World!\00"
define i32 @main { 
  call i32 @puts( [13 x i8] @global_str )
  ret i32 0 
}

这里提供了来自 lli 的日志:
lli: test.s:5:29: error: global variable reference must have pointer type
  call i32 @puts( [13 x i8] @global_str )
                            ^

程序并未按预期的运行。发生了什么?如之前所提及的,LLVM 拥有一个强大的类型系统。因为 puts 期望提供一个指向 i8 的指针,并且您能传递一个 i8 矢量,这样 lli 才能快速指出错误。该问题的常用解决方法(来自 C 编程背景)是使用类型转换。这将您引向了 LLVM 指令 getelementptr。请注意,您必须将 清单 3 中的 puts 调用修改为与 call i32 @puts(i8* %t) 类似,其中%t 是类型 i8*,并且是 [13 x i8] to i8* 的类型转换结果。(请参阅 参考资料,获取 getelementptr 的详细描述的链接。)在进一步探讨之前,清单 4 提供了可行的代码。

清单 4. 使用 getelementptr 正确地将类型转换为指针
    
declare i32 @puts (i8*)
@global_str = constant [13 x i8] c"Hello World!\00"

define i32 @main() {
  %temp = getelementptr [13 x i8]*  @global_str, i64 0, i64 0
  call i32 @puts(i8* %temp)
  ret i32 0
}

getelementptr 的第一个参数是全局字符串变量的指针。要单步执行全局变量的指针,则需要使用第一个索引,即 i64 0。因为getelementptr 指令的第一个参数必须始终是 pointer 类型的值,所以第一个索引会单步调试该指针。0 值表示从该指针起偏移 0 元素偏移量。我的开发计算机运行的是 64 位 Linux®,所以该指针是 8 字节。第二个索引 (i64 0) 用于选择字符串的第 0 个元素,该元素是作为 puts 的参数来提供的。
http://www.ibm.com/developerworks/cn/opensource/os-createcompilerllvm1/


了解 LLVM IR 是件好事,但是您需要一个自动化的代码生成系统,用它来转储 LLVM 汇编语言。谢天谢地,LLVM 提供了强大的应用程序编程接口 (API) 支持,让您可以查看整个过程(请参阅 参考资料,获取程序员手册的链接)。在您的开发计算机上查找 LLVMContext.h 文件;如果该文件缺失,那么可能是您安装 LLVM 的方式出错。
现在,让我们创建一个程序,为之前讨论的 Hello World 程序生成 LLVM IR。该程序不会处理这里的整个 LLVM API,但是接下来的代码样例会证明,适量位数的 LLVM API 很直观而且易于使用。
LLVM 提供了一款出色的工具,叫做 llvm-config(参阅 参考资料)。运行 llvm-config –cxxflags,获取需要传递至 g++ 的编译标志、链接器选项的 llvm-config –ldflags 以及 llvm-config –ldflags,以便针对正确的 LLVM 库进行链接。在 清单 5的样例中,所有的选项均需要传递至 g++。

清单 5. 通过 LLVM API 使用 llvm-config 构建代码
    
tintin# llvm-config --cxxflags --ldflags --libs \
-I/usr/include  -DNDEBUG -D_GNU_SOURCE \
-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS \
-D__STDC_LIMIT_MACROS -O3  -fno-exceptions -fno-rtti -fno-common \
-Woverloaded-virtual -Wcast-qual \
-L/usr/lib  -lpthread -lm \
-lLLVMXCoreCodeGen -lLLVMTableGen -lLLVMSystemZCodeGen \
-lLLVMSparcCodeGen -lLLVMPTXCodeGen \
-lLLVMPowerPCCodeGen -lLLVMMSP430CodeGen -lLLVMMipsCodeGen \
-lLLVMMCJIT -lLLVMRuntimeDyld \
-lLLVMObject -lLLVMMCDisassembler -lLLVMXCoreDesc -lLLVMXCoreInfo \
-lLLVMSystemZDesc -lLLVMSystemZInfo \
-lLLVMSparcDesc -lLLVMSparcInfo -lLLVMPowerPCDesc -lLLVMPowerPCInfo \
-lLLVMPowerPCAsmPrinter \
-lLLVMPTXDesc -lLLVMPTXInfo -lLLVMPTXAsmPrinter -lLLVMMipsDesc \
-lLLVMMipsInfo -lLLVMMipsAsmPrinter \
-lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter \
-lLLVMMBlazeDisassembler -lLLVMMBlazeAsmParser \
-lLLVMMBlazeCodeGen -lLLVMMBlazeDesc -lLLVMMBlazeAsmPrinter \
-lLLVMMBlazeInfo -lLLVMLinker -lLLVMipo \
-lLLVMInterpreter -lLLVMInstrumentation -lLLVMJIT -lLLVMExecutionEngine \
-lLLVMDebugInfo -lLLVMCppBackend \
-lLLVMCppBackendInfo -lLLVMCellSPUCodeGen -lLLVMCellSPUDesc \
-lLLVMCellSPUInfo -lLLVMCBackend \
-lLLVMCBackendInfo -lLLVMBlackfinCodeGen -lLLVMBlackfinDesc \
-lLLVMBlackfinInfo -lLLVMBitWriter \
-lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen \
-lLLVMX86Desc -lLLVMX86AsmPrinter -lLLVMX86Utils \
-lLLVMX86Info -lLLVMAsmParser -lLLVMARMDisassembler -lLLVMARMAsmParser \
-lLLVMARMCodeGen -lLLVMARMDesc \
-lLLVMARMAsmPrinter -lLLVMARMInfo -lLLVMArchive -lLLVMBitReader \
-lLLVMAlphaCodeGen -lLLVMSelectionDAG \
-lLLVMAsmPrinter -lLLVMMCParser -lLLVMCodeGen -lLLVMScalarOpts \
-lLLVMInstCombine -lLLVMTransformUtils \
-lLLVMipa -lLLVMAnalysis -lLLVMTarget -lLLVMCore -lLLVMAlphaDesc \
-lLLVMAlphaInfo -lLLVMMC -lLLVMSupport

LLVM 模块类是其他所有 LLVM IR 对象的顶级容器。LLVM 模块类能够包含全局变量、函数、该模块所依赖的其他模块和符号表等对象的列表。这里将提供了 LLVM 模块的构造函数:
explicit Module(StringRef ModuleID, LLVMContext& C);

要构建您的程序,必须从创建 LLVM 模块开始。第一个参数是该模块的名称,可以是任何虚拟的字符串。第二个参数称为LLVMContextLLVMContext 类有些晦涩,但用户足以了解它提供了一个用来创建变量等对象的上下文环境。该类在多线程的上下文环境中变得非常重要,您可能想为每个线程创建一个本地上下文环境,并且想让每个线程完全独立于其他上下文环境运行。目前,使用这个默认的全局上下文来处理 LLVM 所提供的代码。这里给出了创建模块的代码:
llvm::LLVMContext& context = llvm::getGlobalContext();

llvm::Module* module = new llvm::Module("top", context);

您要了解的下一个重要类是能实际提供 API 来创建 LLVM 指令并将这些指令插入基础块的类:IRBuilder 类。IRBuilder 提供了许多华而不实的方法,但是我选择了最简单的可行方法来构建一个 LLVM 指令,即使用以下代码来传递全局上下文:
llvm::LLVMContext& context = llvm::getGlobalContext();

llvm::Module* module = new llvm::Module("top", context);

llvm::IRBuilder<> builder(context); 

准备好 LLVM 对象模型后,就可以调用模块的 dump 方法来转储其内容。清单 6 给出了该代码。

清单 6. 创建一个转储模块
    
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Support/IRBuilder.h"

int main()
{
  llvm::LLVMContext& context = llvm::getGlobalContext();
  llvm::Module* module = new llvm::Module("top", context);
  llvm::IRBuilder<> builder(context); 

  module->dump( );
}

运行 清单 6 中的代码之后,控制台的输出如下:
; ModuleID = 'top'

然后,您需要创建 main 方法。LLVM 提供了 llvm::Function 类来创建一个函数,并提供了 llvm::FunctionType 将该函数与某个返回类型相关联。此外,请记住,main 方法必须是该模块的一部分。清单 7 给出了该代码。

清单 7. 将 main 方法添加至顶部模块
    
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Support/IRBuilder.h"

int main()
{
  llvm::LLVMContext& context = llvm::getGlobalContext();
  llvm::Module *module = new llvm::Module("top", context);
  llvm::IRBuilder<> builder(context); 

  llvm::FunctionType *funcType = 
      llvm::FunctionType::get(builder.getInt32Ty(), false);
  llvm::Function *mainFunc = 
      llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module);

  module->dump( );
}

请注意,您需要让 main 返回 void,这就是您调用 builder.getVoidTy() 的原因;如果 main 返回 i32,那么该调用会是builder.getInt32Ty()。在编译并运行 清单 7 中的代码后,出现的结果如下:
; ModuleID = 'top'
declare void @main()

您还尚未定义 main 要执行的指令集。为此,您必须定义一个基础块并将其与 main 方法关联。基础块 是 LLVM IR 中的一个指令集合,拥有将标签(类似于 C 标签)定义为其构造函数的一部分的选项。builder.setInsertPoint 会告知 LLVM 引擎接下来将指令插入何处。清单 8 给出了该代码。

清单 8. 向 main 添加一个基础块
    
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Support/IRBuilder.h"

int main()
{
  llvm::LLVMContext& context = llvm::getGlobalContext();
  llvm::Module *module = new llvm::Module("top", context);
  llvm::IRBuilder<> builder(context); 

  llvm::FunctionType *funcType = 
      llvm::FunctionType::get(builder.getInt32Ty(), false);
  llvm::Function *mainFunc = 
      llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module);

  llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "entrypoint", mainFunc);
  builder.SetInsertPoint(entry);

  module->dump( );
}

这里提供了 清单 8 的输出。请注意,由于现在已经定义了 main 的基础块,所以 LLVM 转储将 main 看作为是一个方法定义,而不是一个声明。非常酷!
; ModuleID = 'top'
define void @main() { 
entrypoint: 
}

现在,向代码添加全局 hello-world 字符串。清单 9 给出了该代码。

清单 9. 向 LLVM 模块添加全局字符串
    
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Support/IRBuilder.h"

int main()
{
  llvm::LLVMContext& context = llvm::getGlobalContext();
  llvm::Module *module = new llvm::Module("top", context);
  llvm::IRBuilder<> builder(context); 

  llvm::FunctionType *funcType = 
      llvm::FunctionType::get(builder.getVoidTy(), false);
  llvm::Function *mainFunc = 
      llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module);

  llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "entrypoint", mainFunc);
  builder.SetInsertPoint(entry);

  llvm::Value *helloWorld = builder.CreateGlobalStringPtr("hello world!\n");

  module->dump( );
}

在 清单 9 的输出中,注意 LLVM 引擎是如何转储字符串的:
; ModuleID = 'top'
@0 = internal unnamed_addr constant [14 x i8] c"hello world!\0A\00"
define void @main() {
entrypoint:
}

现在您需要做的就是声明 puts 方法,并且调用它。要声明 puts 方法,则必须创建合适的 FunctionType*。从您的 Hello World 源始代码中,您知道 puts 返回了 i32 并接受 i8* 作为输入参数。清单 10 给出了创建 puts 的正确类型的代码。

清单 10. 声明 puts 方法的代码
    
  std::vector putsArgs;
  putsArgs.push_back(builder.getInt8Ty()->getPointerTo());
  llvm::ArrayRef  argsRef(putsArgs);

  llvm::FunctionType *putsType = 
    llvm::FunctionType::get(builder.getInt32Ty(), argsRef, false);
  llvm::Constant *putsFunc = module->getOrInsertFunction("puts", putsType);

FunctionType::get 的第一个参数是返回类型;第二个参数是一个 LLVM::ArrayRef 结构,并且最后的 false 指明了后面未跟可变数量的参数。ArrayRef 结构与矢量相似,只是它不包含任何基础数据,并且主要用于包装诸如阵列和矢量等数据块。由于这个改变,输出显示将如 清单 11 所示。

清单 11. 声明 puts 方法
    
; ModuleID = 'top'
@0 = internal unnamed_addr constant [14 x i8] c"hello world!\0A\00"
define void @main() {
entrypoint:
}
declare i32 @puts(i8*)

剩下要做的是调用 main 中的 puts 方法,并从 main 中返回。LLVM API 非常关注转换等操作:您需要做的是调用 puts 来调用builder.CreateCall。最后,要创建返回语句,请调用 builder.CreateRetVoid清单 12 提供了完整的运行代码。

清单 12. 输出 Hello World 的完整代码
    
#include "llvm/ADT/ArrayRef.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/Support/IRBuilder.h"
#include 
#include 

int main()
{
  llvm::LLVMContext & context = llvm::getGlobalContext();
  llvm::Module *module = new llvm::Module("asdf", context);
  llvm::IRBuilder<> builder(context);

  llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getVoidTy(), false);
  llvm::Function *mainFunc = 
    llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module);
  llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "entrypoint", mainFunc);
  builder.SetInsertPoint(entry);

  llvm::Value *helloWorld = builder.CreateGlobalStringPtr("hello world!\n");

  std::vector putsArgs;
  putsArgs.push_back(builder.getInt8Ty()->getPointerTo());
  llvm::ArrayRef  argsRef(putsArgs);

  llvm::FunctionType *putsType = 
    llvm::FunctionType::get(builder.getInt32Ty(), argsRef, false);
  llvm::Constant *putsFunc = module->getOrInsertFunction("puts", putsType);

  builder.CreateCall(putsFunc, helloWorld);
  builder.CreateRetVoid();
  module->dump();
}

在这篇初步了解 LLVM 的文章中,了解了诸如 lli 和 llvm-config 等 LLVM 工具,还深入研究了 LLVM 中间代码,并使用 LLVM API 来为您自己生成中间代码。本系列的第二部分(也是最后一部分)将探讨可以使用 LLVM 完成的另一项任务,即毫不费力地添加额外的编译传递。

2013年9月22日星期日

Adding Cocos2d (2.0) to existing iPhone Project

添加 cocos2d 2.0 到现有的工程

http://www.ggkf.com/xcode/adding-cocos2d-2-0-to-existing-iphone-project

http://www.cocos2d-iphone.org/forums/topic/adding-cocos2d-2-0-to-existing-iphone-project/


步骤:

Step 1.
Create a test project in Cocos2d and find the “libs” folder in finder, and then just copy it into your project’s folder in finder. Then from finder, drag-and-drop the “libs” folder into Xcode’s “Project Navigator” sidebar and check the “add files to destination”.
Step 2.
In Project > Targets > Build Phases > Link Binaries with libraries > Hit the + and Check if following frameworks are there if not add them:

  1. AVFoundation.framework

  2. GameKit.framework

  3. CoreText.framework

  4. AudioToolbox.framework
  5. OpenAL.framework

  6. QuartzCore.framework

  7. CoreGraphics.framework

  8. UIKit.framework

  9. Foundation.framework
  10. OpenGLES.framework
Step 3.
In Project > Targets > Build Settings > Search Paths > Header Search Paths
Add (quotes included) this
“(your Project’s folder name in finder)/libs/kazmath/include”
Step 4.
In Project > Targets > Build Phases > Link Binaries with libraries > Compile Sources
Select all files except classes that are your project already and hit enter and add the Compiler Flag -fno-objc-arc.
By doing that, hopefully all the Cocos2D files are now ARC-disabled.
Try to Build at this moment….
If there are issues then continue
Step 5.
Go to Project > Targets > Build Settings > Linking > “Other linker flags”
Add -lz and -ObjC .
Build again to check any issue still exists…
Step 6.
Go to Project > Targets > Build Settings >Search Paths > User Header Search Paths
Add this
./(your Project’s folder name in finder)/libs/kazmath/include
Now try to build.. The issues might have gone by now.
I got help from the Coco2d forum and would like to thank the forum members..

2013年9月17日星期二

OSX10.7 安装mysql-python报错cc1: error: unrecognized command line option

Mac OS X 10.7 安装 mysql-python 报错

cc1: error: unrecognized command line option "-Wno-null-conversion"
error: Setup script exited with error: command 'llvm-gcc-4.2' failed with exit status 1

应该是 llvm-gcc-4.2 的编译器不识别 option 导致的



http://stackoverflow.com/questions/16127493/cc1-error-unrecognized-command-line-option-wno-null-conversion-within-insta


将 mysql_config 里面的相关 option 去掉再次编译就可以了 



Try to Remove cflags -Wno-null-conversion -Wno-unused-private-field in
/usr/local/mysql/bin/mysql_config.
like:
cflags="-I$pkgincludedir  -Wall   -Os -g -fno-strict-aliasing -DDBUG_OFF -arch x86_64 "

2013年9月8日星期日

自动代理配置 PAC

http://zh.wikipedia.org/zh/%E4%BB%A3%E7%90%86%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE

PAC简介:
代理自动配置(PAC)文件定义了浏览器和其他用户代理如何自动选择适当的代理服务器来访问一个URL。
一个PAC文件包含一个JavaScript的函数"FindProxyForURL(url, host)". 这个函数返回一个包含一个或多个访问规则的字符串。用户代理根据这些规则适用一个特定的代理其或者直接访问。 当一个代理服务器无法响应的时候,多个访问规则提供了其他的后备访问方法。 浏览器在访问其他页面以前,首先访问这个PAC文件。PAC文件中的URL可能是手工配置的,也可能是是通过网页的网络代理自发现协议(Web Proxy Autodiscovery Protocol)自动配置的。

现代的浏览器实现了几个级别的自动化;用户可以选择最适合他们需要的级别。下面的这些方法被普遍的实现:
  • 手动代理配置:为所有的URLs规定一个主机名和端口作为代理。大多数浏览器允许用户规定一个域名的列表(例如 localhost),访问这个列表里面的域名的时候不通过代理服务器。
  • 代理自动配置(PAC): 规定一个指向PAC文件的URL,这个文件中包括一个JavaScript函数来确定访问每个URL时所选用的合适代理。这个方法更加适合需要几个不同代理配置的笔记本用户,或者有很多不同代理服务器的复杂的企业级设置。这个就是我们在本文中所要讨论的。
  • 网络代理自发现协议(WPAD): 浏览器通过DHCP和DNS的查询来搜索PAC文件的位置。

PAC的使用:
要使用PAC,我们应当在一个网页服务器上发布一个PAC文件,并且通过在浏览器的代理链接设置页面输入这个PAC文件的URL或者通过使用WPAD协议告知用户代理去使用这个文件。
一个PAC文件是一个至少定义了一个JavaScript函数的文本文件。这个函数FindProxyForURL(url, host)有2个参数:url是一个对象的URL,host是一个由这个URL所衍生的主机名。按照惯例,这个文件名字一般是proxy.pac. WPAD标准使用wpad.dat.
虽然大多数客户端无论从HTTP请求返回的MIME类型是什么都能正确处理,但为了完整性和最佳的兼容性,我们应该设置网页服务器将这个文件的MIME类型声明为 application/x-ns-proxy-autoconfig 或者 application/x-javascript-config .
没有什么理由偏爱一种MIME类型多一些,如果有的话,假设 application/x-ns-proxy-autoconfig 相对 application/x-javascript-config 被更多的客户端所支持是可以理解的。因为它被定义在最初的Netscape规范里面,后者是最近才开始被使用。
一个非常简单的PAC文件内容
   function FindProxyForURL(url, host) { return "PROXY proxy.example.com:8080; DIRECT"; }
这个函数告知浏览器通过服务器proxy.example.com的8080端口来获取所有的页面。如果这个服务器没有反应,那么浏览器应该不使用代理服务器直接访问WWW

高级PAC:
有些高级的PAC文件可以在请求到达代理服务器以前通过负载平衡,故障转移甚至黑白名单得方法减少对于代理服务器的负载。并且可以返回多个代理服务器。