自由

淡泊以明志,宁静以致远。

Shall We Play a Game?

WarGames”是一部 1983 年上映的科幻电影,作为投资仅 1200 万美元的小制作,在当年赢得了近 8000 万的票房。故事发生在美苏冷战时期,那个年代的电影,多多少少都会跟核威慑有关。这两个国家不管谁先发射导弹,那第三次世界大战就会爆发。电影中 NORAD(北美防空司令部)使用了一台叫做 WOPR 的超级计算机进行战事控制,这台计算机特别的地方在于它能自己模拟战争,模拟的过程就像在玩一个游戏(game)。某一天,我们的男主角天才高中生无意中侵入了这台电脑,出于好奇和好玩,启动了核战争游戏。不料这场模拟战争误使 NORAD 以为苏联发动了袭击,一度差点引爆真正的核对抗。最后在男主角和 WOPR 创造者的共同努力下及时终止了这场“战争”。

电影中男主角的人物原型来自一位叫做 David Scott Lewis 的黑客,这位老兄之后一直在搞机器人,后来按照他自己的话来说是“sold my soul to the bigger corporations”,分别在三星、Microsoft 和 Oracle 工作一段时间之后,他来到了中国,跟清华大学合作。现在貌似又搞太阳能去了。WOPR 的创造者 Dr. Stephen Falken 的原型来自著名的物理学家 Steven Hawking(是不是名字也很像?),WarGames 最初的剧本就是根据 Hawking 来写的,曾经还打算塑造一个坐在轮椅上的天体物理学家,但因为太容易让人联想到另一部讲述冷战的电影“Dr. Strangelove”而作罢。其实 Dr. Stephen Falken 对于人工智能的深入研究,倒让我觉得更像是 Alan Turing。

WarGames 对于此后的黑客文化产生了深远的影响。它创造了“firewall”这个词汇(方校长表示感谢)。电影中男主角入侵 NORAD 时使用的技术衍生出了“wardialing”术语。wardialing 是指通过程序不断扫描电话号码来发现计算机 modem,早期的电话黑客即是使用的这种技术。著名的电话黑客(phone phreak)John Draper 因为通过 wardialing 免费打电话而闻名,后来他将这项技术教给了 Steve Jobs 和 Steve Wozniak(是的,没错,就是乔帮主),帮主他们还因此赚了不少钱(帮主果然是个好商人,从小就懂得怎么把技术转为商业利益)。John Draper 后来受雇于 Apple,但这是后话了。wardialing 之后又衍生出了 wardriving,通过扫描和收集 Wi-Fi 热点来进行攻击,之所以叫这个名字,是因为通常是在汽车里一边行驶,一边收集(这样说来 Google 的街景小车也算是 wardriving 了一把)。现在你可以在你的 iPhone 或者 Android 手机里装上一款 wardriving 软件试试看,我曾经试过,但是貌似效果不是很好。

还有一个人“深受”这部电影的影响,Kevin Mitnick,这个计算机安全界传说级的人物。当然不是说 Kevin 同学是因为这部电影走上的不归路,Kevin 同学搞入侵那会儿 WarGames 还没上映呢。Kevin 同学后来入狱时被拒绝接触任何电子设备,包括电话,是因为控诉律师相信他可以通过电话连接到 NORAD。据 Kevin 同学分析 WarGames 这部电影很大程度上使得公众相信这件事情是可以很容易办到的,其实他根本就没有入侵过 NORAD,通过电话来入侵也过于夸张。尽管如此,他还是被判单独监禁,从此传为计算机安全界的一段“佳话”……

游戏界也从 WarGames 获益不少,1984 年同名游戏发布。2006 年一款叫做 DEFCON 的即时战略游戏发布,游戏画面与电影中 NORAD 指挥中心的大屏幕极为相似。DEFCON(defense readiness condition)是美国军方采用的警报等级,在 WarGames 电影中 NORAD 曾因模拟的苏联进攻一度将 DEFCON 等级提升到最高等级 1。著名的黑客大会 DEF CON 的名字也是来源于此。

或许 WarGames 对于电影史并没有太大的贡献,但却深深影响着那一代的 Geek 们。谨以此文献给那些逝去的先驱,RIP

GYP 简介

说起项目构建工具,Linux 用户最熟悉的恐怕就是 Autoconf,它将编译安装这个步骤大大简化。但对于项目作者来说,想要使用 Autoconf 生成有效的配置文件着实需要下一番功夫,用现在流行的话来说就是用户体验不够友好。对 Unix shell 的依赖,也使得 Autoconf 天生对于跨平台支持不佳。

后来我从大猫同学那里听说了 CMake,CMake 使用 C++ 编写,原生支持跨平台,不需要像 Autoconf 那样写一堆的配置文件,只需一个 CMakeLists.txt 文件即可。简洁的使用方式,强大的功能使得我立马对 CMake 情有独钟。在后来的使用过程中,虽然会遇到一些因为使用习惯带来的小困扰,但我对于 CMake 还是基本满意的。直到我发现了 GYP。

GYP(Generate Your Projects)是由 Chromium 团队开发的跨平台自动化项目构建工具,Chromium 便是通过 GYP 进行项目构建管理。为什么我要选择 GYP,而放弃 CMake 呢?功能上 GYP 和 CMake 很是相似,在我看来,它们的最大区别在于配置文件的编写方式和其中蕴含的思想。

编写 CMake 配置文件相比 Autoconf 来说已经简化很多,一个最简单的配置文件只需要写上源文件及生成类型(可执行文件、静态库、动态库等)即可。对分支语句和循环语句的支持也使得 CMake 更加灵活。但是,CMake 最大的问题也是在这个配置文件,请看下面这个示例文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
cmake_minimum_required(VERSION 2.8)
project(VP8 CXX)

add_definitions(-Wall)
cmake_policy(SET CMP0015 NEW)
include_directories("include")
link_directories("lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../lib")
set(VP8SRC VP8Encoder.cpp VP8Decoder.cpp)

if(X86)
    set(CMAKE_SYSTEM_NAME Darwin)
    set(CMAKE_SYSTEM_PROCESSOR i386)
    set(CMAKE_OSX_ARCHITECTURES "i386")

    add_library(vp8 STATIC ${VP8SRC})
elseif(IPHONE)
    if(SIMULATOR)
        set(PLATFORM "iPhoneSimulator")
        set(PROCESSOR i386)
        set(ARCH "i386")
    else()
        set(PLATFORM "iPhoneOS")
        set(PROCESSOR arm)
        set(ARCH "armv7")
    endif()

    set(SDKVER "4.0")
    set(DEVROOT "/Developer/Platforms/${PLATFORM}.platform/Developer")
    set(SDKROOT "${DEVROOT}/SDKs/${PLATFORM}${SDKVER}.sdk")
    set(CMAKE_OSX_SYSROOT "${SDKROOT}")
    set(CMAKE_SYSTEM_NAME Generic)
    set(CMAKE_SYSTEM_PROCESSOR ${PROCESSOR})
    set(CMAKE_CXX_COMPILER "${DEVROOT}/usr/bin/g++")
    set(CMAKE_OSX_ARCHITECTURES ${ARCH})

    include_directories(SYSTEM "${SDKROOT}/usr/include")
    link_directories(SYSTEM "${SDKROOT}/usr/lib")

    add_definitions(-D_PHONE)
    add_library(vp8-armv7-darwin STATIC ${VP8SRC})
endif()

你能一眼看出这个配置文件干了什么吗?其实这个配置文件想要产生的目标(target)只有一个,就是通过 ${VP8SRC} 编译生成的静态库,但因为加上了条件判断,及各种平台相关配置,使得这个配置文件看起来很是复杂。在我看来,编写 CMake 配置文件是一种线性思维,对于同一个目标的配置可能会零散分布在各个地方。而 GYP 则相当不同,GYP 的配置文件更多地强调模块化、结构化。看看下面这个示例文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
  'targets': [
    {
      'target_name': 'foo',
      'type': '<(library)',
      'dependencies': [
        'bar',
      ],
      'defines': [
        'DEFINE_FOO',
        'DEFINE_A_VALUE=value',
      ],
      'include_dirs': [
        '..',
      ],
      'sources': [
        'file1.cc',
        'file2.cc',
      ],
      'conditions': [
        ['OS=="linux"', {
          'defines': [
            'LINUX_DEFINE',
          ],
          'include_dirs': [
            'include/linux',
          ],
        }],
        ['OS=="win"', {
          'defines': [
            'WINDOWS_SPECIFIC_DEFINE',
          ],
        }, { # OS != "win",
          'defines': [
            'NON_WINDOWS_DEFINE',
          ],
        }]
      ],
    }
  ],
}

我们可以立马看出上面这个配置文件的输出目标只有一个,也就是 foo,它是一个库文件(至于是静态的还是动态的这需要在生成项目时指定),它依赖的目标、宏定义、包含的头文件路径、源文件是什么,以及根据不同平台设定的不同配置等。这种定义配置文件的方式相比 CMake 来说,让我觉得更加舒服,也更加清晰,特别是当一个输出目标的配置越来越多时,使用 CMake 来管理可能会愈加混乱。

配置文件的编写方式是我区分 GYP 和 CMake 之间最大的不同点,当然 GYP 也有一些小细节值得注意,比如支持跨平台项目工程文件输出,Windows 平台默认是 Visual Studio,Linux 平台默认是 Makefile,Mac 平台默认是 Xcode,这个功能 CMake 也同样支持,只是缺少了 Xcode。Chromium 团队成员也撰文详细比较了 GYP 和 CMake 之间的优缺点,在开发 GYP 之前,他们也曾试图转到 SCons(这个我没用过,有经验的同学可以比较一下),但是失败了,于是 GYP 就诞生了。

当然 GYP 也不是没有缺点,相反,我觉得它的“缺点”一大堆:

  • 文档不够完整,项目不够正式,某些地方还保留着 Chromium 的影子,看起来像是还没有完全独立出来。
  • 大量的括号嵌套,很容易让人看晕,有过 Lisp 使用经验的同学可以对号入座。对于有括号恐惧症,或者不使用现代编辑器的同学基本可以绕行。
  • 为了支持跨平台,有时不得不加入某些特定平台的配置信息,比如只适用于 Visual Studio 的 RuntimeLibrary 配置,这不利于跨平台配置文件的编写,也无形中增加了编写复杂度。
  • 不支持 make clean,唯一的方法就是将输出目录整个删除或者手动删除其中的某些文件。

如果你已经打算尝试 GYP,那一定记得在生成项目工程文件时加上 --depth 参数,譬如:

$ gyp --depth=. foo.gyp

这也是一个从 Chromium 项目遗留下来的历史问题。

也许你根本用不上跨平台特性,但是 GYP 依然值得尝试。我编写了一份 GYP 配置文件的模板,有兴趣的同学可以参考。GYP 和 CMake 分别代表了两种迥异的“风格”,至于孰优孰劣,还得仁者见仁,智者见智。

Octopress Rocks!

今天开始尝试 Octopress,之前也有耳闻,当时立马被它的 Geek 气息吸引,今天详细了解,Octopress 真不愧为“A blogging framework for hackers.”。我用了多年的 Blogger 博客也终于寿终正寝,如果你是一个非 hacker 博客作者,Blogger 绝对值得推荐(满足 GFW 三定律)。

Another WordPress?

Yes。Octopress 具备一个博客应当具备的所有功能,文章、评论、页面、分享、RSS、搜索、Archives 等等。

No。正如 Octopress 网站介绍所说:A blogging framework for hackers,重点就在最后那个 hackers。没有了 WordPress 的后台界面,写博客需要的工具仅仅是 Ruby、Git、Markdown 和你喜爱的编辑器。如果你是一个 hacker,那你对这些工具不会陌生,相比 WordPress 蹩脚的后台页面,Octopress 提供的写作方式会让你非常喜爱。

写作

博客最重要的功能就是写作,写作就像程序员编写代码,如果不能提供舒服的方式,那简直是一种自虐。事实已经证明 HTML 不是一种好的写作方式,因此 WordPress 这类博客提供了所见即所得编辑器,但对于喜欢精确掌控的 hacker 来说这还不够,于是类似于 Markdown 这样的标记语言逐渐在圈内盛行。这类标记语言最大的好处就是让作者不用关心文章的样式,而专注于文章的内容。这很重要,一篇文章的精髓在于文字,如果过多地被样式困扰,精力便会分散,也必然不会思考出更好的文字。类似的比较还有 Word 和 LaTeX,当然这种观点也是仁者见仁,智者见智。

Octopress 原生为我们提供了 Markdown 支持,需要写一篇新博客了?打开你喜欢的编辑器,使用 Markdown 语法开始书写即可。WordPress?虽然也可以添加 Markdown 支持,但不免显得蹩脚。

语法高亮

这个功能对程序员来说尤为重要,但至今没有博客提供原生支持,这也是最大的遗憾。Octopress 彻底颠覆了这种局面,语法高亮变得如此顺其自然。

rename.pydownload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Batch rename utility. <http://code.google.com/p/princess-alist/>
# Copyright (C) <2011>  xiaogaozi <gaochangjian@gmail.com>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import re
import sys

def usage():
    """Usage"""
    print "Usage: rename.py expr files"

def main():
    """Main progress."""
    if len(sys.argv) < 3:
        usage()
        sys.exit(1)

    expr = sys.argv[1]
    m = re.search(r'^[sy]/([^/]*)/([^/]*)/$', expr)
    if m is None:
        sys.stderr.write("expression incorrect\n")
        sys.exit(1)
    re1 = m.group(1)
    re2 = m.group(2)  # actually in substitute mode this portion is not regular expression

    for oldfile in sys.argv[2:]:
        d = os.path.dirname(oldfile)
        oldname = os.path.basename(oldfile)
        newname = ''
        newfile = ''
        if expr[0] == 's':  # substitute
            newname = re.sub(re1, re2, oldname)
            newfile = os.path.join(d, newname)
            os.rename(oldfile, newfile)
        elif expr[0] == 'y':  # transliterate
            pass
        print oldfile, '->', newfile

if __name__ == "__main__":
    main()

版本控制

程序员已经被版本控制惯坏了,只要能纳入版本库,就统统放进去。WordPress 拥有同样蹩脚的版本控制,显然不足以满足 hacker 的需求,Octopress 为我们提供了 Git 原生支持,一切一切都为你所控,放在你喜欢的版本控制库里即可。

部署

Octopress 为我们提供了三种部署方式:GitHub Pages,Heroku,Rsync,在我看来,其实就两种:免费和收费。GitHub Pages 和 Heroku 都是免费使用,Rsync 则需要你拥有自己的虚拟主机。我选择了 Heroku,毕竟 GitHub Pages 本意是用来放项目介绍页面的,结果被强大的 hacker 们发掘来作为博客了……

Continue?

开始享受写作的乐趣吧~