Ubuntu 12.04 + Apache2.2.22搭建SPDY服务器

SPDY是Google开发的基于传输控制协议(TCP)的应用层协议,该协议规定在一个SPDY连接内可以有无限个并行请求,服务器可以主动向客户端发起通信向客户端推送数据,通过请求优化、预加载、压缩HTTP 来达到加速的目的。

对用记而言,SPDY是基于SSL加密,它可以让网络访问更安全,用户隐私更加得到保护。对站长而言,SPDY在降低连接数目的同时,还使服务器上每个客户端占用的资源减少,从释放出更多内存和CPU ,让网站的浏览速度提升不少。

SPDY协议已经被Chrome、Firefox、Opera、IE 11以上支持,用户在访问使用SPDY协议加载的网站几乎感觉不到与普通的Https页面访问有何不同,而SPDY带来的页面加载速度提升和服务器性能优化确是有十分重要意义的。

具体的操作步骤如下:

  • 启用Apache2的HTTPS支持

参考 UBUNTU 12.04 下 APACHE 2.2.22 开启 HTTPS

  • 下载Apache2的mod_spdy模块

官网:https://developers.google.com/speed/spdy/mod_spdy/
由于众所周知的原因,本站提供下载(2015-11-6版本)
mod_spdy 64-bit .deb (Debian/Ubuntu)
mod_spdy 32-bit .deb (Debian/Ubuntu)

  • 安装mod_spdy模块(本站是64位系统)
$sudo dpkg -i mod-spdy-*.deb
$sudo apt-get -f install
  • 重启Apache2
$sudo service apache2 restart
  • 验证

目前验证貌似没有起作用啊!目前最新的chrome已经没办法进行验证了,主要是由于HTTP/2已经发布,Google放弃了spdy,转而支持HTTP/2,还是静待新版本的HTTP/2吧。

  • 卸载
$sudo dpkg -r mod-spdy-beta
$sudo dpkg -P mod-spdy-beta
  • 参考链接

Linux Mint + Apache2.2搭建SSL/HTTPS/SPDY服务器
https://developers.google.com/speed/spdy/mod_spdy/

IScroll的使用-方向键绑定&自定义滚动条样式

之前在webkit上开发一个滚动控件,需要完成的是一段文字,上下键可以滚动,且自定义滚动条。第一想法就是浏览器原生overflow:scroll,且webkit支持自定义滚动条样式:

webkit自定义滚动条样式:

/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar
{
    width: 0.05rem;
    height:1rem;
    background-color: transparent;
}

/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track
{
    background-color: transparent;
}

/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb
{
    border-radius: 0.1rem;
    /*-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);*/
    background-color: rgba(255,255,255,0.6);
}

后来换了个引擎,发现其他引擎不支持自定义滚动条,那就满足不了UED的要求了。来同事推荐使用IScroll,用了一下,确实比较方便,与平台无关,可操作的属性还有性能都很理想,记录一下:

首先看官方文档 https://iiunknown.gitbooks.io/iscroll-5-api-cn/content/versions.html

github地址:https://github.com/cubiq/iscroll

demo:http://cubiq.org/dropbox/iscroll4/examples/simple/

直接拿demo中的iscroll.js套到自己的工程上,一个段落就是一个li,new 一下就完事了,滚动拖动也很happy。然后发现,我按上下方向键没有响应。

IScroll按键事件绑定:

查源码看iscroll的事件处理,都在handleEvent函数里面

handleEvent: function (e) {
    var that = this;
    switch(e.type) {
        case START_EV:
        if (!hasTouch && e.button !== 0) return;
        that._start(e);
        break;
        case MOVE_EV: that._move(e); break;
        case END_EV:
        case CANCEL_EV: that._end(e); break;
        case RESIZE_EV: that._resize(); break;
        case WHEEL_EV: that._wheel(e); break;
        case 'mouseout': that._mouseout(e); break;
        case TRNEND_EV: that._transitionEnd(e); break;
    }
}

根本就没有keyEvent,看来偷懒是不行的,官方文档看一下,原来iscroll有5个版本,各自平台都是不一样的,demo中这个估计是移动平台用的iscroll-lite版本,移动平台根本不鸟方向键的。

去github上down下来源码,找了找,build目录下,5个版本都有。用最原始的common版本,这个版本的handleEvent就丰富多了:

handleEvent: function (e) {
   switch ( e.type ) {
      case 'touchstart':
      case 'pointerdown':
      case 'MSPointerDown':
      case 'mousedown':
         this._start(e);
         break;
      case 'touchmove':
      case 'pointermove':
      case 'MSPointerMove':
      case 'mousemove':
         this._move(e);
         break;
      case 'touchend':
      case 'pointerup':
      case 'MSPointerUp':
      case 'mouseup':
      case 'touchcancel':
      case 'pointercancel':
      case 'MSPointerCancel':
      case 'mousecancel':
         this._end(e);
         break;
      case 'orientationchange':
      case 'resize':
         this._resize();
         break;
      case 'transitionend':
      case 'webkitTransitionEnd':
      case 'oTransitionEnd':
      case 'MSTransitionEnd':
         this._transitionEnd(e);
         break;
      case 'wheel':
      case 'DOMMouseScroll':
      case 'mousewheel':
         this._wheel(e);
         break;
      case 'keydown':
         this._key(e);
         break;
      case 'click':
         if ( !e._constructed ) {
            e.preventDefault();
            e.stopPropagation();
         }
         break;
   }
}

然后套用上去,可以支持方向键了。中间遇到两个小问题,第一个是按键一直没反应,检查下是z-index太小,keyEvent被上层元素拿走了;第二个是只有在#warpper拿到focus的时候才响应按键,但我用的引擎不支持focus,这个也不难,页面强行绑定handleEvent:

document.addEventListener("keydown", function(evt) {
    if (evt.keyCode === keyCodes.ENTER) {
    } else {
        myScroll && myScroll.handleEvent(evt);
    }
}, false);

然后整个页面随便按什么键,都可以响应了。接下来就是滚动条样式的问题了,这个也简单,跟着官方文档&样例走就行

http://lab.cubiq.org/iscroll5/demos/styled-scrollbars/

关键步骤有三个:

1.option

myScroll = new IScroll(document.getElementById('wrapper'), {
    keyBindings: true,          // 绑定按键事件
    scrollbars: 'custom',       // 自定义样式
    resizeScrollbars: false     // 是否自动缩放滚动条
});

设置了scrollbars: 'custom',在页面的Elements就可以找到

<div class="iScrollVerticalScrollbar iScrollLoneScrollbar" ></div>

里面还包含了

<div class="iScrollIndicator" ></div>

第一个是滚动区域,第二个是滚动条。拿到Element就好办了,css给定样式:

.iScrollVerticalScrollbar {
    position: absolute;
    z-index: 9999;
    width: 0.1rem;
    bottom: 2px;
    top: 2px;
    right: 0;
    overflow: hidden;
}

.iScrollIndicator {
    position: absolute;
    width: 0.08rem; height: 0.3rem;
    background: rgba(255,255,255,0.6);
    border-radius: 0.1rem;
}

大功告成!

当然,IScroll不止这点功能,官方文档后面还有无限滚动等高级用法,以后用到再添加。

WordPress使用WP-PostViews实现网站上显示文章的浏览量

WordPress的使用很方便,但是文章的点击浏览量默认是没有的,本文介绍用WP-PostViews实现网站上显示文章的浏览量的功能。效果如下图所示:WP-PostViews_Settings

  • 安装WP-PostViews插件

在插件界面中安装WP-PostViews插件,并且启用插件。

  • 修改主题文件(Twenty Fourteen)

修改content.php,找到如下代码:

<div class="entry-meta">
	<?php
		if ( 'post' == get_post_type() )
			twentyfourteen_posted_on();

		if ( ! post_password_required() && ( comments_open() || get_comments_number() ) ) :
	?>
	<span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'twentyfourteen' ), __( '1 Comment', 'twentyfourteen' ), __( '% Comments', 'twentyfourteen' ) ); ?></span>
	<?php
		endif;

		edit_post_link( __( 'Edit', 'twentyfourteen' ), '<span class="edit-link">', '</span>' );
	?>
</div><!-- .entry-meta -->

在后面添加:

<?php 
	/*View Counter for  wp-postviews*/
	if(function_exists('the_views')) { the_views(); } 
?>

修改后的结果如下:

<div class="entry-meta">
	<?php
		if ( 'post' == get_post_type() )
			twentyfourteen_posted_on();

		if ( ! post_password_required() && ( comments_open() || get_comments_number() ) ) :
	?>
	<span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'twentyfourteen' ), __( '1 Comment', 'twentyfourteen' ), __( '% Comments', 'twentyfourteen' ) ); ?></span>
	<?php
		endif;

		edit_post_link( __( 'Edit', 'twentyfourteen' ), '<span class="edit-link">', '</span>' );
	?>
	<?php 
		/*View Counter for  wp-postviews*/
		if(function_exists('the_views')) { the_views(); } 
	?>
</div><!-- .entry-meta -->
  • 修改主题文件(Twenty Fifteen)

修改content.php,找到如下代码:

<footer class="entry-footer">
	<?php twentyfifteen_entry_meta(); ?>
	<?php edit_post_link( __( 'Edit', 'twentyfifteen' ), '<span class="edit-link">', '</span>' ); ?>
</footer><!-- .entry-footer -->

在后面添加:

<?php 
	/*View Counter for  wp-postviews*/
	if(function_exists('the_views')) { the_views(); } 
?>

修改后的结果如下:

<footer class="entry-footer">
	<?php twentyfifteen_entry_meta(); ?>
	<?php edit_post_link( __( 'Edit', 'twentyfifteen' ), '<span class="edit-link">', '</span>' ); ?>
	<?php 
		/*View Counter for  wp-postviews*/
		if(function_exists('the_views')) { the_views(); } 
	?>
</footer><!-- .entry-footer -->

LMbench 3.0移植到Android并测试内存带宽

LMbench是个可移植的,用于评价系统综合性能的多平台开源benchmark,能够测试包括文档读写、内存操作、进程创建销毁开销、网络等性能。通过以下步骤操作,即可将LMbench移植到Android上。

  • 下载LMbench源码

下载地址http://sourceforge.net/projects/lmbench/
也可在本站下载

  • 修改LMbench代码

1.解压缩到指定的目录,保证最终的目录如下:

├── lmbench3/

│        ├── jni/

│            ├── doc/

│            ├── result/

│            ├── scripts/

│            ├── src/

│            ├── ACKNOWLEDGEMENTS

│            ├── CHANGES

│            ├── COPYING

│            ├── COPYING-2

│            ├── hbench-REBUTTAL

│            ├── Makefile

│            ├── README

2.修改“src/bench.h”的38行,40行,注释掉“#include <rpc/rpc.h>”,“#include <rpc/types.h>”,然后添加如下定义

#ifndef S_IREAD 
#define S_IREAD S_IRUSR
#endif

#ifndef S_IWRITE
#define S_IWRITE S_IWUSR
#endif

3.添加根目录下面Android.mk,jni/目录下面内容如下:

# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

BUILD_LMBENCH := true

include $(call all-subdir-makefiles)

4.添加根目录下面Android.mk,jni/src目录下面内容如下:

# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

ifeq ($(BUILD_LMBENCH),true)
LOCAL_PATH := $(call my-dir)
COMMON_CFLAGS := -DANDROID -DHAVE_uint
COMMON_LIBS := lmbench_lib
ANDROID_LMBENCH := true

# Build lmbench_lib
include $(CLEAR_VARS)

LOCAL_SRC_FILES := lib_unix.c lib_timing.c \
   	lib_mem.c lib_stats.c lib_debug.c getopt.c lib_sched.c
ifneq ($(ANDROID_LMBENCH),true)
	LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) lib_tcp.c lib_udp.c
endif
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lmbench_lib

include $(BUILD_STATIC_LIBRARY)

#
# Build mhz on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= mhz.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := mhz

include $(BUILD_EXECUTABLE)

#
# Build bw_file_rd on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= bw_file_rd.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := bw_file_rd

include $(BUILD_EXECUTABLE)

#
# Build bw_mem on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= bw_mem.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := bw_mem

include $(BUILD_EXECUTABLE)

#
# Build bw_mmap_rd on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= bw_mmap_rd.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := bw_mmap_rd

include $(BUILD_EXECUTABLE)

#
# Build bw_pipe on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= bw_pipe.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := bw_pipe

include $(BUILD_EXECUTABLE)

ifneq ($(ANDROID_LMBENCH),true)
#
# Build bw_tcp on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= bw_tcp.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := bw_tcp

include $(BUILD_EXECUTABLE)
endif

#
# Build bw_unix on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= bw_unix.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := bw_unix

include $(BUILD_EXECUTABLE)

#
# Build lat_cmd on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_cmd.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_cmd

include $(BUILD_EXECUTABLE)

ifneq ($(ANDROID_LMBENCH),true)
#
# Build lat_connect on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_connect.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_connect

include $(BUILD_EXECUTABLE)
endif

#
# Build lat_ctx on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_ctx.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_ctx

include $(BUILD_EXECUTABLE)

#
# Build lat_fcntl on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_fcntl.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_fcntl

include $(BUILD_EXECUTABLE)

#
# Build lat_fs on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_fs.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_fs

include $(BUILD_EXECUTABLE)

#
# Build lat_mem_rd on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_mem_rd.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_mem_rd

include $(BUILD_EXECUTABLE)

#
# Build lat_mmap on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_mmap.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_mmap

include $(BUILD_EXECUTABLE)

#
# Build lat_ops on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_ops.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_ops

include $(BUILD_EXECUTABLE)

#
# Build lat_pipe on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_pipe.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_pipe

include $(BUILD_EXECUTABLE)

#
# Build lat_pagefault on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_pagefault.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_pagefault

include $(BUILD_EXECUTABLE)

#
# Build lat_proc on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_proc.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_proc

include $(BUILD_EXECUTABLE)

#
# Build lat_rand on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_rand.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_rand

include $(BUILD_EXECUTABLE)

ifneq ($(ANDROID_LMBENCH),true)
#
# Build lat_tcp on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_tcp.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_tcp

include $(BUILD_EXECUTABLE)
endif

ifneq ($(ANDROID_LMBENCH),true)
#
# Build lat_sem on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_sem.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_sem

include $(BUILD_EXECUTABLE)
endif

#
# Build lat_sig on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_sig.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_sig

include $(BUILD_EXECUTABLE)

#
# Build lat_syscall on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_syscall.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_syscall

include $(BUILD_EXECUTABLE)

ifneq ($(ANDROID_LMBENCH),true)
#
# Build lat_udp on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_udp.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_udp

include $(BUILD_EXECUTABLE)
endif

#
# Build lat_unix on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_unix.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_unix

include $(BUILD_EXECUTABLE)

#
# Build lat_usleep on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_usleep.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags) -DTRUE=1 -DFALSE=0
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_usleep

include $(BUILD_EXECUTABLE)

#
# Build cache on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= cache.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := cache

include $(BUILD_EXECUTABLE)

#
# Build line on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= line.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := line

include $(BUILD_EXECUTABLE)

#
# Build lmdd on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lmdd.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lmdd

include $(BUILD_EXECUTABLE)

#
# Build tlb on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= tlb.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := tlb

include $(BUILD_EXECUTABLE)

#
# Build stream on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= stream.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lmstream

include $(BUILD_EXECUTABLE)

#
# Build memsize on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= memsize.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := memsize

include $(BUILD_EXECUTABLE)

ifneq ($(ANDROID_LMBENCH),true)
#
# Build lat_select on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_select.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_select

include $(BUILD_EXECUTABLE)
endif

#
# Build lat_unix_connect on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_unix_connect.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_unix_connect

include $(BUILD_EXECUTABLE)

#
# Build lat_fifo on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_fifo.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_fifo

include $(BUILD_EXECUTABLE)

ifneq ($(ANDROID_LMBENCH),true)
#
# Build lat_http on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= lat_http.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := lat_http

include $(BUILD_EXECUTABLE)
endif

#
# Build par_mem on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= par_mem.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := par_mem

include $(BUILD_EXECUTABLE)

#
# Build par_ops on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= par_ops.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := par_ops

include $(BUILD_EXECUTABLE)

#
# Build enough on target
#
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= enough.c
LOCAL_STATIC_LIBRARIES := $(COMMON_LIBS)
LOCAL_C_INCLUDES := $(common_target_c_includes)
LOCAL_CFLAGS := $(COMMON_CFLAGS) $(common_target_cflags)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := enough

include $(BUILD_EXECUTABLE)

endif
  • 编译LMbench代码
ndk-build NDK_PROJECT_PATH=/lmbench3

编译完成后的文件存放在“lmbench3\libs\armeabi”目录下面。

  • 测试内存带宽
./bw_mem 16M rdwr

更详细的命令参数,参考bw_mem

  • 参考链接
  1. andlmbench
  2. lmbench
  3. Performance Measurement on ARM

Windows下VirtualBox直接使用物理硬盘作虚拟机磁盘

目前VirtualBox只能用命令行来建立磁盘才可以使用物理硬盘。

我们假定VirtualBox安装在“D:\Program Files\Oracle\VirtualBox”这个目录下面,要在“D:\Users\VirtualBox VMs\Ubuntu\”目录下面生成文件,则执行如下命令:

"D:\Program Files\Oracle\VirtualBox\VBoxManage.exe" internalcommands createrawvmdk -filename "D:\Users\VirtualBox VMs\Ubuntu\Ubuntu.vmdk" -rawdisk \\.\PhysicalDrive1

\\.\PhysicalDrive1 表示机器上的第二块硬盘,\\.\PhysicalDrive0是第一块,\\.\PhysicalDrive2是第三块,以此类推。

在Windows 的磁盘管理中能看到硬盘的分区路径。如下图所示:ComputerManger

然后新建虚拟机,选择"使用已有的虚拟硬盘文件",找到刚刚创建的 Ubuntu.vmdk 即可。

对于Windows 8.1/10系统,以上的命令需要以管理员启动命令行的方式下启动并执行,否则会报告找不到磁盘。另外启动Virtual Box的时候,同样需要以管理员的身份运行,否则会出现VERR_ACCESS_DENIED错误,如下图所示:

VERR_ACCESS_DENIED

使用grunt压缩代码&配置多个任务

grunt是node环境下一个压缩、合并 js、css代码的工具,还可以做一下代码美化等。体验了一下压缩合并,还是不错的,大概流程如下:

在工程下建一个grunt目录,写两个文件 package.json-工程依赖Gruntfile.js-压缩任务

package.jsn:

{
  "name": "xxx",
  "version": "v0.1.0",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-concat": "~0.5.1",
    "grunt-contrib-cssmin": "~0.12.3",
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-nodeunit": "~0.4.1",
    "grunt-contrib-uglify": "~0.5.0",
    "grunt-htmlhint": "~0.9.2"
  }
}

Gruntfile.js:

module.exports = function(grunt) {
    // 配置参数
    grunt.initConfig({
        pkg:grunt.file.readJSON('package.json'),
        // 代码合并
        concat:{
            options:{
                separator: ";",
                stripBanners: true
            },
            dist:{
                src:[
                    "../focusManager/base.js",
                    "../focusManager/tween.js",
                    "../focusManager/widget.js",
                    "../focusManager/yunos.js"
                ],
                dest: "dest/focusManager.js"
            }
        },
        // 代码压缩
        uglify:{
            options:{

            },
            dist:{
                files:{
                    "dest/focusManager-min.js" : "dest/focusManager.js"
                }
            }
        },
        // css压缩
        cssmin: {
            options: {
                keepSpecialComments: 0
            },
            compress:{
                files:{
                    "dest/default.css": [
                        "../focusManager/base.css",
                        "../focusManager/reset.css"
                    ]
                }
            }
        }
    });

    // 载入concat、uglify、cssmin插件,进行压缩
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');

    // 注册任务
    grunt.registerTask('default', ['concat', 'uglify', 'cssmin']);
};

这个Gruntfile很容易理解,想要压缩的文件以及目标文件写好就行,还有另一种自动化的写法,后面再说。

之后运行命令,grunt

1

出现了一个错误,网上解释

Note that installing grunt-cli does not install the grunt task runner! The job of the grunt CLI is simple: run the version of grunt which has been installed next to a Gruntfile. This allows multiple versions of grunt to be installed on the same machine simultaneously.

So in your project folder, you will need to install (preferably) the latest grunt version:

也就是说,之前装的grunt-cli只是grunt的运行环境,在工程目录下,还需要装一下grunt,运行一下命令:

$npm install grunt --save-dev

Option --save-dev will add grunt as a dev-dependency to your package.json. This makes it easy to reinstall dependencies.

2

之后再次运行grunt命令,又出现错误:

3

好吧,没有装这三个插件?原来是grunt一样,也要在工程下装,分别运行 npm install装一下,运行,成功:

4

工程复杂之后,肯定不会一个一个手动填文件,grunt也可以通过逻辑自动压缩js css文件,Gruntfile.js写法:

module.exports = function(grunt) {
    // 任务配置
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        // 压缩JS
        uglify: {
            // 文件头部输出信息
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            my_target: {
                files: [
                    {
                        expand: true,
                        // 相对路径
                        cwd: '../focusManager',
                        src: ['*.js', '**/*.js'],
                        // src:['**/*.js', '!**/*.min.js'] 多个src的写法以及不包括哪些js
                        dest: 'dest/js/',
                        rename: function (dest, src) {
                            var folder = src.substring(0, src.lastIndexOf('/'));
                            var filename = src.substring(src.lastIndexOf('/'), src.length);
                            filename = filename.substring(0, filename.lastIndexOf('.'));
                            var resultname = dest + folder + filename + '-min.js';
                            grunt.log.writeln("正在处理文件:" + src + " 处理后文件:" + resultname);

                            return resultname;
                        }
                    }
                ]
            }
        },

        // 压缩css
        cssmin: {
            // 文件头部输出信息
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
                // 美化代码
                beautify: {
                    // 防止乱码
                    ascii_only: true
                }
            },
            my_target: {
                files: [
                    {
                        expand: true,
                        // 相对路径
                        cwd: '../focusManager',
                        src: '*.css',
                        // src:['**/*.js', '!**/*.min.js'] 多个src的写法以及不包括哪些js
                        dest: 'dest/css/',
                        rename: function (dest, src) {
                            var folder = src.substring(0, src.lastIndexOf('/'));
                            var filename = src.substring(src.lastIndexOf('/'), src.length);
                            filename = filename.substring(0, filename.lastIndexOf('.'));
                            var resultname = dest + folder + filename + '-min.css';
                            grunt.log.writeln("正在处理文件:" + src + " 处理后文件:" + resultname);

                            return resultname;
                        }
                    }
                ]
            }
        }
    });

    // 加载模块
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');

    grunt.registerTask('default', ['uglify', 'cssmin']);
};

逻辑也很简单,就是把src里面的文件,压缩,生成文件会经过rename函数处理。

这里面需要注意的地方有

src: ['*.js', '**/*.js'],

如果只写一个*.js,是不会递归cwd目录下的所有文件的,要递归几级写到数组中就可以了,如果不想添加什么文件,加!符号-‘!*.min.js’。

当然,这次也没有一帆风顺,运行的时候遇到错误:

5

报错在 最后一句,

grunt.registerTask('default', ['uglify', 'cssmin']);

查了半天也没找到这里有什么错误,网上搜了一下,大多数是 中括号里的uglify没有引号,跟我的情况也不一样。后来仔细检查了一下代码,发现了两处拼写错误,改了后就运行通过了,也就是说,其他错误都会报到最后一句。

做了一个小小的试验,写一个空模块

(function(){
    // for test
})();

压缩后是这样的:


对,什么都没了。

 

最近有新的需求,压缩不同版本的文件,就需要开多个contact uglify任务,琢磨了一会,搞出来了,同时对grunt有了进一步的认识。

配置多任务是这么写的

module.exports = function(grunt) {
    // 配置参数
    grunt.initConfig({
        pkg:grunt.file.readJSON('package.json'),
        // 代码合并
        concat:{
            options:{
                separator: ";",
                stripBanners: true
            },
            123456: {
                src:[
                    "../../system/123.js",
                    "../../system/456.js",
                    "../../system/network/789.js"
                ],
                dest: "out/123456789.js"
            },
            all: {
                src:[
                    "../../system/blitz.js",
                    "../../system/base.js",
                    "../../system/**/*.js",
                ],
                dest: "out/test_all.js"
            }
        },
        uglify:{
            123456: {
                files: [
                    {
                        "out/123456789.min.js" : "out/123456789.js"
                    }
                ]
            },
            all: {
                files: [
                    {
                        "out/test_all.min.js" : "out/test_all.js"
                    }
                ]
            },
            every: {
                // 文件头部输出信息
                //options: {
                //    banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
                //},
                files: [
                    {
                        expand: true,
                        // 相对路径
                        cwd: '../../system',
                        // 这里写三层,如果还有更多的再说
                        src: ['*.js', '**/*.js', '**/**/*.js'],
                        // src:['**/*.js', '!**/*.min.js'] 多个src的写法以及不包括哪些js
                        dest: './out/all/',
                        rename: function (dest, src) {
                            var folder = src.substring(0, src.lastIndexOf('/'));
                            var filename = src.substring(src.lastIndexOf('/'), src.length);
                            filename = filename.substring(0, filename.lastIndexOf('.'));
                            var resultname = dest + folder + filename + '.min.js';
                            grunt.log.writeln("正在处理文件:" + src + " 处理后文件:" + resultname);

                            return resultname;
                        }
                    }
                ]
            }
        }
    });

    // 载入concat、uglify、cssmin插件,进行压缩
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    //grunt.loadNpmTasks('grunt-contrib-cssmin');

    // 注册任务
    grunt.registerTask('default', ['concat', 'uglify']);
};

r简单看一下配置文件

contact

首先配置了option,option中配置了不同文件中间增加;分隔符。

这个是contact所有任务的全局配置

后面又写了三个合并任务,分别配置下src和dest就可以了。

合并顺序就是 src中配置的顺序,*.js则按照字母排序。

uglify

uglify中配置了三个压缩任务,

压缩contact的文件

压缩所有文件并生成.min.js

最后运行

grunt.registerTask('default', ['concat', 'uglify']);

会自动加载contact和uglify中的所有任务。

来源于http://www.haorooms.com/post/qd_grunt_cssjs。

ES6新特性

ECMAScript出现了许多有趣的新特性,梳理一下:

1.支持constant声明

ES5中,想实现constant变量必须通过修改var的property实现

Object.defineProperty(this, "PI", {
    value: 3.1415926,
    configurable: false,
    writable: false
});

2.支持块作用域声明let,

JS只有函数作用域,没有块作用域,var声明有变量提升的效果,即如果var声明了一个未声明过的变量,会自动将此声明提升到顶端,所以想实现块作用域在ES5中是通过闭包的形式。

(function(param) {})(i);

同时ES6也支持了块级作用域的函数

3.一种function的新写法

function中支持this的使用

nums.forEach(function(v) {
    return foo(v);
});

nums.forEach(v => {
    foo(v)
});

4.undefined参数默认配置

ES6:

function(x, y = 7, z = 10) {
    return x + y + z;
}

等效于ES5:

function(x, y, z) {
    if (y === undefined) {
        y = 7;
    }
    if (z === undefined) {
        z = 10;
    }
    return x + y + z;
}

5.支持剩余参数写法

即...p写法会被解释为

p.prototype.slice

ES6:

function f (x, y, ...a) {
    return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9

ES5:

function f (x, y) {
    var a = Array.prototype.slice.call(arguments, 2);
    return (x + y) * a.length;
};
f(1, 2, "hello", true, 7) === 9;

6.可以直接在字符串中加入${表达式}

即console.log("Error: ${e.toString()}");

7.引用

//lib/math.js
export function sum(x, y) {return x + y};
export var pi = 3.1415926;

//app.js
import * as math from "lib/math"
console.log(math.sum(math.pi, math.pi););

8.支持class 继承,setter、getter

class Shape {
    constructor (id, x, y) {
        this.id = id;
        this.move(x, y);
    }
    move (x, y) {
        this.x = x;
        this.y = y;
    }
}
class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y);
        this.width  = width;
        this.height = height;
    }
    set width(width) {this.width = width}
    get width()      {return this.width}
}
class Circle extends Shape {
    constructor (id, x, y, radius) {
        super(id, x, y);
        this.radius = radius;
    }
}

9.支持Promise Generators(待学习)

10.bufferArray

class Example {
    constructor (buffer = new ArrayBuffer(24)) {
        this.buffer = buffer
    }
    set buffer (buffer) {
        this._buffer    = buffer
        this._id        = new Uint32Array (this._buffer,  0,  1)
        this._username  = new Uint8Array  (this._buffer,  4, 16)
        this._amountDue = new Float32Array(this._buffer, 20,  1)
    }
    get buffer ()     { return this._buffer       }
    set id (v)        { this._id[0] = v           }
    get id ()         { return this._id[0]        }
    set username (v)  { this._username[0] = v     }
    get username ()   { return this._username[0]  }
    set amountDue (v) { this._amountDue[0] = v    }
    get amountDue ()  { return this._amountDue[0] }
}

let example = new Example()
example.id = 7
example.username = "John Doe"
example.amountDue = 42.0

Android Studio 1.4主工程中使用gradle:1.3.0生成包含NDK的APK没有包含非".so"后缀的文件

Android Studio 1.4主工程中使用gradle:1.3.0,编译NDK,其中生成两个文件,一个是.so的动态链接库,另一个是可执行程序,没有扩展名,在最后生成的APK中没有包含非".so"后缀的文件。这个问题纠结了好久,最后追踪到了Android Studio对应的Gradle代码文件中。发现在

Android Studio\gradle\m2repository\com\android\tools\build\builder\1.3.0\builder-1.3.0-sources.jar!\com\android\builder\internal\packaging\Packager.java

文件中有一个变量

private static final Pattern PATTERN_NATIVELIB_EXT = Pattern.compile("^.+\\.so$",Pattern.CASE_INSENSITIVE);

这个变量决定了最后的打包时候的过滤条件。

具体的代码如下图所示:ndk_build_not_include
最后的解决方案,就是把编译之后的文件重新命名成为“.so”。

这边的build.gradle的配置如下:

(其他配置参考Android Studio 1.2 开发JNI工程

task ndkBuild(type: Exec) {
	def Properties localProps = new Properties()
	localProps.load(new FileInputStream("local.properties"))
	def ndk_dir=localProps['ndk.dir']

	def ndk_build_cmd = "$ndk_dir/ndk-build"
	if (Os.isFamily(Os.FAMILY_WINDOWS)) {
		ndk_build_cmd = "$ndk_dir/ndk-build.cmd"
	}
	if(ndkBuild_Debug_Enabled) {
		commandLine ndk_build_cmd,
				'-j', Runtime.runtime.availableProcessors(),
				"NDK_PROJECT_PATH=$rootDir/app/src/main",
				"NDK_OUT=$buildDir/native/obj",
				"NDK_DEBUG=1"
	} else{
		commandLine ndk_build_cmd,
				'-j', Runtime.runtime.availableProcessors(),
				"NDK_PROJECT_PATH=$rootDir/app/src/main",
				"NDK_OUT=$buildDir/native/obj"
	}
	doLast {
		/* com.android.build.gradle.tasks.PackageApplication->doFullTaskAction->getBuilder().packageApk
		*Android Studio\gradle\m2repository\com\android\tools\build\builder\1.3.0\builder-1.3.0-sources.jar!\com\android\builder\internal\packaging\Packager.java
		*中的过滤变量     private static final Pattern PATTERN_NATIVELIB_EXT = Pattern.compile("^.+\\.so$",Pattern.CASE_INSENSITIVE);
		* 不能包含名字不是SO的其他文件
		*/
		File file = new File("$rootDir/app/src/main/libs");
		File[] files = file.listFiles(new FilenameFilter() {
			/**
			 * 测试指定文件是否应该包含在某一文件列表中。
			 *
			 * @param dir
			 *            被找到的文件所在的目录。
			 * @param name
			 *            文件的名称。
			 * @return 当且仅当该名称应该包含在文件列表中时返回 true;否则返回
			 *         false。返回true时,该文件将被允许添加到文件列表中,否则不能添加到文件列表中。
			 */
			public boolean accept(File dir, String name) {
				File f = new File(dir, name);
				if (f.isDirectory()) {
					File rf = new File(f.getPath(), "Standalone");
					if(rf.exists()){
						return true;
					}
					return false;
				}
				else {
					return false;// 否则返回false。
				}
			}
		});
		for(File f : files) {
			File src_file = new File(f.getAbsolutePath(), "Standalone");
			File dst_file = new File(f.getAbsolutePath(), "Standalone.so");
			dst_file.delete();
			src_file.renameTo(dst_file)
		}
	}
}

Windows下android-ndk-r10e执行ndk-gdb.py报告“ERROR: Non-debuggable application installed on the target device.”

Windows下android-ndk-r10e执行ndk-gdb.py报告“ERROR: Non-debuggable application installed on the target device.”

使用命令:

#ndk-gdb.py --verbose

具体信息如下所示。android-ndk-r10e-ndk-gdb-py

使用apk-tool反编译了一下APK包,AndroidManifest.xml中的“android:debuggable="true"”已经设置了,lib\armeabi目录下面也已经存在gdb.setup,gdbserver。奇怪了!使用pyScripter跟踪ndk-gdb.py,在684行附近发现,脚本找错目录了。ndk-gdb-py-684

解决方法比较简单,拷贝一份“android-ndk-r10e\prebuilt\android-arm”,并且重新命名成为 “android-ndk-r10e\prebuilt\android-armeabi”即可。