Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2345235
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类:

2009-10-24 07:25:14

续上.

分析一下要在Vim构建的简单通用IDE的需求:
1. 不需保存文件, 不会因长期频繁操作
2. 不需要写常用include文件, 如studio, iostream, 不需要main函数, 打开后就有一个默认的可编译运行的模板, 该模板的内容由一个磁盘文件定义, 可根据需要自行更改
3. 可利用VC的预编译头文件技术, 提高编译速度.
4. 可以方便地对该系统进行修改以支持新的第三方库, 如boost, 方便使用者对第三方库的试用
5. 运行过程全部在后台, 不允许出现黑乎乎的DOS窗口, 即使是那种一闪而过会自动关闭的, 编译链接运行结果都显示在一个vim的split窗口中.
6. 由快捷键最大可能简化地启动.
7. 目前至少支持VC, dev-cpp(g++), pc-lint 以体现对C++编程的通用支持
8. 为支持特殊情况下需要执行不同的命令行选项, 允许在源代码中以特殊注释的形式自行指定命令行选项.
9. 出于对编译器警告的重视, 默认为VC的w4级警告, 可以通过快捷键F4 在0和4之间切换警告级别, 也可手工指定警告级别, 在源文件中以注释形式出现.
10. 支持用Visual studio调试程序, 有时候决定不做什么和决定做什么一样重要, 调试功能将被外包给Visual Studio.

下面是一些vim或其它工具提供的现成机制支撑对以上功能的实现:
1. Vim的插件机制, Vim脚本放在 $VIM/vimfiles/plugin/ 目录下.
2. VC编译器/链接器的命令行支持,  需要: a)一些目录被添加到PATH环境变量中, b)INCLUDE, LIB两个环境变量分别存放常用的头文件和库文件目录
3. Vim中执行外部程序的能力, 执行非console程序可以避免DOS窗口的出现.
4. 对于VC编译器cl.exe这样不可更改又不可避免的命令行程序, 可以通过3中的非console程序控制其启动过程, 避免DOS窗口的出现, 同时又能捕获其标准输出和标准错误输出.

实现:
1. SnippetCompiler.vim 插件文件, 控制Vim与外部程序的交互, 定义快捷键, 定义用户与这个通用开发环境的功能.
2. VimShell.cs   C#源文件, 一个非console程序, 处理与外部程序如 cl.exe, lint-nt.exe的交互. 编译它的命令是csc /debug+ /t:winexe VimShell.cs,  在该文件中以注释形式存在, C#编译器随.NET framework免费发送.
3. Default.cpp   C++的模板文件, 可以直接编译运行, 输出hello, world
4. my_precompile_header.cpp, FrequentlyUsedHeaders.h   为辅助3而存在. 包含预编译文件的"空"的C++源文件, 目的是产生预编译头文件 pch.
======== 以上文件是预制文件, 需要copy, 或者你手工再作修改 =========
======== 以下文件是中间文件, 使用中自动产生              =========
5. CPP_Snippet.cpp  CPP_Snippet.exe (ilk, obj等),  是把Vim中的让你涂鸦写试验性代码的缓冲区, 在每次要编译时保存到磁盘上的临时文件, cl.exe 程序看到的是这个文件, 因编译器而异, 会产生一些同名的临时文件.  默认生成的exe是支持调试的, 即有相应的PDB文件生成.
6. done.txt  VimShellError.txt  compile_output.txt  pch_compile_out.txt  Vim脚本与外部程序之间并无进程间交互的内置方法, 监控外部程序执行完毕靠的是done.txt 文件的存在性, 获取编译器这样的外部程序的输出结果, 并把结果显示在Vim的缓冲区中, 靠的就是上面这些文件的内容.

7. 一个工作目录, 可以在SnippetCompiler.vim中配置. 用来存放上述过程中产生的临时文件

使用:
1. 安装.NET framework 2.0, 可能VimShell.cs 并不使用2.0的特别功能, 所以1.1应该也能工作, 但我没有尝试, 这个要求有点过分, 毕竟VimShell.cs的功能用一个简单的native EXE也容易实现. 但当时我刚好有过C#与外部进程进行进程间交互的经验, 所以选择了这个.

2. 把 SnippetCompiler.vim 文件copy到 $VIM/vimfiles/plugin 目录下, vimfiles 和 plugin两个目录的名字都是vim内置的, 不要奇怪为什么是这个名字, $VIM 代表一个环境变量, 代表vim的安装路径, 打开 vim, 执行命令 :echo $VIM 可以看到它在哪里.

3. 假设已安装VC, dev-cpp, pc-lint, 打开SnippetCompiler.vim 对这些外部工具进行配置. 其中VC由于体积庞大, 经我的实验, 其实是可以从一台已安装了VC的电脑上通过copy的办法让另一台电脑支持命令行的VC编译链接环境的, 见我的另一篇文字(呃, 我写了吗), 需要配置的部分几乎全是目录名, 文件名. 位于整个脚本的最前面.

" Note: ALL the dir variable has a tailing \ character
let s:working_DIR       = 'E:\work\C_CPP\'
let s:template_cpp      = s:working_DIR . 'Default.cpp'
let s:compile_out       = s:working_DIR . 'compile_output.txt'
let s:pch_compile_out   = s:working_DIR . 'pch_compile_out.txt'
let s:pch_cpp_fname     = s:working_DIR . 'my_precompile_header.cpp'
let s:pch_obj_fname     = s:working_DIR . 'my_precompile_header.obj'
let s:cpp_snippet_fname = s:working_DIR . 'CPP_Snippet.cpp'
let s:exe_snippet_fname = s:working_DIR . 'CPP_Snippet.exe'
let s:exe_pclint_fname  = 'e:\software\case\lint\PC.Lint.v8.00e\lint.bat'
let s:exe_gcc           = 'D:\Dev-Cpp\bin\g++.exe'
let s:pch_fname         = s:working_DIR . 'FrequentlyUsedHeaders.PCH'
let s:pch_header_fname  = s:working_DIR . 'FrequentlyUsedHeaders.h'
let s:shell_done        = s:working_DIR . 'done.txt'
let s:shell_error       = s:working_DIR . 'VimShellError.txt'
let s:my_vim_shell      = $VIM . '\vimfiles\plugin\VimShell.exe'

let s:VS_Install_DIR    = 'D:\Program Files\Microsoft Visual Studio 9.0\'
" boost install dir should be used as $INCLUDE directly, gcc -I"E:\work\boost\boost_1_35_0\" won't work
" but bootst's .H file contains fixed lib hint comment, so must keep \
" as last char, for the gcc case should remove the last \ on-the-way
let s:Boost_root        = 'E:\work\boost\boost_1_35_0\'
let s:Win_SDK_DIR       = 'c:\Program Files\Microsoft SDKs\Windows\v6.0A\'

4. 打开SnippetCompiler的缓冲区, 直接写C/C++代码. 不, 如果是第一次使用, 请先看5
  在vim的任何缓冲区中, 用脚本中定义的快捷键触发:  这会在vim中新打开一个tabpage, 一个未命令的缓冲区专供你C++涂鸦之用, 在同一个vim中同时打开多个这样的涂鸦区.

5. 第一次使用时, 你往往还需要预编译一下头文件, 此后每次你向自己的个人工具箱中新加入一个头文件(头文件能加到工具箱, 是的, 在我看来, C/C++的头文件就是可重用组件/代码/模块的接口和规范, 比如你增加了一项使用boost的技能, 实际上是使用了boost头文件所定义的库, 库应该从功能的角度看作是可复用代码的小仓库, 而不仅限于.lib文件, 库也可表现为头文件), 打开要包含的头文件, 必需从 SnippetCompiler缓冲区中使用 快捷键, 这是个特定于缓冲区的快捷键, 以避免与全局的快捷键冲突. 在这里可以添加上要用的头文件. 下面我提供下载的 FrequentlyUsedHeaders.h 包含了C和C++编程常用的头文件, 以及常用的windows开发头文件, 和boost库的头文件, 没有安装boost库的朋友, 需要把它注释起来.  这个预编译头文件是针对VC的, 虽然g++也支持预编译头文件特性, 我还没有使用经验. 所以对链接阶段库文件(专指.lib)的指定, 也可以使用VC的特殊扩展 pragma 在头文件中声明. 在这个打开的FrequentlyUsedHeaders.h 缓冲区, 把你要使用的头文件添加完之后, 按, 这会打开一个DOS窗口来生成预编译的头文件. 等等, 我不是在前面承诺不产生DOS窗口吗, 是的, 但那是指你频繁使用的C++涂鸦缓冲区的操作, 对预编译文件的生成, 当然也可以做到这一点, 不过我在调试的时候, 更希望看到实际的命令行在运行, 更重要的原因是重新生成pch文件并不是一个经常需要进行的操作. 所以这里生成的DOS窗口并不会产生困扰. 关于VC编译器对预编译头文件的使用, 多少有一些细节让人费解, 不过配置使用这套东西并不需要对此很通达, 知道其概念和应用即可.

6. 回到步骤4, 编写你的C++程序, 按用VC来编译运行, 按用dev-cpp(g++)编译运行, 按用pc-lint来静态检查你的程序, 所以这些操作都需要先把涂鸦区的内容保存到 CPP_Snippet.cpp 源文件中一次, 特别说明一下涂鸦区中的默认内容:
6.1) pc-lint特殊注释, pc-lint 会理解下面的第一行注释, pc-lint配置起来不简单, 这里不介绍

/*lint +e* -elib(*) -e966 -e964 -e755 -e757 -e970 */
#include "FrequentlyUsedHeaders.h"
// The following lines makes it possible that only /Yu is specified on the
// command line

// Remove #ifdef ... #endif   because VC will stop to compile, don't
// know why
#pragma hdrstop( "FrequentlyUsedHeaders.pch" )

6.2) VC调试支持特殊注释(参考下面的7)
// DEBUG: Un-comment the following line to debug the program.
// ERR_MSG_BOX("Attach me to a debugger and then click OK");

6.3) 切换W0, W4警告级别, 这个也是专门针对VC, g++的支持更多的警告级别
#ifdef _MSC_VER
// Press F4 to switch the warning /W4 and /W0
#pragma warning(push, 2)
#endif

6.4) 看似无用的语句
argc = argc;
argv = argv;

这是为了避免一个参数未被使用的警告. 无害

6.5) 标准输出控制
// The following lines make the output to stdout and stderr are
// line-buffered, i.e., when a "\n" is encountered, the output is
// flushed
setvbuf( stdout, NULL, _IONBF, 0);
setvbuf( stderr, NULL, _IONBF, 0);
注释里都说明了.

6.6) 你要写的东西, 从这里开始
前面说的那些东西, 意思无非是, 你不要用, 它们都别有用意, 你要写的代码从下面的一行输出Hello, world开始:
//
// Begin your code here
// 
printf("Hello, world\n");

6.7) 不支持 Press any key to continue..., 是的, 在这个框架中, 实现这个可不容易, 事实上我根本没有想法怎么去做, 所有的等待着键盘输入的库调, 如getchar, scanf 都无效.

6.8) 支持GUI程序吗, 是的, 没有限制一个console程序(CPP_Snippet.exe被编译成console程序)不能显示一个窗口, 但我怀疑在一个Snippet compiler里这么做的价值, 正如我认为那些从键盘获取输入并不常用一样.

7. 调试(限VC)
如果你在用涂鸦区试验一个库函数的特性, 一些文档中没有提及的细节让你困惑, 可能还是会需要调试, 那么打开6.2中提到的那一行注释, 这会在程序运行时弹出一个模式对话框, 让你有机会在VS IDE中打开 CPP_Snippet.cpp 源文件(是的, 可以独立于任何项目, 打开一个单个的源代码文件进行调试, 记得我说过产生的pdb文件?), 设置断点之后, 然后点击那个模式对话框, 会在断点处停住.

8. 在Vim中退出一个未命令缓冲区会略有阻力, 这是Vim有意的设计, 目的是避免你丢失重要的工作, 当你要退出涂鸦窗口时, 可以用ZQ 命令, 这是normal模式命令, 注意是大写, 所以你需要同时按住SHIFT键, 不过这通常用一只左手就能搞定, 但是, 由于一个tabpage里面有两个打开的窗口(一个是命令输出窗口), 所以这个命令要重复执行两遍.

文件:SnippetCompiler.rar
大小:8KB
下载:下载
阅读(2644) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~