About Daylight time Info

本文引用:http://zhidao.baidu.com/question/1881583924190384708.html

夏令时,又称“日光节约时制”或“夏时制”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏令时的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。(各时区多数位于其理想边界之西,导致实际上全年实施夏令时。)

夏令时的历史
据称最早有夏令时构思的是本杰明·富兰克林(被印在100元美钞上的人物),他在任美国驻法国大使期间,由于习惯于当时美国农村贵族的早睡早起生活,早上散步时看到法国人10点才起床,夜生活过到深夜。于是他在1784年给《巴黎杂志》的编辑写了一封信,信上说法国人的生活习惯浪费了大好的阳光,建议他们早睡早起,说每年可以节约6千4百万磅蜡烛。但他当时并没有建议实行夏令时,只是建议人们应该早睡早起。因为当时根本还没有统一的时区划分。不过夏令时在英语里就是“节约阳光时间”的意思。

直到1907年,英国建筑师威廉·维莱特(William Willett)才正式向英国议会提出夏令时的构思,主要是为了节省能源和提供更多的时间用来训练士兵,但议会经过辩论没有采纳。由于名声不及本杰明·富兰克林,所以人们很多都将本杰明·富兰克林当为夏令时的发明者而忽略了威廉·维莱特。

1916年,德国首先实行夏令时,英国因为怕德国会从中得到更大的效益,因此紧跟着也采取了夏令时,夏令时节约了约15%的煤气和电力,但为了弥补损失,电力和煤气公司也将价格提高了15%。法国不久也效仿实行。1917年,俄罗斯第一次实行了夏令时,但直到1981年才成为一项经常性的制度。1918年,参加了第一次世界大战的美国也实行了夏令时,但战后立即取消了。

1942年,第二次世界大战期间,美国又实行了夏令时,1945年战争结束后取消。1966年,美国重新实行夏令时。欧洲大部分国家从1976年,即第四次中东战争导致首次石油危机3年后(1973年)开始实行夏令时。

根据联合国 欧洲经济委员会的建议,从1996年起夏令时的有效期推迟到10月份的最后一个星期日。

世界各国的夏令时
美国和墨西哥的实行与否,完全由各州各县自己决定。美国不实行夏令时的地区包括:
亚利桑那州
夏威夷州
波多黎各和维京群岛
美属萨摩亚、关岛和北马里亚纳群岛

美国和加拿大原本于每年10月的最后一个星期日凌晨2时起实施冬令时间;4月的第一个星期日凌晨2时起,恢复夏令时间。

但是根据美国国会最新通过的能源法案,为加强日光节约,自2007年起延长夏令时间,开始日期从每年4月的第一个星期日,提前到3月的第二个星期日,结束日期从每年10月的最后一个星期日,延后到11月的第一个星期日。换言之,冬令时间将缩短约一个月。之所以安排在周日,是为了便于生活的调整不至于受到较大的影响。

从来没有实行过夏令时间的地区欧盟国家、俄罗斯和瑞士都是从3月最后一个星期日到10月最后一个星期日实行夏令时。在格林尼治时间三月最后一个星期日的2:00欧盟国家同时进行时间更改,根据所在时区不同,西欧时区(UTC)国家(如:英国、爱尔兰和葡萄牙)、中欧时区(UTC+1)国家(如:法国、德国和意大利)和东欧时区(UTC+2)国家(如:芬兰和希腊)的当地时间分别从02:00/03:00调整到03:00/04:00。在格林尼治时间十月的最后一个星期日03:00进行相反的调整。

加拿大从3月第二个星期日到11月第一个星期日实行夏令时,不过萨斯喀彻温省大部分地区不实行;

墨西哥从4月第一个星期日到10月最后一个星期日实行夏令时,不过在首都墨西哥城,由于市长不同意总统实行夏令时的决定,有的区服从总统实行夏令时,有的区则服从市长不实行夏令时;

新西兰由于处于南半球,所以夏季和北半球相反。它从9月最后一个星期日到4月第一个星期天实行夏时;

澳大利亚除北部地区和昆士兰州 之外全部实行夏令时;西澳夏令时于十月的最后一个周日开始,到次年三月的最后一个周日结束;其余各州夏令时于十月的第一个周日开始,到次年四月的第一个周日结束。

中国的夏令时
夏令时实施期间,将时间向前调快一小时。
1919年,中华民国在上海和天津曾短暂地实行了一年夏令时。在台湾地区也曾实行过;香港曾于1941年4月1日至1979年10月21日期间,多在夏季时段实施夏令时间(1977年和1978年未实行),香港夏令时间的计算方法为香港标准时间加1小时。在日治时期的几年间(1942年至1945年)曾全年实施,当时香港时间与日本本土时间实际上一致,1980年后不再实行,详情请参阅香港时间;

1986年至1991年,中华人民共和国在全国范围实行了六年夏令时,每年从4月中旬的第一个星期日2时整(北京时间)到9月中旬第一个星期日的凌晨2时整(北京夏令时)。除1986年因是实行夏令时的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。1992年4月5日后不再实行;

实行夏令时的建议最早由窦星元提出。1986年4月,中共中央办公厅和国务院办公厅发出《在全国范围内实行夏令时的通知》,通知动员全国人民为节约能源而早睡早起,并要求全国各部门做好宣传和安排工作。具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时间),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。值得注意的是,夏令时中出生的人,生时须减去1小时。 从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行。

我国实行夏令时的时间:
1986年至1991年,每年4月中旬的第一个星期日1时起至9月中旬的第一个星期日1时止。
1986年4月13日至9月14日,
1987年4月12日至9月13日,
1988年4月10日至9月11日,
1989年4月16日至9月17日,
1990年4月15日至9月16日,
1991年4月14日至9月15日。

夏令时的利弊
优点
高纬度地区由于夏季太阳升起时间明显比冬季早,夏令时确实起到节省照明时间的作用。
不少零售商对夏令时持肯定态度。美国的糖果商院集团已经游说美国国会将夏令时延长到11月,因为万圣节是糖果销售最旺的季节,而家长们不希望孩子们在天黑以后还在外面游逛。
有人认为夏令时对患有夜盲症的人大有好处。

弊端
对低纬度地区,夏令时作用不大。尤其这些地方在夏天十分湿热,夜晚降临时闷热无法入眠,而清晨正是睡眠的好时间。
当夏令时开始和结束时,人们必须将所有计时仪器调快或调慢;当夏令时结束时,某些时间会在当天出现两次,这些都容易构成混乱。
夏令时违背了设定时区的原意──尽量使中午贴近太阳上中天的时间[1]。

其他争议
夏令时让俄罗斯每年能够节约20亿千瓦小时的电量,但这个数字只相当于两三个火力发电厂的发电量。该制度也使法国用于照明的能源消耗减少4%。有人认为夏令时在旅游业和能源消耗上获利不明显,还扰乱了儿童和老年人的生物钟,违反人的正常生理节奏。

About linux TZ 时区问题

本文引用:http://blog.csdn.net/epicyong333/article/details/5258152

tzset

#incude

void tzset(void);

设置时间环境变量。

说明
tzset()函数使用环境变量TZ的当前设置把值赋给三个全局变量:daylight,timezone和tzname。
这些变量由ftime和localtime函数使用校正格林威治(UTC)时间为本地时间,通过time函数从系统时间计算UTC,使用如下语法设置TZ环境变量:

set TZ=tzn[+|-]hh[:mm[:ss]][dzn]

tzn:三字母时区名,例如PST,你必须指出本地时间距UTC的偏移量。
hh:UTC与本地时间的时差,任选带符号的。
mm:分钟,由冒号(:)与hh分隔开。
ss:秒钟,用冒号(:)与mm分隔开。
dzn:三字母夏令时时区例如PDT。如果夏令时没作用,设置TZ时不设置dzn的值。C运行库假设在计算夏令时(DST)时执行美国的规则。

其实tzn和dzn可为任意3个字母,只要中间的时差设置正确,localtime()和gmtime()函数调用都会处理正确。要注意一点,比如要将时区TZ设置为中国所在的东八区(即UTC+8:00),不使用夏令时,使用如下语句:

setenv(“TZ”, “GMT-8”, 1);

注意是GMT-8而不是GMT+8,要不就设为了西八区,要比UTC还慢8个小时,这一点比较令人费解。

例如,为了设置TZ环境为德国对应的当前时区,你可以使用如下语句之一:
set TZ=GST-1GDT
set TZ=GST+1GDT
这些字符串使用GST指出德国标准时间,假设德国是超前UTC一个小时,并假设夏令时起作用。
如果TZ值没设置,tzset试图使用操作系统指定的时区信息,在Windwos NT和Windows95之下,这个信息指定在控制面版的日期/时间应用中,如果tzset不能获取这些信息,它缺省使用PST8PDT,它指定为太平洋标准时间。

基于TZ环境变量的值,当调用tzset时把如下值赋给全局变量daylight、timezone和tzname:
全局变量 说明 缺省值
daylight 如果在TZ设置中指定夏令时时区 1则为非0值;否则为0
timezone UTC和本地时间之间的时差,单位为秒 28800(28800秒等于8小时)
tzname[0] TZ环境变量的时区名称的字符串值 如果TZ未设置则为空 PST
tzname[1] 夏令时时区的字符串值; 如果TZ环境变量中忽略夏令时时区则为空PDT在上表中daylight和tzname数组的缺省值对应于”PST8PDT”。

如果从TZ环境变量忽略DST时区,daylight的值为0,ftime,gmtime和localtime函数对于它们的DST标志返回0。
例子

/ *
TZSET.C: This program first sets up the time zone by*
placing the variable named TZ=EST5 in the environment*
table. It then uses tzset to set the global variables*
named daylight, timezone, and tzname.*/
#include
#include
#include
void main( void )
{
if( putenv( “TZ=EST5EDT” ) == -1 )
{
printf( “Unable to set TZ/n” );exit( 1 );
}
else
{
tzset(); printf( “daylight = %d/n”, daylight );
printf( “timezone = %ld/n”, timezone );
printf( “tzname[0] = %s/n”, tzname[0] );
}
exit( 0 );
}

输出
daylight = 1
timezone = 18000
tzname[0] = EST

参见
asctime,ftime,gmtime,localtime,time,utime

首先要说明的是我的系统是fedora,其他系统可能不完全相同。

1,时间保存在硬件实时钟(RTC)中,RTC由主板电池供电,即使关断电源也不会造成时间丢失。

2,系统启动时从RTC获取时间,这个步骤在rc.sysinit中做:

a,首先从/etc/sysconfig/clock中获取RTC相关参数UTC/ARC/SRM。UTC为true表示RTC保存的时间是UTC时间,false表示保存的是本地时间。ARC与SRM的含义参考hwclock的manpage,一般false即可;

b,根据上面获取的内容构造hwclock命令的参数,将时间由RTC读取到系统时钟。

*需要说明的一点是hwclock的输出是本地时间,localtime/utc参数只是用 来告诉hwclock命令COMS时区是哪个时区。比如Linux系统的系统时区设置为CST(中国标准时间),COMS时间采用墙上时间,即COMS时 区也是CST,这时如果使用–utc参数,会让hwclock误以为COMS时区为UTC,所以输出的时间会自动+8。

3,tzset():tzset在程序中用来初始化tzname等全局变量,它首先试图从环 境变量“TZ”中获取时区,如果TZ环境变量存在,即getenv(“TZ”)返回值不为NULL,且包含内容有效,则使用TZ值;如果该变量存在但内容 无效,比如包含错误的时区名字,则使用UTC;如果该变量不存在,即getenv(“TZ”)返回NULL,则查找系统时区设置文件,一般是/etc /localtime。localtime所指文件的内容格式可参考tzfile(5)。

4,time():返回自00:00:00 UTC, January 1, 1970到现在所经过的秒数,注意,是UTC。

5,ctime()/localtime()/mktime():这类和时区相关的函数内部会调用tzset,但只是第一次调用tzset会做实际初始化,后面的调用都是直接返回。

6,系统关闭时,如执行shutdown/reboot/poweroff/halt等操作后,系统时间会保存到RTC中,这是在halt脚本中完成的,参看/etc/init.d/halt内容。

OpenWrt Makefile 整体分析

分析版本: svn://svn.openwrt.org.cn/openwrt/branches/backfire

OpenWrt基本结构
–target/linux/ 目录里面是各平台(arch)的相关代码
–target/linux//config 文件的配置文件
–package 目录里面包含了我们在配置文件里面设定的所有编译好的软件包
–scripts/feeds update 来对软件包进行更新
–scirpts/feeds search X 查找软件包X
–package/symlinks 估计意思是更新软件源之类的

=========================我是分割线=================
==以下部分参考:http://www.right.com.cn/forum/thread-73443-1-1.html===
=======================================================
OpenWrt的主Makefile文件只有100行,可以简单分为三部分,1~17行为前导部分,19~31为首次执行部分,33~101为再次执行部分。

前导部分
CURDIR为make默认变量,默认值为当前目录。
前导部分主要把变量TOPDIR赋值为当前目录,把变量LC_ALL、LANG赋值为C,并使用变量延伸指示符export,把上述三个变量延伸到下层Makefile。
使用文件使用指示符include引入$(TOPDIR)/include/host.mk。在OpenWrt的主Makefile文件使用了多次include指示符,说明主Makefile文件被拆分成多个文件,被拆分的文件放在不同的目录。拆分的目的是明确各部分的功能,而且增加其灵活性。
在前导部分比较费解的是使用world目标,在makefile中基本规则为:
TARGETS : PREREQUISITES
COMMAND

即makefile规则由目标、依赖、命令三部分组成,在OpenWrt的主Makefile文件的第一个目标world没有依赖和命令。它主要起到指示当make命令不带目标时所要执行的目标,没有设定依赖和命令部分表明此目标在此后将会有其他依赖关系或命令。world目标的命令需要进一步参考$(TOPDIR)/include/toplevel.mk和主Makefile文件的再次执行部分。

首次执行部分
OPENWRT_BUILD是区分首次执行与再次执行的变量。在首次执行时使用强制赋值指示符override把OPENWRT_BUILD赋值为1,并使用变量延伸指示符export把OPENWRT_BUILD延伸。在OPENWRT_BUILD使用强制赋值指示符override意味着make命令行可能引入OPENWRT_BUILD参数。
引入$(TOPDIR)/include/debug.mk、$(TOPDIR)/include/depends.mk、$(TOPDIR)/include/toplevel.mk三个文件,由于TOPDIR是固定的,所以三个文件也是固定的。其中$(TOPDIR)/include/toplevel.mk的135行%::有效解释首次执行时world目标的规则。

再次执行部分
引入rules.mk、$(INCLUDE_DIR)/depends.mk、$(INCLUDE_DIR)/subdir.mk、target/Makefile、package/Makefile、tools/Makefile、toolchain/Makefile七个文件,rules.mk没有目录名,即引入与主Makefile文件目录相同的rules.mk。在rules.mk定义了INCLUDE_DIR为$(TOPDIR)/include,所以$(INCLUDE_DIR)/depends.mk实际上与首次执行时引入的$(TOPDIR)/include/depends.mk是同一个文件。
四个子目录下的Makefile实际上是不能独立执行。主要利用$(INCLUDE_DIR)/subdir.mk动态建立规则,诸如$(toolchain/stamp-install)目标是靠$(INCLUDE_DIR)/subdir.mk的stampfile函数动态建立。在package/Makefile动态建立了$(package/ stamp-prereq)、$(package/ stamp-cleanup)、$(package/ stamp-compile)、$(package/ stamp-install)、$(package/ stamp-rootfs-prepare)目标。
定义一些使用变量命名的目标,其变量的赋值位置在$(INCLUDE_DIR)/subdir.mk的stampfile函数中。目标只有依赖关系,可能说明其工作顺序,在$(INCLUDE_DIR)/subdir.mk的stampfile函数中有进一步说明其目标执行的命令,并为目标建立一个空文件,即使用变量命名的目标为真实的文件。

定义一些使用固定的目标规则。
其中:clean是清除编译结果的目标,清除$(BUILD_DIR) $(BIN_DIR) $(BUILD_LOG_DIR)三个目录的用意是十分明确。暂时不知道为什么执行make target/linux/clean。
dirclean是删除所有编译过程产生的目录和文件的目标,执行dirclean目标依赖于clean,因此将执行clean目标所执行的命令,然后删除$(STAGING_DIR) $(STAGING_DIR_HOST) $(STAGING_DIR_TOOLCHAIN) $(TOOLCHAIN_DIR) $(BUILD_DIR_HOST) $(BUILD_DIR_TOOLCHAIN)目录,以及删除$(TMP_DIR)目录。上述目录的变量均在rules.mk定义。好像删除staging_dir目录就意味着删除staging_dir目录下的所有子目录,不知道为什么要强调删除$(STAGING_DIR_HOST) $(STAGING_DIR_TOOLCHAIN) $(TOOLCHAIN_DIR)目录。同样删除builde_dir目录就意味着删除builde_dir目录下的所有子目录,不知道为什么要强调删除$(BUILD_DIR_TOOLCHAIN)目录。
tmp/.prereq_packages目标是对所需软件包的预处理。目标依赖于.config,即执行make menuconfig后将会进行一次所需软件包的预处理。不知什么原因在编译前删除tmp目录,执行时无法建立tmp/.prereq_packages文件。
prereq应该是预请求目标,在OpenWrt执行Makefile时好像都要先执行prereq目标。
prepare应该是准备目标,是world依赖的一个伪目标。依赖于文件.config和$(tools/stamp-install) $(toolchain/stamp-install)目标。
world就是编译的目标。依赖于prepare为目标和前面提到的变量命名目标。采用取消隐含规则方式执行package/index目标。package/index目标在package/Makefile的92行定义。
package/symlinks和package/symlinks-install是更新或安装软件包来源的目标,使用$(SCRIPT_DIR)/feeds脚本文件完成。
package/symlinks-clean是清除软件包来源的目标,也是使用$(SCRIPT_DIR)/feeds脚本文件完成。
最后使用伪目标.PHONY说明clean dirclean prereq prepare world package/symlinks package/symlinks-install package/symlinks-clean属于伪目标。通过伪目标说明可以知道可以执行的目标。

===================我是分割线==================
====>Makefile:
TOPDIR:=${CURDIR} #定义直接变量取得当前make的工作目录
LC_ALL:=C
LANG:=C
export TOPDIR LC_ALL LANG #定义直接变量,把变量延伸,使得在包含的mk中也可用

world:
#指示make不带目标时要执行的命令,也就是默认执行的命令,由于其不带规则和依赖,所以表明此目标在此后将会有其他依赖关系或命令,当执行”~$ make”时,即跳转到toplevel.mk执行。======1======

include $(TOPDIR)/include/host.mk #引入文件

ifneq ($(OPENWRT_BUILD),1) #判断是否是首次执行OPENWRT_BUILD在toplevel.mk中定义为0
# XXX: these three lines are normally defined by rules.mk
# but we can’t include that file in this context
empty:=
space:= $(empty) $(empty)
_SINGLE=export MAKEFLAGS=$(space);

override OPENWRT_BUILD=1 #如果是首次执行,使用override强制openwrt_build为1
export OPENWRT_BUILD #延伸openwrt_build变量的使用
include $(TOPDIR)/include/debug.mk #引入文件
include $(TOPDIR)/include/depends.mk
include $(TOPDIR)/include/toplevel.mk
else
include rules.mk #不是首次执行,则引入以下文件
include $(INCLUDE_DIR)/depends.mk
include $(INCLUDE_DIR)/subdir.mk
include target/Makefile
include package/Makefile
include tools/Makefile
include toolchain/Makefile

$(toolchain/stamp-install): $(tools/stamp-install)
$(target/stamp-compile): $(toolchain/stamp-install) $(tools/stamp-install) $(BUILD_DIR)/.prepared
$(package/stamp-cleanup): $(target/stamp-compile)
$(package/stamp-compile): $(target/stamp-compile) $(package/stamp-cleanup)
$(package/stamp-install): $(package/stamp-compile)
$(package/stamp-rootfs-prepare): $(package/stamp-install)
$(target/stamp-install): $(package/stamp-compile) $(package/stamp-install) $(package/stamp-rootfs-prepare)
$(BUILD_DIR)/.prepared: Makefile
@mkdir -p $$(dirname $@)
@touch $@

prepare: $(target/stamp-compile)

clean: FORCE
$(_SINGLE)$(SUBMAKE) target/linux/clean
rm -rf $(BUILD_DIR) $(BIN_DIR) $(BUILD_LOG_DIR)

dirclean: clean
rm -rf $(STAGING_DIR) $(STAGING_DIR_HOST) $(STAGING_DIR_TOOLCHAIN) $(TOOLCHAIN_DIR) $(BUILD_DIR_HOST) $(BUILD_DIR_TOOLCHAIN)
rm -rf $(TMP_DIR)

#处理依赖问题===========9=========
tmp/.prereq_packages: .config
@echo “this is in main Makefile tmp/.prereq_packages”
unset ERROR; \
for package in $(sort $(prereq-y) $(prereq-m)); do \
$(_SINGLE)$(NO_TRACE_MAKE) -s -r -C package/$$package prereq || ERROR=1; \
done; \
if [ -n “$$ERROR” ]; then \
echo “Package prerequisite check failed.”; \
false; \
fi
touch $@

# check prerequisites before starting to build

#在toplevel.mk中的prereq目标执行完之后,跳转回到主Makefile文件,执行其prereq目标的规则================8====================
prereq: $(target/stamp-prereq) tmp/.prereq_packages
@echo “this is in main Makefile”

prepare: .config $(tools/stamp-install) $(toolchain/stamp-install)

#当所有的依赖已经准备好之后,开始执行编译==============10=============
world: prepare $(target/stamp-compile) $(package/stamp-cleanup) $(package/stamp-compile) $(package/stamp-install) $(package/stamp-rootfs-prepare) $(target/stamp-install) FORCE
$(_SINGLE)$(SUBMAKE) -r package/index

# update all feeds, re-create index files, install symlinks
package/symlinks:
$(SCRIPT_DIR)/feeds update -a
$(SCRIPT_DIR)/feeds install -a

# re-create index files, install symlinks
package/symlinks-install:
$(SCRIPT_DIR)/feeds update -i
$(SCRIPT_DIR)/feeds install -a

# remove all symlinks, don’t touch ./feeds
package/symlinks-clean:
$(SCRIPT_DIR)/feeds uninstall -a

.PHONY: clean dirclean prereq prepare world package/symlinks package/symlinks-install package/symlinks-clean

endif

=====>./include/toplevel.mk:
RELEASE:=Backfire #为了避免出现循环
SHELL:=/usr/bin/env bash
PREP_MK= OPENWRT_BUILD= QUIET=0

include $(TOPDIR)/include/verbose.mk

ifeq ($(SDK),1)
include $(TOPDIR)/include/version.mk
else
REVISION:=$(shell $(TOPDIR)/scripts/getver.sh) #shell 执行操作系统的命令
endif

OPENWRTVERSION:=$(RELEASE)$(if $(REVISION), ($(REVISION)))
export RELEASE
export REVISION
export OPENWRTVERSION
export IS_TTY=$(shell tty -s && echo 1 || echo 0)
export LD_LIBRARY_PATH:=$(if $(LD_LIBRARY_PATH),$(LD_LIBRARY_PATH):)$(STAGING_DIR_HOST)/lib
export DYLD_LIBRARY_PATH:=$(if $(DYLD_LIBRARY_PATH),$(DYLD_LIBRARY_PATH):)$(STAGING_DIR_HOST)/lib

# prevent perforce from messing with the patch utility
unexport P4PORT P4USER P4CONFIG P4CLIENT

# prevent user defaults for quilt from interfering
unexport QUILT_PATCHES QUILT_PATCH_OPTS

# make sure that a predefined CFLAGS variable does not disturb packages
export CFLAGS=

ifeq ($(FORCE),)
.config scripts/config/conf scripts/config/mconf: tmp/.prereq-build
endif

SCAN_COOKIE?=$(shell echo $$$$)
export SCAN_COOKIE

SUBMAKE:=umask 022; $(SUBMAKE)

prepare-mk: FORCE ;

#依赖于FORCE保证及时目标存在也会执行此命令=================4=============
prepare-tmpinfo: FORCE
mkdir -p tmp/info #-r禁止使用任何隐含规则 -f制定需要执行的文件-j输出规则中的命令 -r命令运行时不输出命令的输出 mkdir –p 一次性创建多层目录
$(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f include/scan.mk SCAN_TARGET=”packageinfo” SCAN_DIR=”package” SCAN_NAME=”package” SCAN_DEPS=”$(TOPDIR)/include/package*.mk $(TOPDIR)/overlay/*/*.mk” SCAN_DEPTH=5 SCAN_EXTRA=””
$(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f include/scan.mk SCAN_TARGET=”targetinfo” SCAN_DIR=”target/linux” SCAN_NAME=”target” SCAN_DEPS=”profiles/*.mk $(TOPDIR)/include/kernel*.mk $(TOPDIR)/include/target.mk” SCAN_DEPTH=2 SCAN_EXTRA=”” SCAN_MAKEOPTS=”TARGET_BUILD=1″
for type in package target; do \
f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \
[ “$$t” -nt “$$f” ] || ./scripts/metadata.pl $${type}_config “$$f” > “$$t” || { rm -f “$$t”; echo “Failed to build $$t”; false; break; }; \
done
./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
touch $(TOPDIR)/tmp/.build

.config: ./scripts/config/conf $(if $(CONFIG_HAVE_DOT_CONFIG),,prepare-tmpinfo)
@+if [ \! -e .config ] || ! grep CONFIG_HAVE_DOT_CONFIG .config >/dev/null; then \
#”+”无论如何这些命令都会被执行
[ -e $(HOME)/.openwrt/defconfig ] && cp $(HOME)/.openwrt/defconfig .config; \
$(_SINGLE)$(NO_TRACE_MAKE) menuconfig $(PREP_MK); \
fi

scripts/config/mconf:
@$(_SINGLE)$(SUBMAKE) -s -C scripts/config all

$(eval $(call rdep,scripts/config,scripts/config/mconf))

scripts/config/conf:
@$(_SINGLE)$(SUBMAKE) -s -C scripts/config conf
#-C 意思就是转到此目录下执行make -s全面禁止命令的显示,跳转到scripts/config下执行此目录下的Makefile文件的conf标签=============4=========

config: scripts/config/conf prepare-tmpinfo FORCE
$< Config.in #$< 描述了所有的依赖 config-clean: FORCE $(_SINGLE)$(NO_TRACE_MAKE) -C scripts/config clean defconfig: scripts/config/conf prepare-tmpinfo FORCE touch .config $< -D .config Config.in oldconfig: scripts/config/conf prepare-tmpinfo FORCE $< -$(if $(CONFDEFAULT),$(CONFDEFAULT),o) Config.in menuconfig: scripts/config/mconf prepare-tmpinfo FORCE if [ \! -e .config -a -e $(HOME)/.openwrt/defconfig ]; then \ cp $(HOME)/.openwrt/defconfig .config; \ fi $< Config.in prepare_kernel_conf: .config FORCE ifeq ($(wildcard staging_dir/host/bin/sed),) prepare_kernel_conf: @+$(SUBMAKE) -r tools/sed/install else prepare_kernel_conf: ; endif kernel_oldconfig: prepare_kernel_conf $(_SINGLE)$(NO_TRACE_MAKE) -C target/linux oldconfig kernel_menuconfig: prepare_kernel_conf $(_SINGLE)$(NO_TRACE_MAKE) -C target/linux menuconfig #建立其依赖 ===========6==============转到include/prereq-build.mk下执行,主要就是检查各种依赖关系是否已经安装好。 tmp/.prereq-build: include/prereq-build.mk mkdir -p tmp rm -f tmp/.host.mk @$(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f $(TOPDIR)/include/prereq-build.mk prereq 2>/dev/null || { \
echo “Prerequisite check failed. Use FORCE=1 to override.”; \
false; \
}
touch $@

download: .config FORCE
@+$(SUBMAKE) tools/download
@+$(SUBMAKE) toolchain/download
@+$(SUBMAKE) package/download
@+$(SUBMAKE) target/download

clean dirclean: .config
@+$(SUBMAKE) -r $@

#再次找到prereq目标,然后建立其依赖prepare-tmpinfo .config========3=========
prereq:: prepare-tmpinfo .config
@+$(MAKE) -r -s tmp/.prereq-build $(PREP_MK)
#-r 不运行命令,也不输出,仅仅检查目标是否需要更新========5===========
@+$(NO_TRACE_MAKE) -r -s $@ #所有的准备完之后,跳转回主Makefile文件======7=======

#双::号规则允许在多个规则中为同一个目标创建不同命令,NO_TRACE_MAKE在include/verbose.mk中定义为 :=$(MAKE) V=99,PREP_MK在开始定义为0,+代表之后的命令都要执行,也就是表示执行-r禁止使用任何隐含规则-s禁止所有执行命令的显示 $ make prereq =========2=========
%::
@+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq
@+$(SUBMAKE) -r $@

help:
cat README

docs docs/compile: FORCE
@$(_SINGLE)$(SUBMAKE) -C docs compile

docs/clean: FORCE
@$(_SINGLE)$(SUBMAKE) -C docs clean

distclean:
rm -rf tmp build_dir staging_dir dl .config* feeds package/feeds package/openwrt-packages bin
@$(_SINGLE)$(SUBMAKE) -C scripts/config clean

ifeq ($(findstring v,$(DEBUG)),)
.SILENT: symlinkclean clean dirclean distclean config-clean download help tmpinfo-clean .config scripts/config/mconf scripts/config/conf menuconfig tmp/.prereq-build tmp/.prereq-package prepare-tmpinfo
endif
.PHONY: help FORCE
.NOTPARALLEL:

快速了解 GNU Makefile 笔记

1. Make 程序会把第一条规则之后的多有以[Tab]字符开始的行都作为命令行来处理
2. 通过.PHONY特殊目标将clean目标声明为伪目标,防止在磁盘上存在一个clean文件名的时候,clean目标的规则无法执行
3. – 的意思是忽略命令的执行错误,比如:-rm edot $(objects)、 sinclude= -include
4. 一个完整的Makefile中,包含5个东西:显示规则,隐含规则,变量的定义,指示符和注释。
5. 默认查找Makefile文件名顺序:GNUmakefile、makefile、Makefile 推荐使用Makefile
6. Include 指示符告诉make暂停读取当前的Makefile,转去读取include指定的文件,完成后再继续当前Makefile的读取
7. MAKEFILE_LIST 变量make读取的文件名会被自动的追加到变量的定义域中
8. Makefile规则中,如果使用一个没有依赖只有命令行的双冒号规则去更新一个文件,那么每次执行make时,此规则的目标文件将会无条件的更新。
9. “所有匹配规则“
%:force
@$(MAKE) –f MAKEFILE $@
Force:;
10. 它的依赖是“force”,保证了即使目标文件已经存在也会执行这个规则
强制目标:没有命令或依赖的规则,如果一个规则没有命令或依赖,而且它的目标不是一个存在的文件名,在执行此规则时,目标总会被认为是最新的。
11.make的执行过程如下:

1. 依次读取变量“MAKEFILES”定义的makefile文件列表

2. 读取工作目录下的makefile文件(根据命名的查找顺序“GNUmakefile”,“makefile”,“Makefile”,首先找到那个就读取那个)

3. 依次读取工作目录makefile文件中使用指示符“include”包含的文件

4. 查找重建所有已读取的makefile文件的规则(如果存在一个目标是当前读取的某一个makefile文件,则执行此规则重建此makefile文件,完成以后从第一步开始重新执行)

5. 初始化变量值并展开那些需要立即展开的变量和函数并根据预设条件确定执行分支

6. 根据“终极目标”以及其他目标的依赖关系建立依赖关系链表

7. 执行除“终极目标”以外的所有的目标的规则(规则中如果依赖文件中任一个文件的时间戳比目标文件新,则使用规则所定义的命令重建目标文件)

8. 执行“终极目标”所在的规则

12.make 参数选项:
-f 指定make读取的Makefile文件 –f NAME 、–file=NAME
-n 那么make执行时只显示所要执行的命令,但不会真正的去执行这些命令 –just-print
-s 则是禁止所有执行命令的显示,就好像所有的命令均使用@开始一样 –slient
-j 可以告诉make在同一时刻可以允许多条命令同时被执行。–job
-k 当由于某种原因被终止时,会等待其它的子进程完成后才退出。
-l 告诉make限制当前运行的任务的数量—max-load 一般跟一个浮点数 -l 2.5
-I make将会忽略所有规则中命令执行错误 –ignore-errors
-w 可以让make在开始编译一个目录之前和完成此目录的编译之后给出相应的提示信息—print-directory

13.文件通配符:*、?、 [ ]
可以用在规则的目标,依赖,此时make会自动将其展开
可出现在规则的命令中,其展开是在shell执行此命令时完成
二是需要通过函数wildcard来实现

14.自动环变量
$? 表示依赖文件列表中被改变过的所有文件
$^ 表示所有的是通过目录搜索得到的依赖文件的完整路径名
$@ 表示规则的目标
$< 表示规则中通过目录搜索得到的依赖文件列表的第一个依赖文件 15.变量定义中使用的通配符不会被展开objects=”*.o” 则变量objects的值就是*.o 如果需要变量的值代表所有的.o文件需要使用函数wildcard实现(objects=$(wildcard *.o)) 16.vpath 指定搜索路径 vpath %.h ../headers如果不能再当前目录下找到,则到目录../headers下寻找。 要注意vpath 和VPATH 以及GPATH变量定义搜索路径时,生成目标文件的路径问题。 17. SUBDIRS = foo bar baz .PHONY: subdirs $(SUBDIRS) subdirs: $(SUBDIRS) $(SUBDIRS): $(MAKE) -C $@ foo: baz 上边的实现中使用了一个没有命令行的规则“foo: baz”,用来限制子目录的make顺序。此规则的含义时在处理“foo”目录之前,需要等待“baz”目录处理完成。 18.Makefile的特殊目标 .PHONY:所有的依赖被作为伪目标,当用make 命令行指定此目标时,目标所在的规则定义的命令都会被无条件的执行。 .SUFFIXES : 所有依赖指出了一系列在后缀规则中需要检查的后缀名 .DEFAULT:被用在重建那些没有具体规则的目标 .PRECIOUS:当命令在执行过程中被中断时,make不会删除它们 .INTERMEDIATE:的依赖文件在make时被作为中间过程文件对待。没有任何依赖文件的目标“.INTERMEDIATE”没有意义。 .SECONDARY:的依赖文件被作为中间过程文件对待。但这些文件不会被自动删除 .DELETE_ON>ERROR:如果规则的命令执行错误,将删除已经被修改的目标文件
.IGNORE:指定依赖文件,则忽略创建这个文件所执行命令的错误。给此目标指定命令是没有意义的。当此目标没有依赖文件时,将忽略所有命令执行的错误
.SILENT:的依赖列表中的文件,make在创建这些文件时,不打印出重建此文件所执行的命令。同样,给目标“.SILENT”指定命令行是没有意义的。没有任何依赖文件的目标“.SILENT”告诉make在执行过程中不打印任何执行的命令。
.EXPORT_ALL_VARIABLES:它的功能含义是将之后所有的变量传递给子make进程
.NOTPARALLEL:则所有命令按照串行方式执行
19. 某些情况下,需要对相同的目标使用不同的规则中所定义的命令,这种情况我们可使用另外一种方式“双冒号”规则来实现。
20.:: 对于一个没有依赖而只有命令行的双冒号规则,当引用此目标时,规则的命令将会被无条件执行。当同一个文件作为多个双冒号规则的目标时。这些不同的规则会被独立的处理,而不是像普通规则那样合并所有的依赖到一个目标文件。
21.gcc 支持一个-M的选项来实现自动找寻源文件中包含的头文件,并生成一个依赖关系。
当我们不需要标准库的依赖规则描述时,应该使用-MM则输出的便是我们自己写的.h的头文件
22.$$$$ 表示当前的进程号
23. 在一个规则的命令中,命令行“cd”改变目录不会对其后的命令的执行产生影响。就是说其后的命令执行的工作目录不会是之前使用“cd”进入的那个目录。如果要实现这个目的,就不能把“cd”和其后的命令放在两行来书写。而应该把这两条命令写在一行上,用分号分隔
foo : bar/lose
cd bar; gobble lose > ../foo
25.Make命令运行结束后返回0为正确的执行。返回非0为出错
26.mkdir -p 命令的使用,一次性创建多层次的目录
27.Make的递归调用 $(MAKE) –C subdir
28.CURDIR此变量代表了make当前的工作路径,使用-C选项进入目录后,此变量会被从新赋值
29.上层Makefile中定义的某一个变量需要传递给子make时,应该在上层Makefile中使用指示符“export”对此变量进行声明。
30.在多级递归调用的make执行过程中。变量“MAKELEVEL”代表了调用的深度。
31. 采用define endef 定义命令包。
32.变量定义
= 风格的变量时递归方式扩展的变量。
:= 直接展开式变量
?= 条件赋值操作符,只有变量之前没有赋值的情况下才会对这个变量进行赋值。
$(foo:.o=.c) 变量的替换引用,替换foo变量中所有以.c结尾的文件为.o结尾
+= 追加变量
Override 变量在定义时使用了“override”,则后续对它值进行追加时,也需要使用带有“override”指示符的追加方式。否则对此变量值的追加不会生效。
% 模式变量,单独使用“%”作为目标时,指定的变量会对任何类型的目标文件都有效
33.+之后的命令都需要执行。

GNU MAKE内嵌函数

$(subst FROM,TO,TEXT) 把字串TEXT中的FROM替换为TO,返回替换后的新字串

$(patsubst PATTERN,REPLACEMENT,TEXT) 搜索TEXT中以空格分开的单词,将符合模式TATTERN的替换为REPLACEMENT,返回替换后的新字串
eg:$(patsubst %.c,%.o,x.c c.c bar.c) 把字串x.c c.c bar.c中以.c结尾的单词替换成以.o结尾的字符,返回的结果是:x.o o.o bar.o

$(strip STRINT) 去掉字串STRING开头和结尾的空字符,返回无前导和结尾空字符,使用单一空格分割的多个单词字符串

$(findstring FIND,IN) 搜索字串IN,查找FIND字串,如果在IN中存在FIND则返回FIND,否则返回空。搜索需要时严格的文本匹配

$(filter PATTERN…,TEXT) 过滤掉字串TEXT中所有不符合模式PATTERN的单词,保留所有符合此模式的单词,可以使用多个模式,模式中一般需要包含模式字符%,存在多个模式时,模式表达式之间使用空格分割。返回所有符合模式的字串。

$(filter-out PATTERN…,TEXT) 过滤掉字串TEXT中所有符合模式PATTERN的单词,保留所有不符合此模式的单词,和filter函数相反。返回所有不符合模式的字串。

$(sort LIST) 给字串LIST的单词以首字母为准进行排序(升序),并去掉重复的单词,返回空格分割没有重复的单词。

$(word N,TEXT) 取字串TEXT中第N个单词(N从1开始),返回字串TEXT中第N个单词

$(wordlist S,E,TEXT) 从字串TEXT中取出从S开始到E的单词(S,E表示单词在字串中位置的数字),返回字串TEXT中从第S到E的单词串。(S和E都从1开始,当S比TEXT中的数字大时,返回空。如果E大于TEXT字数,返回从S开始到结尾的单词串,如果S大于E也是返回空)

$(words TEXT) 统计字串TEXT中单词的数目,返回TEXT字串中的单词数。

$(firstword NAMES…) 取字串NAMES…中的第一个单词,返回NAMES…的第一个单词,以空格分割序列

$(dir NAMES) 从文件名序列NAMES中取出各个文件名目录部分,返回空格分割的文件名序列NAMES…中每一个文件的目录部分。

$(notdir NAMES…) 从文件名序列NAMES…中取出非目录部分,返回空格分割的文件名序列NAMES…中每一个文件的非目录部分。

$(suffix NAMES…) 从文件名序列NAMES…中取出各个文件名的后缀,返回以空格分割的文件名序列NAMES…中每一个文件的后缀序列。

$(basename NAMES…) 从文件名序列NAMES…中取出文件名的前缀部分,返回前缀序列,没有前缀则返回空字串

$(addsuffix SUFFIX,NAMES…) 为NAMES中的每一个文件名添加后缀SUFFIX,将SUFFIX加到每一个文件的后面,返回以空格分割的添加了后缀SUFFIX的文件序列

$(addprefix PREFIX,NAMES…) 为NAMES中的每一耳光文件添加前缀PREFIX,返回以空格分割的添加了前缀PREFIX的文件序列。

$(join LIST1,LIST2) 将字串LIST1和字串LIST2各个单词进行对应连接,就是将LIST2中的第一个单词追加到LIST1第一个单词字后合并为一个单词,将LIST2中第二个单词追加到LIST1的第二个单词之后合并为第一个单词,返回单空格分割的合并后的字串序列。

$(wildcard PATTERN) 列出当前目录下所有符合模式PATTERN格式的文件名,返回空格分割的存在当前目录下的所有符合模式PATTERN的文件名

$(foreach VAR,LIST,TEXT) 类似foreach(VAR,LIST){ TEXT }

$(if CONDITION,THEN,ELSE) 第一个参数CONDITTION的展开结果非空,则条件为真,将第二个参数的THEN作为函数的返回值,CONDITION的结果为空,返回ELSE的结果,当不存在第三个参数,且CONDITION为空时,返回空。

$(call VARIABLE,PARAM,PARAM…) call函数是唯一一个可以创建指定参数化的函数引用的函数,在执行时,将它的参数“PARAM”依次赋值给临时变量“$(1)”、“$(2)”(这些临时变量定义在“VARIABLE”的值中,参考下边的例子)…… call函数对参数的数目没有限制,也可以没有参数值,没有参数值的“call”没有任何实际存在的意义。执行时变量“VARIABLE”被展开为在函数上下文有效的临时变量,变量定义中的“$(1)”作为第一个参数,并将函数参数值中的第一个参数赋值给它;变量中的“$(2)”一样被赋值为函数的第二个参数值;依此类推(变量$(0)代表变量“VARIABLE”本身)。之后对变量“VARIABLE” 表达式的计算值。
Ø 返回值:参数值“PARAM”依次替换“$(1)”、“$(2)”…… 之后变量“VARIABLE”定义的表达式的计算值。
示例:
reverse = $(2) $(1)
foo = $(call reverse,a,b)
变量“foo”的值为“ba”。这里变量“reverse”中的参数定义顺序可以根据需要来调整

$(value VARIABLE) 不对变量VARIBLE进行任何展开操作,直接返回变量VARIBALE代表的值。

eval函数
函数功能:函数“eval”是一个比较特殊的函数。使用它我们可以在我们的Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。函数“eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。
返回值:函数“eval”的返回值时空,也可以说没有返回值。
函数说明:“eval”函数执行时会对它的参数进行两次展开。第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。明确这一点对于使用“eval”函数非常重要。在理解了函数“eval”二次展开的过程后。实际使用时,当函数的展开结果中存在引用(格式为:$(x))时,那么在函数的参数中应该使用“$$”来代替“$”。因为这一点,所以通常它的参数中会使用函数“value”来取一个变量的文本值。
我们看一个例子。例子看起来似乎非常复杂,因为它综合了其它的一些概念和函数。不过我们可以考虑两点:其一,通常实际一个模板的定义可能比例子中的更为复杂;其二,我们可以实现一个复杂通用的模板,在我们的所有Makefile中包含它,以可作到一劳永逸。相信这一点可能是大多数程序员所推崇的。
示例:
# sample Makefile
PROGRAMS = server client
server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
# Everything after this is generic
.PHONY: all
all: $(PROGRAMS)
define PROGRAM_template
$(1): $$($(1)_OBJ) $$($(1)_LIBS:%=-l%)
ALL_OBJS += $$($(1)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
rm -f $(ALL_OBJS) $(PROGRAMS)
我们来看一下这个例子:它实现的功能是完成“PROGRAMS”的编译链接。例子中“$(LINK.o)”为“$(CC) $(LDFLAGS)”,意思是对所有的.o文件和指定的库文件进行链接。
“$(foreach prog,$(PROGRAM),$(eval $(call PROGRAM_template,$(prog))))”展开为:
server : $(server_OBJS) –l$(server_LIBS)
client : $(client_OBJS) –l$(client_LIBS)

$(origin VARIABLE) 查询参数VARIABLE的出处,返回VARIABLE的定义方式。
函数的返回情况有以下几种:
1. undefined
变量“VARIABLE”没有被定义。
2. default
变量“VARIABLE”是一个默认定义(内嵌变量)。如“CC”、“MAKE”、“RM”等变量(参考 10.3 隐含变量 一节)。如果在Makefile中重新定义这些变量,函数返回值将相应发生变化。
3. environment
变量“VARIABLE”是一个系统环境变量,并且make没有使用命令行选项“-e”(Makefile中不存在同名的变量定义,此变量没有被替代)。
4. environment override
变量“VARIABLE”是一个系统环境变量,并且make使用了命令行选项“-e”。Makefile中存在一个同名的变量定义,使用“make -e”时环境变量值替代了文件中的变量定义。
5. file
变量“VARIABLE”在某一个makefile文件中定义。
6. command line
变量“VARIABLE”在命令行中定义。
7. override
变量“VARIABLE”在makefile文件中定义并使用“override”指示符声明。
8. automatic
变量“VARIABLE”是自动化变量。

$(shell cat foo) 函数shell实现的功能和shell中用()相同,实现的是命令的扩展,意味着需要一个shell命令作为它的参数,返回的结果是此命令在shell中的执行结果。返回空字符、。

$(error TEXT…) 产生致命错误,并提示TEXT…信息给用户,之后退出make的执行。

$(warning TEXT…) 提示TEXT信息,make的执行过程继续,返回空字符

ubuntu install googlepinyin

转载至:http://www.2cto.com/os/201211/172017.html

安装步骤(需要自己编译):

A. 获取代码:(没有git的先安装git:sudo apt-get install git-core)

$ git clone git://github.com/tchaikov/scim-googlepinyin.git

$ cd scim-googlepinyin

B. 编译前提:

上面给的链接里面有介绍怎么编译的,但少提了几个必需组件,这里列一下:

* autotools-dev

* libgtk2.0-dev

* libscim-dev

* libtool

* automake

用下面命令看看是不是安装了,如果没有,会自动帮你安装上:

$ aptitude install autotools-dev libgtk2.0-dev libscim-dev libtool automake

C. 编译:

记住系统必须先存在SCIM(没有的话 sudo apt-get install scim 一下)

$ ./autogen.sh

$ make

$ sudo make install

现在重启scim:

关闭scim:pkill scim

然后启动: scim -d

OK,去首选项里的“语言支持”的“输入法”选择scim作为默认输入法就OK了。

1 3 4 5 6 7 20