如转载本文,请注明出处:http://blog.youkuaiyun.com/shuimuniao。
2>------ 已启动生成: 项目: JavaScriptCoreGenerated, 配置: Debug Win32 ------
2>正在执行生成文件项目操作
2>系统找不到指定的路径。
2> touch "%ConfigurationBuildDir%\buildfailed"
2> bash build-generated-files.sh "%ConfigurationBuildDir%" "D:\WorkSpace\WebKit\WebKitLibraries\win"
2>python /cygdrive/d/WORKSP~1/WebKit/Source/JAVASC~1/KeywordLookupGenerator.py /cygdrive/d/WORKSP~1/WebKit/Source/JAVASC~1/parser/Keywords.table > KeywordLookup.h
2>Traceback (most recent call last):
2> File "/cygdrive/d/WORKSP~1/WebKit/Source/JAVASC~1/KeywordLookupGenerator.py", line 209, in <module>
2> keywords = parseKeywords(keywordsText)
2> File "/cygdrive/d/WORKSP~1/WebKit/Source/JAVASC~1/KeywordLookupGenerator.py", line 79, in parseKeywords
2> raise Exception("expected description ending with @end")
2>Exception: expected description ending with @end
2>make: *** [KeywordLookup.h] Error 1
2>NMAKE : fatal error U1077:
2>Stop.
2>Project : error PRJ0019: 工具从"正在执行生成文件项目操作"
2>项目 : warning PRJ0018 : 未找到下列环境变量:
2>$(PRODUCTION)
2>生成日志保存在“file://D:\WorkSpace\WebKit\WebKitBuild\Debug\obj\JavaScriptCoreGenerated\BuildLog.htm”
2>JavaScriptCoreGenerated - 2 个错误,0 个警告
这是我第二次遇到这个错误了,印象中上次费了好大的力气解决这个问题。因此,这次一定要记录下来分析问题、解决问题的过程。
第一步,从打印中收集足够的信息。
* 项目JavaScriptCoreGenerated会解析Source/JavascriptCore/parser/Keywords.table文件,生成KeywordLookup.h文件。
* 使用了Source/JavascriptCore/KeywordLookupgenerator.py脚本来完成解析工作。
* 在编译webkit之前,我已经使用dos2unix_on_webkit.py脚本对所有sh、asm脚本作了处理,保证所有的sh、asm脚本的换行符都是unix格式的,而非dos格式的。
* 解析出错的原因是:keywords.table的尾行不是@end。
第二步,分析KeywordLookupgenerator.py的工作流程。主函数的源码如下:
def parseKeywords(keywordsText):
lines = keywordsText.split("\n")
lines = [line.split("#")[0] for line in lines]
lines = [line for line in lines if (not allWhitespace(line))]
name = lines[0].split()
terminator = lines[-1]
if not name[0] == "@begin":
raise Exception("expected description beginning with @begin")
if not terminator == "@end":
raise Exception("expected description ending with @end")
lines = lines[1:-1] # trim off the old heading
return [line.split() for line in lines]
- 首先将keywords.table的内容分隔成数组,分隔符是换行符'\n'。这里要考虑一个问题:'\n'是unix格式,还是dos格式,还是没有关系。考虑到python是跨平台的,python自身应该会解决平台问题。因此,最后测试'\n'的正确性。
- 然后将"# ..."格式的元素删除。这一步处理后,原来为"#..."格式的字符串会变为。
- 然后将只包含空格的字符串删除。这一步没有任何问题。
- 然后把首行按照空格分隔,分隔形成的新数组放入name中。
- 然后把尾行取出来存入terminator中。
- 期望首行以@begin开始。
- 期望尾行为@end。
- 最后把除首行、尾行之外的内容返回。
第三步,结合keywords.table文件分析数据变化。
keywords.table文件最后两行的数据如下高亮部分。
- 可以预期按照'\n'分隔之后,最后两行变为["yield sp sp sp ... sp sp RESERVED_IF_STRICT",null,"@end",null]。
- 将"#..."格式元素删除之后,最后两行不变。
- 将只包含空格字符的字符串删除后,最后两行变为["yield sp sp ... sp sp RESERVED_IF_STRICT","@end"]。
- 最后terminator中存储的是"@end"。
第四步,在KeywordLookupgenerator.py文件中加打印,把处理后的结果打印出来。与我预期数据作比较,看一看是否有错误数据。加完打印后的运行结果如下:

你妹的!!!和预期效果完全一样!!
第五步,分析terminator中存储的是否有某些不可见的特殊字符。加完打印后,运行结果如下:

可见,terminator中记录一个不可见的字符。这个字符只能与换行符有关。原因很简单:keywords.table源文件中,@end之后只有0xa, 0xd两个字符。
使用dos2unix.exe处理keywords.table文件后,最后两行的数据变为:

可见,换行符变为'0xa'了。
重新运行脚本,打印信息如下:

说明分析的原因是正确的。
附:加完打印语句后,parseKeywords变为如下:
def parseKeywords(keywordsText):
lines = keywordsText.split("\n")
#### added by pengchao.zhang for analyze problem ####
print "=======after split by '/\/n'========="
print lines[-4];
print lines[-3];
print lines[-2];
print lines[-1];
#### added by pengchao.zhang end ####
lines = [line.split("#")[0] for line in lines]
#### added by pengchao.zhang for analyze problem ####
print "=======after remove '#.....========="
print lines[-4];
print lines[-3];
print lines[-2];
print lines[-1];
#### added by pengchao.zhang end ####
lines = [line for line in lines if (not allW hitespace(line))]
#### added by pengchao.zhang for analyze problem ####
print "=======after remove empty line========="
print lines[-4];
print lines[-3];
print lines[-2];
print lines[-1];
#### added by pengchao.zhang end ####
name = lines[0].split()
terminator = lines[-1]
print "terminator(%s) == \"@end\" returns %s " % (terminator, terminator == "@end")
i=0
for c in terminator:
print "%d:%c " % (i, c)
i+=1
if not name[0] == "@begin":
raise Exception("expected description beginning with @begin")
if not terminator == "@end":
raise Exception("expected description ending with @end")
lines = lines[1:-1] # trim off the old heading
return [line.split() for line in lines]