2014.5.16

为了验证一下下载的CM11的源码有没有问题,决定编译一下cm官方支持的机器,手上正好有台nexus7
2012,就拿它为例测试一下在mac os x平台的整个编译过程。

1.

最开始,是在os x下面搭编译环境,以前有说过的,详见xda这个帖子。
http://forum.xda-developers.com/showthread.php?t=2510898

这个wiki里面写的是在linux下面编译n7的方法,还是比较详细的,建议先通读一下,对于在os
x下搭编译环境也是很有指导意义的。
http://wiki.cyanogenmod.org/w/Build_for_grouper

2.

repo sync完cm11所有的源码之后,还需要拖device的文件以及内核源码。按照官方wiki的说法,直接用breakfast
grouper它就会自动从github上面拉所有需要的东西,但实测可能是网络原因这里行不通,所以只能手动拖了,这里只需要拖n7的device部分和kernel
source部分。

从cm的官方github页面
https://github.com/cyanogenmod
搜索设备代号,这里就是grouper(nexus7
2012的代号),有两个结果:android_kernel_asus_grouper和android_device_asus_grouper。点进去把这两个项目git
clone下来,或者直接用页面右下方的Download ZIP下载焉。

3.

把上面的device和kernel下载下来之后要放对位置,cd
到cm11的源码树的根目录,我这里是/Volumes/cm/cm11。

mkdir -p device/asus/grouper

mkdir -p kernel/asus/grouper

再把刚才下载的device和kernel解压并放到上面新建的两个目录里面。

就可以按照官方的编译方法envsetup.sh->breakfast grouper->croot->brunch
grouper -j4编译了。

4.

[20:22:34]  
GEN    
/Volumes/cm/cm11/out/target/product/grouper/obj/KERNEL_OBJ/Makefile

[20:22:35]   SHIPPED
scripts/kconfig/zconf.tab.c

[20:22:35]  
HOSTCC  scripts/kconfig/zconf.tab.o

[20:22:35] scripts/kconfig/zconf.tab.c:200:10: fatal error:
'zconf.hash.c' file not found

[20:22:35] #include "zconf.hash.c"

[20:22:35]         
^

[20:22:36] host StaticLib: libclangFrontendTool
(/Volumes/cm/cm11/out/host/darwin-x86/obj/STATIC_LIBRARIES/libclangFrontendTool_intermediates/libclangFrontendTool.a)

[20:22:36] 1 error generated.

[20:22:36] make[3]: *** [scripts/kconfig/zconf.tab.o] Error 1

[20:22:36] make[2]: *** [cyanogenmod_grouper_defconfig] Error
2

[20:22:36] make[1]: *** [sub-make] Error 2

[20:22:36] make: ***
[/Volumes/cm/cm11/out/target/product/grouper/obj/KERNEL_OBJ/.config]
Error 2

[20:22:36] make: *** Waiting for unfinished jobs....

在内核目录不要自己手动用make或make
uImage编译内核,它会干扰到编译整个代码树导致报错。如果之前有这么做过,可以通过删除out/target/product/grouper/obj/KERNEL_OBJ整个文件夹,并在内核目录里面make
mrproper一下来重新clean掉内核源码目录。同时建议在内核的源码目录在brunch之前就make
mrproper一下。

上面这个错误就是由于kernel目录不干净导致的,删除out里面的KERNEL_OBJ和make
mrproper之后不再报错,并不需要像网上说的那样make clobber清掉整个out目录。

5.

[20:08:14] /bin/sh: /bin/false: No such file or
directory

这个看起来像是找不到/bin/false这个程序导致的,在os
x的终端里which false一下,发现位置是/usr/bin/false,这就好办,直接ln
-s一个到/bin目录即可。

ln -s /usr/bin/false /bin/false

6.

[23:08:58] 警告: [options] 未与 -source 1.5 一起设置引导类路径

[23:09:06]
external/doclava/src/com/google/doclava/ClassInfo.java:20: 错误:
程序包com.sun.javadoc不存在

[23:09:06] import com.sun.javadoc.ClassDoc;

[23:09:06]                      
^

[23:09:07]
external/doclava/src/com/google/doclava/ClassInfo.java:61: 错误:
找不到符号

[23:09:07]   public
ClassInfo(ClassDoc cl, String rawCommentText, SourcePositionInfo
position,

[23:09:07]                   
^

[23:09:07]  
符号:   类 ClassDoc

[23:09:07]   位置: 类
ClassInfo

在os
x平台编译cm的话jdk必须要有1.6版的,可以只有1.6,也可以1.6、1.7共存,但不能只有1.7,上面的报错就是因为只有jdk1.7导致的。

苹果官方在jdk6下载地址: http://support.apple.com/kb/DL1572?viewlocale=zh_CN

7.

[00:33:30]   Kernel:
arch/arm/boot/zImage is ready

[00:33:30]  
UIMAGE  arch/arm/boot/uImage

[00:33:30] "mkimage" command not found - U-Boot images will not be
built

[00:33:30] make[3]: *** [arch/arm/boot/uImage] Error 1

[00:33:30] make[2]: *** [uImage] Error 2

[00:33:30] make[1]: *** [sub-make] Error 2

[00:33:30] make: *** [TARGET_KERNEL_BINARIES] Error 2

[00:33:30] make: *** Waiting for unfinished jobs....

找不到mkimage这个程序,去下载一个uboot的源码:ftp://ftp.denx.de/pub/u-boot/u-boot-2012.10.tar.bz2

解压,并进入,make tools -j4编译一下uboot
tools,半分钟就可以完成,在tools目录下面把mkimage拷到系统任何一个PATH目录里面即可。

或者也可以用brew安装:brew
install u-boot-tools,不过我这边没速度,于是就手动下载源码自己编译一个mkimage出来了。

8.

整个编译过程大概需要2小时左右,配置是i5
2300,16G内存,硬盘是2.5的5400rpm,可以根据CPU性能自行判断,看到下面的最后一句,Package
Complete,就说明全部编译完成了。

[22:26:16] using
device-specific extensions in device/asus/grouper

[22:26:36] building image from target_files BOOT...

[22:26:36]  
running:  mkbootfs -f
/var/folders/8_/kgjn7sms2mz3vn_psjgt2mlc0000gn/T/targetfiles-0EEWjX/META/boot_filesystem_config.txt
/var/folders/8_/kgjn7sms2mz3vn_psjgt2mlc0000gn/T/targetfiles-0EEWjX/BOOT/RAMDISK

[22:26:36]  
running:  minigzip

[22:26:36]  
running:  mkbootimg --kernel
/var/folders/8_/kgjn7sms2mz3vn_psjgt2mlc0000gn/T/targetfiles-0EEWjX/BOOT/kernel
--ramdisk
/var/folders/8_/kgjn7sms2mz3vn_psjgt2mlc0000gn/T/tmpnm2TAe --output
/var/folders/8_/kgjn7sms2mz3vn_psjgt2mlc0000gn/T/tmpNzgBUc

[22:26:37] no bootloader.raw in target_files; skipping
install

[22:26:37]  
running:  openssl pkcs8 -in
build/target/product/security/testkey.pk8 -inform DER
-nocrypt

[22:26:37]  
running:  java -Xmx2048m -jar
/Volumes/cm/cm11/out/host/darwin-x86/framework/signapk.jar -w
build/target/product/security/testkey.x509.pem
build/target/product/security/testkey.pk8
/var/folders/8_/kgjn7sms2mz3vn_psjgt2mlc0000gn/T/tmp_RfPg5
/Volumes/cm/cm11/out/target/product/grouper/cm_grouper-ota-f0d0985f7a.zip

[22:27:08] done.

[22:27:09] Package Complete:
/Volumes/cm/cm11/out/target/product/grouper/cm-11-20140516-UNOFFICIAL-grouper.zip

k860i 移植Android 4.4 cm11进度记录【上篇已完结】" title="Lenovo k860i 移植Android 4.4 cm11进度记录【上篇已完结】">

--------------------------------------------------------------------------------------------

2014.5.14

有好长一段时间没写进度日志了,期间主板又因为内存识别的问题给返修了,好在最终还是弄好了。不过起码到现在为止还是没有放弃ki的cm11,如果哪天实在是做不下去了,肯定会说明的。

最近没有什么进展,倒是弄好了一个TWRP,这个recovery功能是比较强大的,不过现在还是有点小问题,还在完善中,等到时候完善的差不多了就发出来。

折腾这么久之后发现原来在mac下面编译android需要很多要注意的地方,比如说最重要的一个就是设置
export BUILD_MAC_SDK_EXPERIMENTAL=1
这个环境变量,之前我就是在设置这个环境变量之前就开始编译,但是从来都没有Make
clobber过,所以导致了一堆错误,2号的第一个错误就是由于这个没设置才会出现,而由于我乱改了HOST_darwin-x86.mk这个makefile,这又导致了后面非常多的找不到头文件的问题。

XDA上面有一篇关于介绍在os x
10.9 mavericks配置andorid的编译环境的帖子:
http://forum.xda-developers.com/showthread.php?t=2510898

按照上面的帖子配置之后,如果之前make/mka/lunch/brunch过,一定要make
clobber一下,再重新breakfast/lunch/mka/brunch。由于之前的疏忽,导致花费了大量的时间在毫无意义的地方,然后2号的进度里面的1、6、7都不会再出现错误。。。

继续错误解决方法:

1.

[10:02:11]
bootable/recovery/minui/../../../device/lenovo/stuttgart/recovery/griphics.c:208:5:
error: conflicting types for 'gr_text'

[10:02:11] In file included from
bootable/recovery/minui/../../../device/lenovo/stuttgart/recovery/griphics.c:39:0:

[10:02:11] bootable/recovery/minui/minui.h:36:5: note: previous
declaration of 'gr_text' was here

[10:02:11] make: ***
[/Volumes/cm/cm11/out/target/product/stuttgart/obj/STATIC_LIBRARIES/libminui_intermediates/../../../device/lenovo/stuttgart/recovery/griphics.o]
Error 1

[10:02:11] make: *** Waiting for unfinished jobs....

按scue的说明文件,device/lenovo/stuttgart/recovery/Readme.md,在这个recovery目录里面执行:

cp -v
../overlay/bootable/recovery/bootloader.c
../../../../bootable/recovery/bootloader.c

即用device里面的overlay/bootable/recovery/bootloader.c
替换内核树中的 bootable/recovery/bootloader.c,替换之后不再报错。

不过在替换完文件之后,在修完下一个错误之后,这个错误又出现了。。。。。

仔细看了下报错信息,发现是有个重定义,打开bootable/recovery/minui/minui.h,第36行有一个函数的声明,是这样的:

int gr_text(int x, int y, const char *s, int bold);

再打开device/lenovo/stuttgart/recovery/griphics.c这个文件,第208行有这个函数:

int gr_text(int x, int y, const char *s)

声明和函数定义不一样,参数个数不一样多,于是直接把minui.h这个文件里面的函数声明注释掉,即可继续编译。

另外吐槽一下,scue貌似把文件名都拼错了,griphics.c,应该是graphics.c才对。。。。。

2.

[17:03:04] target thumb C: recovery <=
bootable/recovery/install.c

[17:03:04] bootable/recovery/bootloader.c: In function
'get_bootloader_message_mtd':

[17:03:04] bootable/recovery/bootloader.c:77:60: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:79:43: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:85:49: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:92:60: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c: In function
'set_bootloader_message_mtd':

[17:03:04] bootable/recovery/bootloader.c:103:60: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:105:43: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:111:49: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:118:60: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:126:49: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:130:50: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:135:51: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c: In function
'get_bootloader_message_block':

[17:03:04] bootable/recovery/bootloader.c:167:22: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:168:22: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:170:49: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:176:43: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:181:53: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:185:53: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c: In function
'set_bootloader_message_block':

[17:03:04] bootable/recovery/bootloader.c:194:22: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:195:22: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:197:49: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:202:43: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:208:53: error: 'Volume'
has no member named 'device'

[17:03:04] bootable/recovery/bootloader.c:212:53: error: 'Volume'
has no member named 'device'

[17:03:04] make: ***
[/Volumes/cm/cm11/out/target/product/stuttgart/obj/EXECUTABLES/recovery_intermediates/bootloader.o]
Error 1

[17:03:04] make: *** Waiting for unfinished jobs....

出错的文件是刚刚(上一个错误)从scue的device里面拷过去的bootloader.c,看了下文件,发现是变量名写错了,把上面错误涉及到的所有的变量device都改成blk_device即可继续编译。

3.

[18:18:49] target thumb C++: libnbaio <=
frameworks/av/media/libnbaio/NBAIO.cpp

[18:18:49] frameworks/av/media/libnbaio/AudioStreamOutSink.cpp: In
member function 'virtual android::status_t
android::AudioStreamOutSink::getTimestamp(AudioTimestamp&)':

[18:18:49]
frameworks/av/media/libnbaio/AudioStreamOutSink.cpp:88:18: error:
'struct audio_stream_out' has no member named
'get_presentation_position'

[18:18:49]
frameworks/av/media/libnbaio/AudioStreamOutSink.cpp:93:23: error:
'struct audio_stream_out' has no member named
'get_presentation_position'

[18:18:49] make: ***
[/Volumes/cm/cm11/out/target/product/stuttgart/obj/SHARED_LIBRARIES/libnbaio_intermediates/AudioStreamOutSink.o]
Error 1

[18:18:49] make: *** Waiting for unfinished jobs....

把88-90三行,和93-96行注释掉,即可继续编译。

这个问题看起来是和音频部分相关的,这个方法很有可能是治标不治本。

4.

[19:30:44] target thumb C++: libaudioflinger <=
frameworks/av/services/audioflinger/Effects.cpp

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp: In
member function 'void
android::AudioFlinger::PlaybackThread::readOutputParameters()':

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:1742:31:
error: 'audio_stream_out_t' has no member named
'set_callback'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:1743:30:
error: 'audio_stream_out_t' has no member named
'set_callback'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp: In
member function 'virtual void
android::AudioFlinger::PlaybackThread::threadLoop_drain()':

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:2037:26:
error: 'audio_stream_out_t' has no member named 'drain'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:2046:26:
error: 'audio_stream_out_t' has no member named 'drain'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp: In
member function 'android::status_t
android::AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp&)':

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:2582:46:
error: 'audio_stream_out_t' has no member named
'get_presentation_position'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:2584:36:
error: 'audio_stream_out_t' has no member named
'get_presentation_position'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp: In
member function 'virtual
android::AudioFlinger::PlaybackThread::mixer_state
android::AudioFlinger::OffloadThread::prepareTracks_l(android::Vector
>*)':

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:4328:26:
error: 'audio_stream_out_t' has no member named 'pause'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:4336:26:
error: 'audio_stream_out_t' has no member named 'resume'

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp: In
member function 'void
android::AudioFlinger::OffloadThread::flushHw_l()':

[19:30:44] frameworks/av/services/audioflinger/Threads.cpp:4380:22:
error: 'audio_stream_out_t' has no member named 'flush'

[19:30:44] make: ***
[/Volumes/cm/cm11/out/target/product/stuttgart/obj/SHARED_LIBRARIES/libaudioflinger_intermediates/Threads.o]
Error 1

[19:30:44] make: *** Waiting for unfinished jobs....

又是一个和音频部分想着的错误,这个错误一直没有解决,至今还卡着,所以暂且先放一放。

后面准备给k860i编译一个TWRP的recovery,其实omni
rom的源码树就是自带了TWRP,所以直接把omni rom的bootable/recovery git
clone下来替换cm11的bootable/recovery就可以了。

不过编译twrp之前需要配置好device,找了下教程,大概只需要配一下device/lenovo/stuttgart/BoardConfig.mk这个就可以,貌似最简单的就只要在这文件里面加一行就可以了:

DEVICE_RESOLUTION := 720x1280

然后就是开始编译的过程:

. build/envsetup.sh

breakfast stuttgart

make -j4 recoveryimage

这个过程看机器性能需要的时间也不相同,一般编译recovery都不会出什么错。之前我在笔记本的虚拟机ubuntu里面花了1小时2分钟,后面在台机的os
x上编译,只花了26分钟就完成了,这性能差距也太大了。

不过这个recovery还有些问题,先说在ubuntu下面编译的recovery.img。这个recovery.img用fastboot
flash recovery
recovery.img刷进去之后,第一次进rec完全正常,功能也正常(当然屏幕灭了之后不能唤醒,是因为把电源键的键位定义错了,当然还没有测试过刷一个zip包)。但是奇怪的问题发生了,在rec状态下接上电脑用adb
shell进去,不能reboot,或者直接用adb
reboot也不行,但是直接在twrp里面点reboot按钮是可以重启的。最诡异的是,只要从这个rec重启了,不管是再次进rec或者是直接进系统,都是直接卡第一屏死掉了,看了下串口的内核日志,居然提示找不到内核,这也太奇怪了。后面刷了szb包的别的rec,就可以正常进系统了。暂还没明白到底是什么原因导致的,需要看一下如何解决。

而在os
x上编译的时候,虽然是通过了编译,最终也生成了recovery.img,但是却无法启动进去TWRP,看了下串口内核日志,一直提示这个找不到,无法执行当然就进不到Rec的图形界面了。

[22:59:34] [   20.376399] init:
cannot execve('/sbin/recovery'): Exec format error

[22:59:39] [   25.393742] init:
cannot execve('/sbin/recovery'): Exec format error

[22:59:44] [   30.410832] init:
cannot execve('/sbin/recovery'): Exec format error

[22:59:49] [   35.424186] init:
cannot execve('/sbin/recovery'): Exec format error

再仔细看了下os
x上编译twrp的日志,在快要编译完成的时候出现了一些错误:

[22:49:39] sed: RE error: illegal byte sequence

[22:49:39] cp -fr bootable/recovery/gui/devices/720x1280/res/*
/Volumes/cm/cm11/out/target/product/stuttgart/recovery/root/res/

[22:49:39] sed: RE error: illegal byte sequence

[22:49:39] sed: RE error: illegal byte sequence

[22:49:39] sed: RE error: illegal byte sequence

一直提示sed的RE错误,有可能是这个造成的,还需要找下原因。因为按理说在os
x和linux上编译android也好,编译recovery也好,应该都是没什么区别的,所以还是更有可能是os
x在一些文件上出了点问题,版本不对?参数不对?都有可能。

--------------------------------------------------------------------------------------------

2014.5.2

台机又出问题了,上次是CPU都报错了,不知道是不是换回来的主板有问题,不过当然我把主板从机箱里面拆出来的时候,它又自己好了,但是更蛋疼的问题出来了,16G内存在BIOS的SPD里面能全部看到是4*4G,但是它死活只认8G,网上搜了下说这个华硕主板的通病,只认一半内存,只能去售后重新用编程器刷BIOS,因为用户自己刷的BIOS有些区域是刷不了的,也就是不彻底。看来下周又要去ASUS售后找他们好好理论理论了。

不过好在虽然台机现在裸奔了,而且只能用8G内存,但起码能正常使用了不是,所以趁着五一放假,好好来弄一下cm11的移植了。因为前面已经测试过内核能正常编译,所以现在要正式开始cm11的移植过程了。之前看过cm的官方wiki的移植的文档,大概也都看了下,肯定是料到会有很多问题出现,所以我觉得整个移植的过程就是一个个fix
error的过程,把这个error都fix完了,cm11也就编译出来了,先暂且不说能不能用,能用的前提是要能编译出来东西。之前有考虑转到ubuntu里面去做,不过个人认为os
x实在是用着很舒服,而且在xda上也有很多人成功移植kitkat,所以就更坚定了我不转到ubuntu的决心,虽然可能在os
x下面编译会有各种各样蛋碎的error。以后的进度日志的更新应该绝大多数都会是我在os
x下面编译cm11解决问题的过程和方法了。

OK,
Let's Rock'n'Roll !

在OS
X下面做编译想着的东西是一定要安装xcoda的,我这里是安装的Xcode
5.1,下载的dmg,挂载dmg后把xcode.app扔到/Application里面去。

到scue的github把他做的device文件拖下来,scue真是给k860i的机油做了很多贡献啊,简直就是造福广大机油,在此特别感谢。把scue的device文件放到device/lenovo/stuttgart里面去,我这里用的是枫大的vibe
1412的zip卡刷包作system文件,所以把这个zip解压出来,按照scue的README,把解出来的system文件夹ln
-s符号链接到device/lenovo/stuttgart/tmp/system这个地方。

.
build/envsetup.sh

breakfast stuttgart

./extract-files.sh

extract-files.sh会先打印proprietary-files.txt里面的内容,再从符号链接的system目录里面拉这里定义的文件,因为scue在写这个proprietary的时候ROM版本肯定是和现在的ROM的system文件夹里面的内容不一样的,所以难免有些文件不存在,所以在编译之前就要对照一下proprietary-files.txt里面的内容和符号链接过来的system文件夹里面的内容,把proprietary-files.txt里面有而符号链接的system里面没有的那些行删掉,不然到下面开始编译之后肯定会报错,提示找不到相应的rule
to make。

修改完proprietary-files.txt之后,要重新./extract-files.sh,它会把一些文件复制到
/Volumes/cm/cm11/vendor/lenovo/stuttgart/proprietary
这里去。

当编译过程中遇到有错误,想完全重新编译的时候,可以把out/target/product/stuttgart这个目录删掉即可。

错误解决方法:

1.

[19:18:14] zhufengs-iMac:cm11 zhufeng$ breakfast stuttgart

[19:18:14] including vendor/cm/vendorsetup.sh

[19:18:19] build/core/combo/HOST_darwin-x86.mk:68:
*****************************************************

[19:18:19] build/core/combo/HOST_darwin-x86.mk:69: * Can not find
SDK  at /Developer/SDKs/MacOSX.sdk

[19:18:19] build/core/combo/HOST_darwin-x86.mk:70:
*****************************************************

[19:18:19] build/core/combo/HOST_darwin-x86.mk:71: ***
Stop..  Stop.

修改
/Volumnes/cm/cm11/build/core/combo/HOST_darwin-x86.mk
,把第62行注释掉,即:

# mac_sdk_root :=
$(mac_sdk_path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(mac_sdk_version).sdk

改成:

mac_sdk_version := 10.9

mac_sdk_root :=
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(mac_sdk_version).sdk

注意这两个变量的定义顺序一定不能弄反了,要先定义mac_sdk_version再定义mac_sdk_root,不然还是会报错。

出这个错的原因是makefile找不到Xcode自带的MacOSX
10.9的SDK目录,看了下文件里面定义也没有问题,不知道怎么就是找不到,于是干脆给它定义死了,就不会再报这个错了。

2.

[21:59:23]
/Volumes/cm/cm11/out/target/product/stuttgart/obj/APPS/SignatureTest_intermediates

[21:59:51] find: src: No such file or directory

[21:59:57]
osc_opensource/device/lenovo/stuttgart_row/multimedia/codecs/exynos_codecs/video/Android.mk:5:
osc_opensource/device/lenovo/stuttgart_row/multimedia/codecs/exynos_codecs/video/exynos4/Android.mk:
No such file or directory

[21:59:57] build/core/base_rules.mk:134: ***
osc_opensource/device/lenovo/stuttgart_row/multimedia/codecs/sec_codecs/video/exynos4/mfc:
MODULE.TARGET.STATIC_LIBRARIES.libsecmfcapi already defined by
osc_opensource/device/lenovo/stuttgart/multimedia/codecs/sec_codecs/video/exynos4/mfc. 
Stop.

出现这个错误是因为我把之前联想放出来的源码解压在了cm11的代码树里面,android
build系统会扫描目录下面所有的Android.mk文件,这两个暂时是不需要的,被它扫描到了,也编译了,结果有些文件放的位置不对,所以报错。直接把osc_opensource这个目录移出cm11代码树即可。

3.

[22:01:54] No private recovery resources for TARGET_DEVICE
stuttgart

[22:01:54] build/core/tasks/kernel.mk:44: *** "Please set
BOARD_KERNEL_IMAGE_NAME to uImage". 
Stop.

这个错误,看了下build/core/tasks/kernel.mk,它不再推荐使用预编译好的内核,但内核已经编译好了,所以就直接用了。直接在终端里面
export BOARD_KERNEL_IMAGE_NAME=uImage 即可解决此问题。

4.

[22:33:31] Notice file: external/zlib/NOTICE --
/Volumes/cm/cm11/out/target/product/stuttgart/obj/NOTICE_FILES/src//system/lib/libz.so.txt

[22:33:31] make: *** No rule to make target
`vendor/lenovo/stuttgart/proprietary/lib/libcamera_client.so',
needed by
`/Volumes/cm/cm11/out/target/product/stuttgart/system/lib/libcamera_client.so'. 
Stop.

[22:33:31] make: *** Waiting for unfinished jobs....

这个问题就是由于上面说到的proprietary-files.txt里面定义的的文件和符号链接到的system里面的文件不匹配造成的,如果不把proprietary-files.txt里面定义了而tmp/system里面没有的项全部删掉,它还会报各种No
rule to make
target。所以只能检查proprietary-files.txt,把它里面有而tmp/system里面没有的项目全部删掉,重新招待extract-files.sh。

5.

[01:31:59] Export includes file: external/libsepol/Android.mk --
/Volumes/cm/cm11/out/host/darwin-x86/obj/SHARED_LIBRARIES/libsepol_intermediates/export_includes

[01:31:59] make: *** No rule to make target
`device/lenovo/stuttgart/preload/preload.img', needed by
`/Volumes/cm/cm11/out/target/product/stuttgart/obj/NONE/preload_intermediates/preload.img'. 
Stop.

[01:31:59] make: *** Waiting for unfinished jobs....

这个又是由于少了makefile,编译不了device/lenovo/stuttgart/preload/preload.img,这个文件是scue做的gms包和联想超级相机用的,在做cm11初期暂时可以不用管这个。看了下明明有Android.mk文件,不知道为什么就是提示找不到,既然如此,直接把Android.mk重命名成_Android.mk,让它不编译这个得了。

6.

[02:35:00] host C: mkbootimg <=
system/core/mkbootimg/mkbootimg.c

[02:35:00] host C: libmincrypt <=
system/core/libmincrypt/dsa_sig.c

[02:35:00] host C: libmincrypt <=
system/core/libmincrypt/p256.c

[02:35:00] host C: libmincrypt <=
system/core/libmincrypt/p256_ec.c

[02:35:00] cc1: error: unrecognized command line option
"-arch"

[02:35:00] cc1: error: unrecognized command line option
"-Wno-nested-anon-types"

[02:35:00] make: ***
[/Volumes/cm/cm11/out/host/darwin-x86/obj/STATIC_LIBRARIES/libmincrypt_intermediates/p256.o]
Error 1

[02:35:00] make: *** Waiting for unfinished jobs....

[02:35:01] cc1: error: unrecognized command line option
"-arch"

[02:35:01] cc1: error: unrecognized command line option
"-Wno-nested-anon-types"

[02:35:01] make: ***
[/Volumes/cm/cm11/out/host/darwin-x86/obj/STATIC_LIBRARIES/libmincrypt_intermediates/p256_ec.o]
Error 1

[02:35:01] make: ***
[/Volumes/cm/cm11/out/host/darwin-x86/obj/STATIC_LIBRARIES/libmincrypt_intermediates/dsa_sig.o]
Error 1

[02:35:01] make: ***
[/Volumes/cm/cm11/out/host/darwin-x86/obj/EXECUTABLES/mkbootimg_intermediates/mkbootimg.o]
Error 1

这个问题困扰了我很久,网上找了很多帖子都是说要安装Apple提供的gcc,但是我都安装了Xcode了肯定自带了gcc啊,而且还有人说是只支持Xcode
4.2。google
这个识别不了的命令行选项-Wno-nested-anon-types的时候只找到了几个关于LLVM的错误修正,居然是给的补丁要重新编译LLVM,这明显不可行。

既然网上找不到方法,就只能自己解决了。分析一下,既然说这个选项不存在,那这个选项是在哪里定义的呢?肯定是在makefile里面嘛,能影响整个编译过程的的makefile有哪几个呢?第一个肯定是想到
/Volumnes/cm/cm11/build/core/combo/HOST_darwin-x86.mk
这个了,打开一看,果然,第90行是这样的:

HOST_GLOBAL_CFLAGS
+= -I$(mac_sdk_root)/usr/include/c++/4.2.1 -arch i386
-Wno-nested-anon-types -Wno-unused-parameter

果然是定义了-arch
和-Wno-nested-anon-types 这两个参数,尝试直接把它们干掉。

把上面一行复制出来,再注释掉(用作备份,如果出问题要能改回去),把那两个参数删掉,就变成了这样:

HOST_GLOBAL_CFLAGS
+= -I$(mac_sdk_root)/usr/include/c++/4.2.1 
-Wno-unused-parameter

修改过后重新编译,问题解决。

7.

[03:02:20] host C: libhost <= build/libs/host/CopyFile.c

[03:02:20] host C: mkbootfs <= system/core/cpio/mkbootfs.c

[03:02:20] host C: checkpolicy <=
external/checkpolicy/queue.c

[03:02:20] system/core/cpio/mkbootfs.c:12:20: error: stdarg.h: No
such file or directory

[03:02:20] system/core/cpio/mkbootfs.c: In function 'die':

[03:02:20] system/core/cpio/mkbootfs.c:30: warning: implicit
declaration of function 'va_start'

居然提示找不到头文件stdarg.h,这个貌似是C标准库的里面的头文件了,自己随便写了个hello
world的c,include这个stdarg.h,没报错啊,这是为何呢?看来这个编译系统在初始化环境变量的时候可能出了点问题。根据以往的经验,但凡是找不到头文件,一般都已经包含在了cm11的内核代码树的某个文件夹里面了,比如说上次的elf.h,其实也在cm11的代码树里面有。这次这个,在代码树的根目录,用du
-a | grep stdarg.h,同样可以找到,它位于:

zhufengs-iMac:cm11
zhufeng$ du -a | grep stdarg

8   
./external/clang/lib/Headers/stdarg.h

8   
./external/connectivity/stlport/stlport/cstdarg

8   
./external/connectivity/stlport/stlport/stdarg.h

8   
./external/connectivity/stlport/stlport/stl/_cstdarg.h

第一个就是,那么找到了头文件要把它放到哪里去呢?又去
/Volumnes/cm/cm11/build/core/combo/HOST_darwin-x86.mk
这里面找了找,有如下的定义:

ifeq
($(mac_sdk_version),10.9)

# HOST_GLOBAL_CFLAGS += -I$(mac_sdk_root)/usr/include/c++/4.2.1
-arch i386 -Wno-nested-anon-types -Wno-unused-parameter

HOST_GLOBAL_CFLAGS +=
-I$(mac_sdk_root)/usr/include/c++/4.2.1 
-Wno-unused-parameter

HOST_GLOBAL_LDFLAGS += -Wl,-arch,i386,-lstdc++

不错,就是刚才第6个错误的时候受影响的那一行,include目录定义的很明显了,去
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include
里面找一下,果然是没有stdarg.h这个头文件,既然这样,那把上面找到的stdarg.h弄过来就好了。直接用符号链接 ln -s
链过来,重新编译之后不再报错。

--------------------------------------------------------------------------------------------

2014.4.27

这两天开始在os x下面尝试编译内核,cm的源码包里面提供了linux和darwin也就是os
x的交叉编译工具链,版本有4.6的4.7两个。最终编译出来的zImage再做成boot.img是可以用的,串口打印的日志如下:

[23:51:39] Starting kernel ...

[23:51:39]

[23:51:39] Uncompressing Linux... done, booting the kernel.

[23:51:41] [ 0.000000] Initializing cgroup subsys cpu

[23:51:41] [ 0.000000] Linux version 3.0.15 (zhufeng@zhufengs-iMac.local)
(gcc version 4.6.x-google 20120106 (prerelease) (GCC) ) #1 SMP
PREEMPT Sat Apr 26 01:17:25 CST 2014

[23:51:41] [ 0.000000] CPU: ARMv7 Processor [413fc090] revision 0
(ARMv7), cr=10c5387d

[23:51:41] [ 0.000000] Machine: STUTTGART

[23:51:41] [ 0.000000] CPU EXYNOS4412 (id 0xe4412220)

[23:51:41] [ 0.000000] S3C24XX Clocks, Copyright 2004 Simtec
Electronics

[23:51:41] [ 0.000000] s3c_register_clksrc: clock audiocdclk has no
registers set

但是在os
x下面配置好环境变量之后,直接make -j4会出现一系列问题,现一一列举出来。

1.

[01:10:24] CC scripts/mod/empty.o

[01:10:24] HOSTCC scripts/mod/mk_elfconfig

[01:10:24] scripts/mod/mk_elfconfig.c:4:10: fatal error: 'elf.h'
file not found

[01:10:24] #include

[01:10:24] ^

[01:10:24] 1 error generated.

[01:10:24] make[2]: *** [scripts/mod/mk_elfconfig] Error 1

[01:10:24] make[1]: *** [scripts/mod] Error 2

[01:10:24] make: *** [scripts] Error 2

这个问题是由于os
x的系统include路径里面少了一个elf.h这个文件,到 http://www.rockbox.org/tracker/9006?getfile=16683
这个地方,把里面的内容保存成elf.h,放到内核源码的scripts/mod/下面即可。

2.

[01:11:49] HOSTCC scripts/mod/mk_elfconfig

[01:11:49] scripts/mod/mk_elfconfig.c:4:10: error: 'elf.h' file not
found with include; use "quotes" instead

[01:11:49] #include

[01:11:49] ^~~~~~~

[01:11:49] "elf.h"

[01:11:49] 1 error generated.

[01:11:49] make[2]: *** [scripts/mod/mk_elfconfig] Error 1

[01:11:49] make[1]: *** [scripts/mod] Error 2

[01:11:49] make[1]: *** Waiting for unfinished jobs....

这个问题是elf.h之前是因为在系统include库里面,现在放到了scripts/mod下面,编译.c文件的时候定义elf.h的时候有问题,想必会c的人都知道#include
和#include "elf.h"
的区别吧。把scripts/mod下面的mk_elfconfig.c,modpost.h这两个文件,开头前几行的#include
改成#include "elf.h"。

3.

[03:05:36] CC
drivers/media/video/samsung/ump_r3p2/common/ump_kernel_common.o

[03:05:36] arm-eabi-gcc: error: Revision:: No such file or
directory

[03:05:36] arm-eabi-gcc: error: Unversioned: No such file or
directory

[03:05:36] arm-eabi-gcc: error: directory: No such file or
directory

[03:05:36] arm-eabi-gcc: error: Revision:: No such file or
directory

[03:05:36] arm-eabi-gcc: error: Unversioned: No such file or
directory

[03:05:36] arm-eabi-gcc: error: directory": No such file or
directory

[03:05:36] make[5]: ***
[drivers/media/video/samsung/ump_r3p2/common/ump_kernel_common.o]
Error 1

[03:05:36] make[4]: *** [drivers/media/video/samsung/ump_r3p2]
Error 2

[03:05:36] make[4]: *** Waiting for unfinished jobs....

这个就是昨天出现的问题,今天终于是把它解决了。google了一下,发现可能是由于
drivers/media/video/samsung/ump_r3p2/Makefine.common 这个文件里面定义的一个变量
SVN_REV 引起的,具体的两行代码是:

#
Get subversion revision number, fall back to 0000 if no svn info is
available

SVN_REV:=$(shell ((svnversion | grep -qv exported && echo
-n 'Revision: ' && svnversion) || git svn info | sed -e
's/$$$$/M/' |   grep '^Revision:
' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e
's/^Revision: //')

后面按照网上给的方法,把SVN_REV这一行直接给注释掉,保存之后再编译还是报一样的错。来分析一下原因,把这个变量后面的这一行命令直接分别在os
x和ubuntu的终端里面执行,看输出的结果有什么不一样。发现在linux里面是没有svnversion这个程序的,所以编译过程就会直接跳过,而os
x里面自带了这个svnversion这个程序,但是命令的输出结果并不对,有可能是Linux的程序和os
x的程序的命令行参数不太一样,输出的结果就不对,然后就引起了报错。但是有可能由于其它的makefile也引用到了svnversion这个程序,所以即使注释掉了那一个makefile,其它的还不知道有多少个Makefile引用到了这个SVN_REV的变量,所以想到干脆直接把svnversion这个东西弄掉。果然,把它重命名成svnverson-bak之后,后面的编译就很顺利,没有再报什么错了。命令如下:

[01:08:23]
zhufengs-iMac:kernel zhufeng$ sudo mv /usr/bin/svnversion
/usr/bin/svnversion-bak

因为现在的黑苹果是装在台机上的,i5
2300 + 16G的内存,所以编译直接速度真的是很快啊,日志如下:

[01:13:50]
zhufengs-iMac:kernel zhufeng$ make -j4

[01:13:52] CHK include/linux/version.h

[01:13:52] CHK include/generated/utsrelease.h

......

[01:17:39] AS arch/arm/boot/compressed/piggy.gzip.o

[01:17:39] LD arch/arm/boot/compressed/vmlinux

[01:17:39] OBJCOPY arch/arm/boot/zImage

[01:17:39] Kernel: arch/arm/boot/zImage is ready

从开始编译的时间和结束的时间看,编译一个k860i的内核源代码,竟然只要四分钟不到!以前在i5
一代笔记本CPU的虚拟机上,编译这个内核至少用了十多分钟,差距实在是太大了,多核真是编译东西的利器啊!

另外,在测试内核的时候还发现了一个更为严重的问题,上次说到把自编译的内核fastboot
flash boot
boot.img之后无法进入桌面,之前几天是推测说/init.rc这个文件有问题,但后面在启动的时候偶然抓了一下adb
logcat,发现一直在重复这几行:

I/SurfaceFlinger(
1356): SurfaceFlinger is starting

I/SurfaceFlinger( 1356): SurfaceFlinger's main thread ready to run.
Initializing graphics H/W...

D/libEGL ( 1356): loaded /system/lib/egl/libEGL_mali.so

D/libEGL ( 1356): loaded /system/lib/egl/libGLESv1_CM_mali.so

D/libEGL ( 1356): loaded /system/lib/egl/libGLESv2_mali.so

E/ ( 1356): ERROR in Mali driver:

E/ ( 1356): * Device driver API mismatch

E/ ( 1356): * Device driver API version: 20

E/ ( 1356): * User space API version: 17

E/ ( 1356): mali: REVISION=Linux-r3p1-01rel1 BUILD_DATE=Tue Jul 2
15:06:24 KST 2013

W/libEGL ( 1356): eglInitialize(0x1) failed
(EGL_BAD_ALLOC)

Mali
driver就是Mali驱动,只要有点主流嵌入式SOC的硬件常识都会知道,k860i用的soc是三星的Exynos
4412,它内置的显卡就是Mali
400。这正是内核显卡驱动和用户空间的驱动版本不匹配引起的,当然驱动就不能正确加载了,很明显显卡驱动都没有加载的话,内核加载完之后是肯定进不到桌面的。之所以之前没有想到是这个原因,是因为这种类型的日志不是内核日志,不可能打印在串口的内核日志输出里面,而之前测试的时候正好又没有抓adb
logcat,所以就忽略了。我估计以后正式开始cm11的时候,这个问题肯定还会再出现,现在还没有想到什么好的解决办法,网上搜了下也没有什么好的建议,到时候再看吧。

--------------------------------------------------------------------------------------------

2014.4.25

有几天没更新进度了,其实这几天一直都在弄台式机的事情。华硕返修个主板给我返了一个多星期,起因是上次我自己不小心把CPU插座弄断了几根针,然后就杯具了。因为过保了,所以说是换插座要100块,也只能给了。不过我在去取的时候很是意外,本来是P8H67M-PRO,给我换了块P8P67M-PRO,从价格上来说是比H67要贵的,外围接口什么的也多了不少,功能应该也是会更多,但是没有了显卡输出接口,而且再加上板子也看起来是全新的,所以我也就收了,最后售后还说给我带来不便再给了三个月的保。这就得要买显卡了啊,P67不能用集显,纠结了很久,终于决定买一块索泰的GTX650,679块,这么一来整个电脑基本上全换掉了。换了主板之后,用win7自带的评分,显卡的两部分升到了7.3,7.3,现在最低的就硬盘了,5.9分,这下整一块SSD就基本上就都7.5了。好吧,这电脑又可以再战三年。。

在换了新主板之后,整了个黑苹果,其实最主要的是换了显卡的功劳,之前的i5
2300的集显hd2000在黑苹果下面驱动不起来,开不了QE/CI。基本上现在弄的黑苹果已经达到90%的完美程度了,网卡声卡显卡都驱动起来了,USB3.0接口还有点问题,AHCI和RAID的问题也解决了。本着不折腾不舒服斯基的原则,不出意外的话k860i的CM11的接下来的部分工作会在os
x上完成,就是不知道能不能进行下去。

把之前下载的CM11和内核的源码都放到os
x下面了,环境变量也都弄好了,使用cm11源码里面带的arm-eabi-gcc 4.6 for
darwin交叉编译器尝试编译内核,除去前几天出现过的smc 0的报错之外,开始出现新的错误,报错是这样的:

[03:05:36] CC
drivers/media/video/samsung/ump_r3p2/common/ump_kernel_common.o

[03:05:36] arm-eabi-gcc: error: Revision:: No such file or
directory

[03:05:36] arm-eabi-gcc: error: Unversioned: No such file or
directory

[03:05:36] arm-eabi-gcc: error: directory: No such file or
directory

[03:05:36] arm-eabi-gcc: error: Revision:: No such file or
directory

[03:05:36] arm-eabi-gcc: error: Unversioned: No such file or
directory

[03:05:36] arm-eabi-gcc: error: directory": No such file or
directory

[03:05:36] make[5]: ***
[drivers/media/video/samsung/ump_r3p2/common/ump_kernel_common.o]
Error 1

[03:05:36] make[4]: *** [drivers/media/video/samsung/ump_r3p2]
Error 2

[03:05:36] make[4]: *** Waiting for unfinished jobs....

网上搜了下这个错误可能是由于makefile和makefile.common里面的SVN_REV变量的设置问题,后面修改之后还是报一样的错,有可能是和mac里面的svn版本和linux里面版本不一样造成的。接下来的时间会继续尝试把mac平台的编译错误尽力解决掉,如果实在不行,到时候那就只能重新在台机上装一个linux了。

好吧,放一张黑苹果的截图,小得瑟一下~~

k860i 移植Android 4.4 cm11进度记录【上篇已完结】" title="Lenovo k860i 移植Android 4.4 cm11进度记录【上篇已完结】">

--------------------------------------------------------------------------------------------

2014.4.21

主板终于要返修回来了,真是操蛋,用了一个多星期,而且华硕官方的售后点、居然不代理广州和深圳之外的其它区的货,这尼玛是在闹哪样,全国联保就一句空话么?下班之后去取回来,换了个CPU插座,100块,晚上还得把台机装起来。用笔记本编译实在是太慢了,台机装好之后应该会好很多,起码编译时间会减半。

在CM的wiki看了下Android的编译方法,看起来比我想象中的要复杂的多,还需要消化一下,各种变量飞来飞去,要找到些规律才能继续下去,所以这几天估计都会在看这个了。把scue的github上的cm10.1的device的代码都拖下来了,应该会有很大的用处。

--------------------------------------------------------------------------------------------

2014.4.20

关于boot.img的内核文件不能启动的问题,google了一下,看到了这个帖子 http://blog.csdn.net/wh_19910525/article/details/8200372
。原来这个boot.img跟普通linux发行版本的内核文件有点不一样,它把zImage,ramdisk,启动参数等等这些东西都打包到一起去了。按照上面的那篇博客的方法,用mkbootimg和unpackbootimg可以实现打包和解包boot.img,于是准备尝试一下把自己编译的zImage打包成boot.img刷进去看看能不能用。

[00:59:35]
zhufeng@zhufeng-lap-vm:/home/cm/cm11/osc_opensource/kernel/arch/arm/boot/bootimg/unpack$
./unpackbootimg -i
boot.img.tj.2.9 -o out

[00:59:36] BOARD_KERNEL_CMDLINE console=ttySAC3,115200
androidboot.hardware=stuttgart

[00:59:36] BOARD_KERNEL_BASE 10000000

[00:59:36] BOARD_PAGE_SIZE 2048

[01:02:06] zhufeng@zhufeng-lap-vm:/home/cm/cm11/osc_opensource/kernel/arch/arm/boot/bootimg/unpack/out$
cat
*base *line *size

[01:02:06] 10000000

[01:02:06] console=ttySAC3,115200
androidboot.hardware=stuttgart

[01:02:06] 2048

[01:02:30] zhufeng@zhufeng-lap-vm:/home/cm/cm11/osc_opensource/kernel/arch/arm/boot/bootimg/unpack/out$
../mkbootimg
--cmdline 'console=ttySAC3,115200 androidboot.hardware=stuttgart'
--kernel boot.img.tj.2.9-zImage --ramdisk
boot.img.tj.2.9-ramdisk.gz -o boot.img

先把现在用的这个ROM的boot.img解压出来,把解出来的内核文件用我自己编译的zImage替换,ramdisk和cmdline不变,再重新生成boot.img,刷到现有的ROM包里面去,终于能启动了,而不是昨天直接刷zImage直接到uboot命令行界面。不过虽然没有再卡lenovo
logo,不过却进不到桌面,看了下串口打印的内核日志,看到了下面这几行。估计就是这个原因导致的了,/init.rc->/init.stuttgart.rc这个文件是初始化图形的配置文件,这个文件有错,自然就会出问题,这个我想只要移植过ARM开发板linux内核的人都明白,是个非常典型的错误。

[01:20:52] [
5.100215] lirx +++in tty_release, ttySAC3+++

[01:20:52] [ 5.110046] lirx +++out tty_release, ttySAC3+++

[01:20:52] [ 5.113912] init: parse config file: /init.rc

[01:20:52] [ 5.119235] init: /init.stuttgart.rc: 190: invalid
command '//'

[01:20:52] [ 5.123717] init: /init.stuttgart.rc: 191: invalid
command '//'

[01:20:52] [ 5.129590] init: /init.stuttgart.rc: 192: invalid
command '//'

[01:20:52] [ 5.135787] init (1): /proc/1/oom_adj is deprecated,
please use /proc/1/oom_score_adj instead.

后面找了群里的朋友“凌乱人生”帮忙在vibe
rom上面fastboot刷了内核做测试,终于可以进到桌面了,有图有真相,这个内核就是我自己编译的,看编译者和编译时间一眼就能看的出来。哈哈,内核暂时应该没什么问题了,不过最近一直都是在做内核测试,真正CM11的代码部分都还没开始呢,可以想象以后肯定会有越来越多各种乱七八糟的问题出来,只能慢慢来了。好吧,下午出去逛逛太古汇,连续弄了好几天了,稍微休息下,晚上回来正式开始CM11代码部分。

k860i 移植Android 4.4 cm11进度记录【上篇已完结】" title="Lenovo k860i 移植Android 4.4 cm11进度记录【上篇已完结】">

下午去电脑城经朋友介绍买了个二手硬盘,西数2.5寸
500G 5400转蓝盘,看通电时间1800小时,150块,价格还算可以了,几乎是新的半价,给笔记本装上,安装上了ubuntu
14.04
x64,现在就差把之前虚拟机里面代码移到硬盘上去。不过郁闷的是,虚拟机的vmdk文件在ubuntu里面无法挂载,真悲催,这样就只能重新解压源码了,但是操蛋的网络晚上又各种渣,
repo
sync之后各种连接被重置,哎,算了,等明天把代码拖下来再继续吧。也已经连续好几天晚上两三点才睡了,今天要早点睡了,明天还要上班。

--------------------------------------------------------------------------------------------
2014.4.19

因为台机主板还没返修回来 ,所以就只能在虚拟机里面继续编译。ubuntu 14.04
x64已经正式发布,只是那块硬盘实在已经装不上系统了,各种IO读取错误,无奈只能继续等台机主板返修回来再说了。

不过今天还是有不少的进展。下午去买了两副耳机,为了做耳机调试线,花了我二十大洋,听了之后发现这音质也就只值三四块钱。好在之前在学校的时候拿了几根杜邦线和一个USB转TTL的小板子,还没想到居然还真派上用场了。立马剪掉耳机和杜邦线,打火机烧一下,接起来,耳机那边有四根线,只需要GND和RXD,最后还是给试出来了,耳机调试线就OK了。这下这手机就跟开发一样了啊,直接打印输出串口的内核日志,看了下,内核日志确实对内核的调试是有极大的帮助的,开机直接就是启动到uboot界面,不过因为没有接TXD到TTL上面,所以在uboot界面无法按任意键停止自动加载FLASH上面的内核。

借助于耳机调试线,终于是发现为什么上次用fastboot
boot zImage刷进去的内核不能用了,这自己编译的内核是能启动的,下面放几条打印的内核日志:

[20:21:06] Starting kernel ...

[20:21:06]

[20:21:07] Uncompressing Linux... done, booting the kernel.

[20:21:08] [ 0.000000] Initializing cgroup subsys cpu

[20:21:08] [ 0.000000] Linux version 3.0.15 (zhufeng@zhufeng-lap-vm)
(gcc version 4.6.x-google 20120106 (prerelease) (GCC) ) #3 SMP
PREEMPT Fri Apr 18 12:00:44 CST 2014

[20:21:08] [ 0.000000] CPU: ARMv7 Processor [413fc090] revision 0
(ARMv7), cr=10c5387d

[20:21:08] [ 0.000000] CPU: VIPT nonaliasing data cache, VIPT
aliasing instruction cache

[20:21:08] [ 0.000000] Machine: STUTTGART

[20:21:08] [ 0.000000] ####get g_lcd_nova=1#####

[20:21:08] [ 0.000000] Memory policy: ECC disabled, Data cache
writealloc

[20:21:08] [ 0.000000] CPU EXYNOS4412 (id 0xe4412220)

[20:21:08] [ 0.000000] S3C24XX Clocks, Copyright 2004 Simtec
Electronics

[20:21:12] [ 4.985941] VFS: Cannot open root device "(null)" or
unknown-block(0,0)

[20:21:12] [ 4.992053] Please append a correct "root=" boot option;
here are the available partitions:

[20:21:12] [ 5.072773] b310 2048 mmcblk0boot1 (driver?)

[20:21:12] [ 5.078062] b308 2048 mmcblk0boot0 (driver?)

[20:21:12] [ 5.083352] b318 31166976 mmcblk1 driver: mmcblk

[20:21:12] [ 5.088643] b319 31162880 mmcblk1p1
00000000-0000-0000-0000-000000000000

[20:21:12] [ 5.096118] Kernel panic - not syncing: VFS: Unable to
mount root fs on unknown-block(0,0)

这也是个典型问题了,以前在玩2410、6410弄Linux内核移植的时候经常遇到这样,特别是在挂NFS
ROOT,找不到根目录。后面试了用ROM原配的boot.img也是一样,这样可能就得猜想一下fastboot
boot直接下载内核的机制到底是怎么样的了,这个就暂不深究了。

不过在测试中还发现了另外一个值得庆幸的事情,那就是k860i可以直接用fastboot来刷内核,其实好像很多手机都是可以支持的?不过确实说起来联想把这个bootloader还算是做的很好的了,电源+音量加进入bootloader模式,里面有很多个选项,可以切换耳机孔作为音频输出还是串口console,还可以选择进入recovery,或者进入usb下载(也就是fastboot模式),SD下载(也就是联想官方用的szb刷机方式)。进入usb下载模式,直接就可以用fastboot刷机了。尝试把zImage刷到boot里面去:fastboot
flash boot
zImage,再重启手机,可以看到,会报错不能引导,会直接进入到uboot的命令行,会报错。后面再刷入之前用的boot.img,就又可以正常启动了。

[20:41:55] downloading of 3749708 bytes finished

[20:41:55] Received 10 bytes: flash:boot

[20:41:55] flashing 'boot'

[20:41:55]

[20:41:57] MMC write: dev # 0, block # 6660159, count 40897 ...
40897 blocks written: OK

[20:41:57] partition 'boot' flashed

[20:42:11] Received 6 bytes: reboot

[20:42:11] resetting ...

[20:42:11] reset...

[20:42:13] s5p_dsim_set_main_disp_resol:vert_resol:1280,
hori_resol:720

[20:42:13] Hit any key to stop autoboot: 0

[20:42:13] Wrong Image Format for bootm command

[20:42:13] ERROR: can't get kernel image!

[20:43:04] STUTTGART #

看来boot.img是把zImage加了一些文件头等信息,不过也是可以理解的,毕竟boot.img是在系统的源码目录用make
bootimage生成的,而这个内核只是在内核目录生成的zImage。明天准备尝试一下把这个zImage内核文件加文件头,看能不能直接引导现用的ROM。

好吧,今天的更新日志就这些了,耳机调试线确实是个非常给力的工具,估计也能增加那么一点点移植成功的机率吧。

--------------------------------------------------------------------------------------------

2014.4.18

从昨天晚上开始编译一下官方给的内核源码,仅仅只是做下测试看能不能编译通过。不过由于虚拟机里面的ubuntu是10.04
32位的,不能编译4.0以上的系统,所以必须重新在虚拟机里面搭一个64位的环境。本来是想直接用最新的14.04
x64,结果在vmware有各种问题,网上说是最新版的vmware不支持14.04的linux 3.13内核。后面换到12.04.4
x64,图形又用不了。真是各种操蛋,最终只能用字符界面了,好在编译这些东西不需要图形操作,还用了SecureCRT的自动记录功能,把终端所有输出的命令的时间都加上了,这样就很好了,记录所有操作,为以后记这篇日志有点根据。

好在最后还是把环境搭起来了,虚拟机里面迁移起来就比较方便了,之前拖cm的源码的时候,我是在/home下面另外新建了一块vmware虚拟硬盘vmdk挂到/home/cm的,所以我重装系统完全不会影响到源码,把几个重要的系统配置文件备份到cm的vmdk里面,比如/etc/bash.bashrc,
/etc/fstab/, /etc/profile, ~/.vim,
~/.vimrc等等,重新完成之后把这些文件再覆盖回去重启系统即可,之前设置的环境变量,各种使用习惯全部都回来了。

然后是安装编译系统和内核所必备的一些包:

sudo apt-get install bison build-essential curl flex git-core gnupg
gperf libesd0-dev libncurses5-dev libsdl1.2-dev libwxgtk2.8-dev
libxml2 libxml2-utils lzop openjdk-6-jdk openjdk-6-jre pngcrush
schedtool squashfs-tools xsltproc zip zlib1g-dev g++-multilib
gcc-multilib lib32ncurses5-dev lib32readline-gplv2-dev lib32z1-dev
p7zip-full vim-gtk openjdk-6-jdk openjdk-6-jre

最后两个jdk和jre,最好不要安装openjdk的,看编译的时候会报一些错,安装sun
jdk比较好。

说一下我的目录环境情况,/home/cm/cm11这个是所有cm源码的根目录,下面有osc_opensource这个目录是联想4月放出来的源码的目录,现在还是一个独立的目录,还没有放到cm源码的内核目录里面去。开始测试编译内核之前要配置好交叉编译器的toolchain的环境变量,当然所有的前提都是要把cm11.0的所有源码都拖下来,repo
sync完全显示done才可以进行,此时/home/cm/cm11应该有abi bionic cts development docs
hardware Makefile out prebuilt system android bootable dalvik
device
等等目录,这里面同时也已经包含了交叉编译器的toolchain了。具体配置是编辑/etc/bash.bashrc,在文件最后添加如下几行保存之后,source一下/etc/bash.bashrc就可以了。

# set jdk environment

export JAVA_HOME=/usr/local/src/jdk1.6.0_24/

export PATH=$JAVA_HOME/bin:$PATH

export
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

# set PATH for adb and android sdk folder

export
PATH=/home/cm/:/home/cm/android-sdk-linux/tools/:/home/cm/android-sdk-linux/platform-tools/:$PATH

# set PATH for arm-linux-gcc eabi 4.6

export CM11=/home/cm/cm11

export
PATH=$CM11/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH

export
ARCH=arm

export SUBARCH=arm

export CROSS_COMPILE=arm-eabi-

环境都搭好之后就可以cd到osc_opensource的kernel目录,开始:

make stuttgart_android_defconfig 
//用来生成.config文件

make -j4

好吧,报错了。

  CC arch/arm/mach-exynos/cpu-exynos4.o

  CC arch/arm/mach-exynos/pm-exynos4.o

/tmp/cctXCN1T.s: Assembler messages:

/tmp/cctXCN1T.s:69: Error: selected processor does not support ARM
mode `smc 0'

/tmp/cctXCN1T.s:97: Error: selected processor does not support ARM
mode `smc 0'

/tmp/cctXCN1T.s:119: Error: selected processor does not support ARM
mode `smc 0'

/tmp/cctXCN1T.s:141: Error: selected processor does not support ARM
mode `smc 0'

/tmp/cctXCN1T.s:188: Error: selected processor does not support ARM
mode `smc 0'

make[1]: *** [arch/arm/mach-exynos/cpu-exynos4.o] 错误 1

make[1]: *** 正在等待未完成的任务....

/tmp/ccMpIkta.s: Assembler messages:

/tmp/ccMpIkta.s:112: Error: selected processor does not support ARM
mode `smc 0'

/tmp/ccMpIkta.s:303: Error: selected processor does not support ARM
mode `smc 0'

/tmp/ccMpIkta.s:394: Error: selected processor does not support ARM
mode `smc 0'

/tmp/ccMpIkta.s:422: Error: selected processor does not support ARM
mode `smc 0'

/tmp/ccMpIkta.s:444: Error: selected processor does not support ARM
mode `smc 0'

/tmp/ccMpIkta.s:466: Error: selected processor does not support ARM
mode `smc 0'

/tmp/ccMpIkta.s:789: Error: selected processor does not support ARM
mode `smc 0'

make[1]: *** [arch/arm/mach-exynos/pm-exynos4.o] 错误 1

make: *** [arch/arm/mach-exynos] 错误 2

make: *** 正在等待未完成的任务....

make: *** wait: 没有子进程。 停止。

反反复复都是报的同一个错,网上搜了下,说是三星Exynos的CPU的一个smc的支持问题,幸运的是,在
https://gist.github.com/anonymous/4395518
这个github里面,有个大神已经提交了一个修复这个错误的补丁,源代码都在,不过这个是patch.txt,好吧不会用patch功能的我只能纯手工自己添加了(请不要吐槽我不会用patch。。。。)。虽然不会用patch,不过好在这是纯文件,咱看下也能明白这个patch到底是怎么打的,怎么分析patch文件怎么用我就不说了,自己可以看源码,想想便知,现在说的是怎么手动修改。

arch/arm/mach-exynos/include/mach/smc.h
这个文件,

在第53行下面和第69行下面都加入这行代码:

".arch_extension sec\n"

arch/arm/mach-exynos/sleep-exynos4.S
这个文件,

在第41行下面加入下面这三行代码:

#ifdef CONFIG_ARM_TRUSTZONE

 .arch_extension sec

#endif

arch/arm/mach-exynos/idle-exynos4.S

这个文件 ,

在第47行下面加入下面这三行代码:

#ifdef CONFIG_ARM_TRUSTZONE

 .arch_extension sec

#endif

大概就是改这三个源文件,改好之后继续
make -j4,大概十几分钟左右,应该没有其它错误了,显示如下的信息就表示内核 zImage已经编译完成了。

  MODPOST 4 modules

  GZIP arch/arm/boot/compressed/piggy

  SHIPPED arch/arm/boot/compressed/lib1f

  AS arch/arm/boot/compressed/lib1f

  LD [M] crypto/ansi_cprng.ko

  LD [M] drivers/media/video/gspca/gspc

  AS arch/arm/boot/compressed/piggy

  LD arch/arm/boot/compressed/vmlin

  OBJCOPY arch/arm/boot/zImage

  Kernel: arch/arm/boot/zImage is ready

编译好之后当然就想试一下能不能用。因为暂时还不准备刷机,要备份的东西太多,所以我就想着看能不能直接用fastboot
boot zImage这种方式来测试下内核,发现然后就直接卡死在开机lenovo
logo了。之前以为可能是内核的问题,后面直接用现在用的这个刷机包的boot.img,用同样的fastboot boot
boot.img来启动,发现也不行,同样是卡死在lenovo logo。

调内核没有串口几乎无法进行啊,看到之前有个帖子
http://bbs.lephone.cc/forum.php?mod=viewthread&action=printable&tid=547161
,准备去弄个这个线,USB转TTL的板子我自己有一个,要想办法做一个这个线,就可以跟开发板一样直接看串口输出的信息了,弄好了的话调内核就真是方便太多了。

另外,发到上海去修的主板,还没回来,估计这周都回不来了,真是操蛋。每次在笔记本的虚拟机ubuntu上编译东西,这笔记本风扇都是在嚎叫。。。。好惨的样子。。。。。

好吧,昨晚弄这个东西搞到三点钟才睡觉。。。。。

http://www.xuebuyuan.com/1011648.html

http://iwillbemyself.blog.163.com/blog/static/170223228201222831425225/

--------------------------------------------------------------------------------------------

2014.4.17

昨天晚上给笔记本分了个LVM,以避免坏道对数据可能造成的影响。把LV做了镜像,同步时间真是漫长,干脆让它自己跑了一整晚,今早看到应该已经是完成了,lvs命令查看lv状态,copy%两个LV一个是99.99%一个是99.97%,不知道这样正不正常?按说应该要是100%完成才行的。linux的LVM好像没有aix里面LV那种查看有多少个stale的PP的命令。

在笔记本的虚拟机上面把cm11.0的所有源码和联想4月放的源码都解出来了,准备先试一下编译官方的kernel,看能不能通过。看来SOC都是ARM构架,跟以前编译2410、6410的linux内核完全没有任何区别嘛。

在kernel目录里面执行:

make stuttgart_android_defconfig 
//用来生成.config文件

make -j4

就可以开始编译。

不过需要说明的是,这只是在测试一下这个内核的源码编译起来有没有问题,完完全全是测试用的,即使能编译出来也是不能刷的。

编译过程中报错了,应该是虚拟机里面搭的环境有问题,看网上说是4.0以上系统编译都必须要linux
x64才行。在虚拟机里面弄个14.04
x64,结果。。。。现在的vmware还不支持14.04使用的3.13的内核,结果就是各种问题,桌面打不开,运行各种慢,halt命令关机CPU会被强制禁用。。。只能再去拖个10.04.4
x64再扔到虚拟机安装。不过很奇怪,交叉编译器toolchain不是明明写的linux-x86么。。。为何一定要64位linux呢?

zhufeng@zhufeng-lap-vm:/home/cm/cm11/osc_opensource/kernel$
make
-j5

/home/cm/cm11/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc:
1: Syntax error: "(" unexpected

scripts/kconfig/conf --silentoldconfig Kconfig

/home/cm/cm11/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc:
1: Syntax error: "(" unexpected

  CHK include/linux/version.h

  CHK include/generated/utsrelease.h

  CC scripts/mod/empty.o

/home/cm/cm11/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-gcc:
1: Syntax error: "(" unexpected

make[2]: *** [scripts/mod/empty.o] 错误 2

make[1]: *** [scripts/mod] 错误 2

make: *** [scripts] 错误 2

make: *** 正在等待未完成的任务....

--------------------------------------------------------------------------------------------

2014.4.16晚

cm11.0的最新代码已经全部同步完了,大概有11g,看了下打好的tar包,repo
sync之后打的tar包比原来从网盘下载的tar包大了500多M。

zhufeng@zhufeng-lap-vm:/media/cm-k860i/.repo$
du
-sc

10786272   
.

10786272   
总用量

用acer
3750g挂那个有坏道的移动硬盘拆出来的2.5的TOSHIBA 500G盘,测试用ubuntu 14.04
beta2做了一个LVM,48G两个分区做镜像分给/,180G两个分区做镜像分给/home,系统还没开始安装,必须要等做的镜像同步完成之后才能安装系统,这个同步的过程是比较漫长的,几乎是相当于要往硬盘里面写48+180G的数据,镜像同步明天继续,目测主板还没那么快回来。Linux的LVM还是跟AIX的有不少区别啊,明显的aix下面的LVM相关的命令要比Linux里面的LVM相关命令要好用很多。

--------------------------------------------------------------------------------------------

2014.4.16

项目准备开始,前期准备工作开始进行。因台式机主板返修还没回来,所以得等到台式机主板到了才能开始搭环境,并安装使用最新的ubuntu
14.04 LTS正式版进行。

同时由于硬盘不够,到时候只能用有坏道的500G移动硬盘里面拆出来的2.5硬盘接到台式机上装ubuntu,为了保证数据安全,会做LVM,并做镜像,希望不要因此造成数据丢失。

今天准备开始同步cm11的最新源码。上次下载了深度论坛的13年11月的CM11.tar,一共有11G,今天准备解压它在虚拟机里面repo
sync同步到最新的11.0代码。

【PS,对于k860i移植Android
4.4 kitkat Cyanogenmod
11不要抱太大希望,很有可能最终做不出来或者即便做出来了也有不少bug,而且这也是我第一次做Android的移植,so,都懂的。】

Lenovo k860i 移植Android 4.4 cm11进度记录【上篇已完结】的更多相关文章

  1. Lenovo k860i 移植Android 4.4 cm11进度记录【下篇--实时更新中】

    2014.8.24 k860i的cm11的移植在中断了近两三个月之后又開始继续了,进度记录的日志上一篇已经没什么写的了,就完结掉它吧,又一次开一篇日志做下篇好了.近期的战况是,在scue同学的努力之下 ...

  2. Lenovo k860i 移植Android 4.4 cm11进度记录【下篇--实时更新中】

    2014.8.24 k860i的cm11的移植在中断了近两三个月之后又开始继续了,进度记录的日志上一篇已经没什么写的了,就完结掉它吧,重新开一篇日志做下篇好了.最近的战况是,在scue同学的努力之下, ...

  3. Cocos2dx-3.0版本 从开发环境搭建(Win32)到项目移植Android平台过程详解

    作为重量级的跨平台开发的游戏引擎,Cocos2d-x在现今的手游开发领域占有重要地位.那么问题来了,作为Cocos2dx的学习者,它的可移植特性我们就需要掌握,要不然总觉得少一门技能.然而这个时候各种 ...

  4. 关于文章“cocos2dx移植android平台-我的血泪史”需要注意事项

    关于文章"cocos2dx移植android平台-我的血泪史"需要注意事项 在上次转载的这篇文章中,按照配置一步一步的下去.发现工程中在Android.mk中有一处错误.直接bui ...

  5. cocos2dx使用了第三方库照样移植android平台-解决iconv库的移植问题

    当我写这篇文章的时候我是怀着激动的心情的,因为我又解决了一个技术问题.你可能对题目还一知半解,这是什么意思,我之所以要写这篇文章就是要解决当我们在cocos2dx中使用了第三方库的时候,移植到andr ...

  6. Android学习笔记- ProgressBar(进度条)

    本节引言: 本节给大家带来的是Android基本UI控件中的ProgressBar(进度条),ProgressBar的应用场景很多,比如 用户登录时,后台在发请求,以及等待服务器返回信息,这个时候会用 ...

  7. Android 使用ProgressBar实现进度条

    ProgressBar简介ProgressBar是进度条组件,通常用于向用户展示某个耗时操作完成的进度,而不让用户感觉是程序失去了响应,从而更好地提升用户界面的友好型. 课程目标(1)制定Progre ...

  8. Cocos2d-x移植Android 常见问题处理办法

    1.函数.变量出现"could not be resolved "问题 出现此问题通常是没有找到cocos2d-x声明的头文件.在eclipse将cocos2d的头文件文件夹引入. ...

  9. android 对话框中的进度条 (ProgressDialog)

    from:http://byandby.iteye.com/blog/817214 显然要定义对话框进度条就要用ProgressDialog,首先我们需要创建ProgressDialog对象,当然这里 ...

随机推荐

  1. 关于Java集合的小抄--转

    原文地址:http://calvin1978.blogcn.com/articles/collection.html 在尽可能短的篇幅里,将所有集合与并发集合的特征.实现方式.性能捋一遍.适合所有&q ...

  2. ZBrush笔刷属性栏简介

    在笔刷的属性栏当中,最先要了解和掌握的就是Zadd和Zsub两个按钮,当激活Zadd按钮时,我们雕刻的形态向屏幕外突出:当激活Zsub时,我们雕刻的形体就会向屏幕内凹陷.如果在激活Zadd按钮时,雕刻 ...

  3. (GDOI2018模拟九)【UOJ#192】【UR#14】最强跳蚤

    (开头先Orz myh) 原题目: 在人类和跳蚤的战争初期,人们凭借着地理优势占据了上风——即使是最强壮的跳蚤,也无法一下越过那一堵坚固的城墙. 在经历了惨痛的牺牲后,跳蚤国王意识到再这样下去,跳蚤国 ...

  4. HDU-1024 Max Sum Plus Plus 动态规划 滚动数组和转移优化

    题目链接:https://cn.vjudge.net/problem/HDU-1024 题意 给n, m和一个序列,找m个不重叠子串,使这几个子串内元素和的和最大. n<=1e6 例:1 3 1 ...

  5. luogu P2664 树上游戏(点分治)

    点分治真是一个好东西.可惜我不会 这种要求所有路经的题很可能是点分治. 然后我就不会了.. 既然要用点分治,就想,点分治有哪些优点?它可以\(O(nlogn)\)遍历分治树的所有子树. 那么现在的问题 ...

  6. [ZJOI2007]捉迷藏 (点分树+堆*3)

    点分树一点都不会啊(还是太菜了) 点分树就是我们点分治构成的新树.满足深度很小. 然后我们就可以在上面瞎维护东西了. 三个大根堆: \(C[u]\)里装的是点分树中u的子树所有点到点分树中u的父亲的距 ...

  7. suse 11 sp4 bond 网卡 mode0模式

    开启网卡: ifocnfig eth1 up 点亮网卡ethtool eth1 db2:~ # cat /etc/sysconfig/network/ifcfg-bond0 DEVICE='bond0 ...

  8. Java中四种复制数组的方法

    JAVA语言的下面几种数组复制方法中,哪个效率最高? B.效率:System.arraycopy > clone > Arrays.copyOf > for循环 1.System.a ...

  9. Java里的各种队列

    以下翻译来自java8的官方文档: 1.LinkedBlockingQueue:基于链接节点的可选限定的blocking queue . 这个队列排列元素FIFO(先进先出). 队列的头部是队列中最长 ...

  10. Codeforces Round #256 (Div. 2) B. Suffix Structures(模拟)

    题目链接:http://codeforces.com/contest/448/problem/B --------------------------------------------------- ...