星期一, 十二月 30, 2013

星期四, 十二月 26, 2013

icu 52.1 for android window 下交叉编译 mingw-64/msys

00.下载android ndk http://developer.android.com/tools/sdk/ndk/index.html
01.下载安装MSys http://www.mingw.org/wiki/MSYS 1.01
02.下载gcc 3.8.1 w64版本,比官方版本修复了一些c++11bug,http://mingw-w64.sourceforge.net/
03.下载icu 代码52.1版本 http://site.icu-project.org/download/52#TOC-ICU4C-Download
04.展开icu代码到d:\icu
05.进入msys 环境
,使用export PATH将msys 1.0 bin目录和mingw bin目录加入到PATH里.
06.cd /d/icu;mkdir mingw;mkdir android;cd mingw
   这里主要是按照icu 目录下的README.html里的cross compile的步骤.
07. ../source/runConfigureICU MinGW ;#生成配置文件  然后执行make 开始编译
这里将自动在当前mingw目录下的bing子目录里生成后面需要的一些icu打包工具
  并生成mingw 下的icu相应的库,见本文后面详细的库名解释.所有的库在lib子目录里
在msys+mingw的编译是很顺利的,没有任何错误,麻烦就在于交叉编译。

08.cd ../android 准备使用交叉编译生成android下使用的库.
09. 准备生成编译icu的android ndk 独立工具链包执行
  比如:
  /d/android-ndk-r9b/build/tools/make-standalone-toolchain.sh --platform=android-9 --install-dir=/c/temp/my-toolchain -- toolchain=arm-linux-androideabi-4.8
如果是window 7/8 64 bit 需要加上 --system=windowx86_64
然后将export PATH将msys 1.0 bin目录和/c/temp/my-toolchain/bin及ndk 独立工具链目录下的arm-linux-androideabi/bin/
目录都放入到PATH变量中,在arm-linux-androideabi/bin/目录下有需要建库的ar.exe工具,所以必须加入到PATH变量里。
   export PATH=/d/msys/1.0/bin/:/d/androidgcc/bin/:/d/androidgcc/arm-linux-androideabi/bin/
用的是gcc 4.8.1 reversion 5版本。
10. ../source/configure --host=arm-linux-androideabi --target=arm-linux-androideabi --build=i686-pc-mingw32 --with-cross-build=/d/icu/mingw -enable-shared --disable-static

以下语法顺利生成静态链接库!!!()
$ sh ../source/configure --host=armv6-google-linux --enable-static --disable-shared -with-cross-build=/d/icu/mingw CC=a
rm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ AR=arm-linux-androideabi-ar
make 

再尝试只生成动态库,在data 目录下make出现许多问题,这个data模式只在尝试将data打包成动态库的方式的出现问题,
所以尝试用其他选项避开该问题。
$ sh ../source/configure --host=armv6-google-linux --enable-shared=yes --disable-static -with-cross-build=/d/icu/mingw CC=a
rm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ AR=arm-linux-androideabi-ar --with-data-packaging=archive

make
经过阅读 http://userguide.icu-project.org/icudata 可以看到这个data库并不是必须的,不影响常规的功能使用,如果是用
archive的方式,可以让数据和应用分类,更新该.dat数据文档,不需要重新编译icu的程序. 这样使用 --with-data-packaging=archive
最后生成的动态库如图,而字典.dat文件在/d/icu/android/data/out/icudt52l.dat ,可以将该文件和ICU程序一起发布
该文件比较巨大,可以在网站下下载定制的字典数据文件:http://apps.icu-project.org/datacustom/

可能的错误:
   注意,如果这里出现错误说不支持arm-linux-androideabi,需要下载补丁覆盖修改
     source目录config.sub和config.guess,然后再次执行该命令
需要下载支持android版本 config.sub
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD

以及config.guess source目录下
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
11.make开始编译,这里52.1版本编译data目录下的时候出现一些错误.
错误一:../../source/common/putil.cpp:133:22: fatal error: langinfo.h: No such file or directory
#include <langinfo.h>
从http://ftp.cc.uoc.gr/mirrors/OpenBSD/src/include/ 下载langinfo.h和nl_types.h 到/d/ic/source/common目录下,
再重新make clean;make.

错误二:
android/common: make 
rm -f ../lib/libicuuc.so.52 && ln -s libicuuc.so.52.1 ../lib/libicuuc.so.52
ln: creating symbolic link `../lib/libicuuc.so.52' to `libicuuc.so.52.1': No such file or directory
通过使用make -d 查询到规则是.o规则,最后在
D:\icu\source\config\mh-linux 中修改对应%.o的规则加上目录../lib修复该错误。
%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
     $(RM) $@ && ln -s ../lib/${<F} $@
%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
     $(RM) $@ && ln -s ../lib/${*F}.$(SO).$(SO_TARGET_VERSION) $@

回到/d/icu/android 继续make 还会出现其他错误,但都可以通过提示反复修改mk-linx并继续make通过错误,
这是由于相对路径的错误造成的,具体原因可能是sed获取路径模式出现问题。

错误三:
android/data:
pkgdata: bash -c "arm-linux-androideabi-gcc -D_REENTRANT  -DU_HAVE_ELF_H=1 -DU_HAVE_ATOMIC=1  -DU_ATTRIBUTE_DEPRECATED=
-O2 -std=c99 -Wall -pedantic -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings   -c -I../../source/common -I
../common -DPIC -fPIC -o ./out/tmp/icudt52l_dat.o ./out/tmp/icudt52l_dat.s"
pkgdata: bash -c "arm-linux-androideabi-gcc -O2 -std=../lib/libicudata.lib -nodefaultlibs -nostdlib -o ../lib/icudata.so
.52 ./out/tmp/icudt52l_dat.o -Wl,-soname -Wl,icudata.so.52  -Wl,-Bsymbolic"
arm-linux-androideabi-gcc.exe: error: unrecognized command line option '-std=../lib/libicudata.lib'
-- return status = 1
Error generating library file. Failed command: arm-linux-androideabi-gcc -O2 -std=../lib/libicudata.lib -nodefaultlibs -
nostdlib -o ../lib/icudata.so.52 ./out/tmp/icudt52l_dat.o -Wl,-soname -Wl,icudata.so.52  -Wl,-Bsymbolic
Error generating assembly code for data.
很明显是 -std 后面的选项出现了错误
cd android\data ;make -d 查看是那个规则出现的错误
发现是D:\icu\source\tools\pkgdata\pkgdata.cpp  method pkg_checkFlag,代码逻辑错误:
1858行代码,将部分数据丢,Mingw 下不需要如此处理:
     #if U_PLATFORM == U_PF_CYGWIN
         uprv_memset(flag + position, 0, length - position);
     #endif

修正该错误后,依然不能通过,依然是无法发现:../lib/libicudata.lib

10.
首先要看README.html 

How To Cross Compile ICU 里有如何骄交叉编译的步骤

Here are some useful links regarding ICU and internationalization in general.
ICU, ICU4C & ICU4J Homepagehttp://icu-project.org/
FAQ - Frequently Asked Questions about ICUhttp://userguide.icu-project.org/icufaq
ICU User's Guidehttp://userguide.icu-project.org/
How To Use ICUhttp://userguide.icu-project.org/howtouseicu
Download ICU Releaseshttp://site.icu-project.org/download
ICU4C API Documentation Onlinehttp://icu-project.org/apiref/icu4c/
Online ICU Demoshttp://demo.icu-project.org/icu-bin/icudemos
Contacts and Bug Reports/Feature Requestshttp://site.icu-project.org/contacts

Library NameWindows FilenameLinux FilenameComment
Data LibraryicudtXYl.dlllibicudata.so.XY.ZData required by the Common and I18n libraries. There are many ways to package and customize this data, but by default this is all you need.
Common LibraryicuucXY.dlllibicuuc.so.XY.ZBase library required by all other ICU libraries.
Internationalization (i18n) LibraryicuinXY.dlllibicui18n.so.XY.ZA library that contains many locale based internationalization (i18n) functions.
Layout EngineiculeXY.dlllibicule.so.XY.ZAn optional engine for doing font layout.
Layout Extensions EngineiculxXY.dlllibiculx.so.XY.ZAn optional engine for doing font layout that uses parts of ICU.
ICU I/O (Unicode stdio) LibraryicuioXY.dlllibicuio.so.XY.ZAn optional library that provides a stdio like API with Unicode support.
Tool Utility LibraryicutuXY.dlllibicutu.so.XY.ZAn internal library that contains internal APIs that are only used by ICU's tools. If you do not use ICU's tools, you do not need this library.


参看README.html里有关cross complile的步骤:

Three initially-empty directories will be used in this example:
/icua copy of the ICU source
/buildAan empty directory, it will contain ICU built for A
(MacOSX in this case)
/buildBan empty directory, it will contain ICU built for B
(HaikuOS in this case)
  1. Check out or unpack the ICU source code into the /icu directory.You will have the directories /icu/source, etc.
  2. Build ICU in /buildA normally (using runConfigureICU or configure):
    cd /d/icu/mingw
    sh /d/icu/source/runConfigureICU MinGW
    gnumake
    
  3. Set PATH or other variables as needed, such as CPPFLAGS.
  4. Build ICU in /buildB
    Note: "--with-cross-build" takes an absolute path.
    cd /d/icu/android
    sh /d/icu/source/configure  --host=arm-linux-androideabi --with-cross-build=/d/icu/mingw
    gnumake
    
  5. Tests and testdata can be built with cd test;make

星期五, 十二月 20, 2013

android NDK 编译常用c开源库curl和sqlite

编译curl

1.安装msys 1.0
2.制作android独立编译工具链,这里是最新的android ndk r9b
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-9 --toolchina=arm-linux-androideabi-4.8 --install-dir=/d/androidgcc
这里是安装到d:\androidgcc目录下

3.下载最新curl源代码http://curl.haxx.se/download.htm

4. 进入msys 环境
5.修改PATH环境变量
   export PATH=/d/androidgcc/bin
6.进入curl源代码目录比如C:\curl-7.33.0\
     cd /c/curl-7.33.0
7.运行配置命令,告知是跨平台编译通过--host
    ./configure --host=arm-linux-androideabi   如果一切正确,最后生成标准的配置文件
8.make 开始编译,最后生成的静态库及动态库 curl-7.33.0\lib\.libs 目录下.a为静态库,.so为动态库

如果要使用静态库编译独立的可执行文件,需要在编译包含curl 函数调用的源文件加上-DCURL_STATICLIB
window下需要加入 并在最后添加如下系统库:
  d:\curl-7.33.0\libcurl.a -lws2_32 -lwldap32

Android 需要在连接生成可执行文件的时候加上 -lz
否则出现:undefined reference to 'inflateEnd'  的错误。


编译sqlite 381

同理,安装msys 1.0 和制作android 独立编译工具链同上。
1.安装msys 1.0
2.制作android独立编译工具链,这里是最新的android ndk r9b
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-9 --toolchina=arm-linux-androideabi-4.8 --install-dir=/d/androidgcc
这里是安装到d:\androidgcc目录下
3.下载最新sqlite 源代码:http://www.sqlite.org/download.html  Source Code 部分下载对应最新代码
  我使用的是3.8.1
  4.进入sqlite 源代码目录 cd /d/temp
  5.运行编译命令
     arm-linux-androideabi-gcc  sqlite3.c -fpic -shared -o libsqlite381.so
     得到动态库,如果想要静态库,请 加上-static 编译选项
6.测试是否成功代码,读取sqlite 版本号
   #include <stdio.h>
#include "sqlite3.h"
main()
{
printf("version is %s\n",sqlite3_libversion());
printf("sqlite3_sourceid is %s\n",sqlite3_sourceid());
}
然后编译成android 下执行文件:
arm-linux-androideabi-gcc getv.c   -o getv.android.exe    libsqlite381.so
准备传送到手机上测试:

D:\temp>adb push libsqlite381.so /sdcard/temp
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
2808 KB/s (853708 bytes in 0.296s)

D:\temp>adb push getv.android.exe /sdcard/temp
6 KB/s (6204 bytes in 1.000s)

D:\temp>adb shell
shell@maguro:/ $ su
su
root@maguro:/ # cd /system/tmp
cd /system/tmp
root@maguro:/system/tmp # cp /sdcard/temp/libsqlite381.so .
cp /sdcard/temp/libsqlite381.so .

root@maguro:/system/tmp # cp /sdcard/temp/getv.*.exe .
cp /sdcard/temp/getv.*.exe .
root@maguro:/system/tmp # chmod 755 getv.android.exe
chmod 755 getv.android.exe
root@maguro:/system/tmp # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/system/tmp
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/system/tmp
root@maguro:/system/tmp # ./getv.android.exe
./getv.android.exe
version is 3.8.1
sqlite3_sourceid is 2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a
240|root@maguro:/system/tmp # 
all is work!perfect
     

星期四, 十二月 19, 2013

改变javac的错误提示信息的语言。Change Javac Error Message Language

使用-J传递进去系统变量设置。
javac -J-Duser.language=en
chang error message to english.
改变错误信息为英语提示了。


星期三, 十二月 18, 2013

About c++ Excpetion处理

C++只所以被很多人鄙视,认为难学很大一部分是由于历史进化造成的。
C++作为super c,很多设计受到设计师的思维和编码习惯约束,典型的技术债
(technical debt).
和java那浑然天成的Exception 处理,c++的一场处理就是一个充满了设计师
个人经验思维局限和实验的大杂烩。
 很难想象,如果尝试用c++ ifstream open 一个不存在的文件错误,竟然没有
扔出异常,而是丑陋和另类的 good,bad fail,eof.
怎么不来一个stupid方法呢?
而且竟然没有完整的错误信息文字,只是丑陋的state.

如何偿还技术债,是c++重生的前提,我在c++11里,还没有看到整体的一种
规划和设计。


星期二, 十二月 17, 2013

string.find 和pcre regular match 那个快?

通过对比12万条的记录,查找同时包含2个子字符串的字符串行,
使用pcre需要7328 milliseconds
而调用2次 .find 时间是:2891 milliseconds

如果不是regular expression 写的不够聪明,就是regular 在简单查询上的确慢。

当然扩展性是regular 好了,只要将regular pattern string 传递函数即可。
字符串find 则需要编写非常复杂的代码表达简单的逻辑判断。

效率也基本是2~3倍的差距。几千行的数据比较,基本都在1秒内完成。


星期五, 十二月 13, 2013

C++ 11 迷茫的语言设计师们

刚刚看完c++11的激动过去了,再实际测试使用中,碰到了许多啼笑皆非的语言行为,
或者说实现和设计完全背离的行为。
C++11给出了很好的uniform initialization的方式。即花括号{}
auto i{10};非常优雅。
但是,且慢。
struct ABC_def
{
  string name;
  int tall{20};//给个默认的初始值吧。
}
然后
ABC_def test={"William",1000};
g++ 4.8.1 编译通不过了。
blabla:
error: could not convert '{"William",1000}' from '<brace-enclosed initializer list>' to 'BALL_DATA'
  BALL_DATA data=
{"William",1000};
 
What Hell?
Google !果然发现了有关聚合初始化的一些语言规范限制:
http://en.cppreference.com/w/cpp/language/aggregate_initialization
 
no brace-or-equal initializers for non-static members 非静态成员.不能有默认的值语法
 
 为什么语言规范里会有这么愚蠢的限制?且慢吐槽!先看看规范提交大师们的解释或者思路。
找了许久,只是看到一些讨论的帖子,完全没有找到一个理由解释这种限制的原因,
而且据说要在c++14里消掉这种限制............
 
C++ 的各位大神把一个语言规范弄成这样。。。惭愧吗?
 
 
 

规则表达开源库PCRE向Android下的移植步骤 window 下mingw64 gcc/g++ 4.8.1

pcre向Android下的移植 window 下mingw64 4.8.1

该编译需要在msys环境下运行,所以必须准备的环境是:
1.Android ndk (我使用的是android ndk r9b )
2.msys (http://www.mingw.org/wiki/MSYS)下载http://downloads.sourceforge.net/mingw/MSYS-1.0.11.exe。安装到d:\msys
3.下载 pcre 8.33包www.pcre.org
4.展开pcre 8.33 包pcre-8.33.zip 到d:\
 以下是步骤。

1.准备独立的android ndk toolchain,
D:\Android\android-ndk-r9b\build\tools\make-standalone-toolchain.bat --platform=android-9 --install-dir=d:\temp\my-toolchain --toolchain=arm-linux-androideabi-4.8
2.进入 msys shell 通过桌面快捷方式或者d:\msys\1.0\msys.bat都可以.
 运行mount 可以看到系统的各个盘被映射的方式 window d:盘 映射为  /d
3.将目录输入到PATH里
 export PATH=/d/temp/my-toolchina/bin:/d/msys/1.0/bin/
./configure --host=arm-linux-androideabi --prefix=G:/William_Wang/pcre-8.33 
--disable-shared --enable-newline-is-anycrlf --enable-utf8 --enable-unicode-properties
$ make #等待稍长时间后,在.libs目录下生成了.a静态库和.so后缀的动态库,由于--disable-shared禁止了动态库,所以只有.a的静态库了
$ make install 
此时在pcre-8.33目录下生成了android 命令行程序 pcretest
adb push pcretest /sdcard/temp/然后adb shell 进入超级用户后,如果手机已经root了,可以chmod 755 pcretest 权限后,直接运行。
即可。

PCRE configure 参数清单
 
 
 

    Build 8 bit pcre library ........ : yes --disable-pcre8
    Build 16 bit pcre library ....... : no --enable-pcre16
    Build 32 bit pcre library ....... : no --enable-pcre32
    Build C++ library ............... : yes --disable-cpp
    Enable JIT compiling support .... : no --enable-jit
    Enable UTF-8/16/32 support ...... : yes --enable-utf8
    Unicode properties .............. : yes --enable-unicode-properties
    Newline char/sequence ........... : anycrlf --enable-newline-is-anycrlf
    \R matches only ANYCRLF ......... : no --enable-bsr-anycrlf
    EBCDIC coding ................... : no   --enable-ebcdic
    EBCDIC code for NL .............. : n/a --enable-ebcdic-nl25
    Rebuild char tables ............. : no   --enable-rebuild-chartables
    Use stack recursion ............. : yes --disable-stack-for-recursion
    POSIX mem threshold ............. : 10 --with-posix-malloc-threshold=20
    Internal link size .............. : 2 --with-link-size=2
    Match limit ..................... : 10000000 --with-match-limit=10000000
    Match limit recursion ........... : MATCH_LIMIT --with-match-limit-recursion=10000
    Build shared libs ............... : no --disable-shared
    Build static libs ............... : yes --disable-static
    Use JIT in pcregrep ............. : no --disable-pcregrep-jit
    Buffer size for pcregrep ........ : 20480 --with-pcregrep-bufsize=20K
    Link pcregrep with libz ......... : no --enable-pcregrep-libz
    Link pcregrep with libbz2 ....... : no --enable-pcregrep-libbz2
    Link pcretest with libedit ...... : no --enable-pcretest-libedit
    Link pcretest with libreadline .. : no --enable-pcretest-libreadline
    Valgrind support ................ : no --enable-valgrind
    Code coverage ................... : no --enable-coverage
 
 Libraries (lib):
    libpcre16     (if 16-bit character support support is enabled)
    libpcre32     (if 32-bit character support support is enabled)
    libpcre       (if 8-bit support is enabled)
    libpcreposix  (if 8-bit support is enabled)
    libpcrecpp    (if 8-bit and C++ support is enabled)
The following table shows the different representations of a few characters in comparison:
Unicode code point
U+0041
U+00DF
U+6771
U+10400
Representative glyph
UTF-32 code units
00000041
000000DF
00006771
00010400
UTF-16 code units
0041
00DF
6771
D801DC00
UTF-8 code units
41
C39F
E69DB1
F0909080
参考个选项意义:
http://www.pcre.org/pcre.txt
 

星期五, 十二月 06, 2013

mingw for window gcc 4.8.1 有bug.不支持std::to_string

这个bug自2012年就被发现了,可是一直到现在都在www.ming.org的版本里没有更新。
通过stackflow的帖子,下载了mingw32 w64的版本,果然这个bug修复了。

http://mingw-w64.sourceforge.net/

看gnu,现在c++11在语法编译器g++和运行库libstdc++都已经完备支持了。但是还没有window下的版本释放。
据说到2014年的gcc 4.9系列将完全释出。

星期四, 十二月 05, 2013

c++11革命性特征,增加软件健壮性。

Java处理异常通过try
{}catch(Exception e)//或者catch(Throwable t)
{}可以处理所有的异常了。
c++早期虽然可以通过
try
{}catch(...){}
来处理所有的异常。但是无法得知是什么异常类型,只能给出自己定制的异常信息。

c++11 后,提供了std::current_exception()即可处理所有异常了,并明确异常信息。
当然为了提出这个一场信息,处理过程依然不够java优雅,
需要一个再次扔出异常指针的过程。
代码:
catch(...)
 {
         std::exception_ptr eptr= std::current_exception(); // capture
         handle_eptr(eptr);
     }

void handle_eptr(std::exception_ptr eptr) // passing by value is ok
{
    try {
        if (eptr != std::exception_ptr()) {
            std::rethrow_exception(eptr);
        }
    } catch(const std::exception& e) {
        std::cout << "Caught exception \"" << e.what() << "\"\n";
    }
}