VELT的全称是Visual EmbedLinuxTools,它是一个visual studio插件,用以辅助完成Linux开发。利用这个插件,将可以在visual studio的IDE中进行Linux应用程序的开发(包括编译和调试),也可以进行uboot和linux内核的编译,并根据编译时的错误信息正确定位到源码。目前的版本是0.1.4,仅支持vs2013。此插件可以在CSDN下载频道下载(http://download.csdn.net/detail/lights_joy/8429771),安装过程参见《用vs2013+velt-0.1.4进行嵌入式开发:插件安装》。下面是它的基本功能:
- 支持x86 Linux,海思hi3516/hi3520,MinGW这几个平台,提供这几个平台的项目模板。
- 完成UBOOT的编译,并根据编译的错误信息自动定位到相应的文件位置。
- 完成LINUX内核的编译,并根据编译的错误信息自动定位到相应的文件位置。
- 在VS下完成Linux内核的配置。
- 不使用Makefile进行Linux应用程序的编译。
- 使用Makefile进行Linux应用程序的开发。
- 使用SSH连接目标机器并用gdb进行应用程序的调试。
- 使用Telnet连接目标机器并用gdb进行应用程序的调试。
- 在VS中集成Linux终端(Poderosa),支持SSH/Telnet/Com,在打开终端时自动将VS的变量导出为bash里的变量,如ProjectDir等。
开始时并不打算在VS2013下编译gdb,只是在MINGW下编译gdb-7.8.2总有问题,再加上对调试技术的学习无论如何绕不过gdb,因而决定在vs2013下将gdb重新编译一遍。
编译的基本过程为:
首先在linux编译gdb,让其生成一些动态生成的文件如config.h,init.c等,这些文件是在configure时生成的。接着从main函数开始,根据链接错误逐步加入所需要的文件,而不是一次把所有文件都添加到工程中,因为有许多文件是不需要的。在添加过程中进行一些简单语法差异的修改。
下面列出几个主要的修改:
- include_next
在gdb的头文件中使用了
#include_next <wctype.h>
这样的包含语句,处理方式是将头文件改名,再用VS支持的include包含。
- config.h
这个配置文件是动态生成的,定义了开发环境的一些特性,这个需要根据VS的支持进行修改,也是改动最大的。
- 特定变量
gdb中有一些特定的变量, 如
char small;
而small在vs下是一个宏定义:
#define small char
因而直接将变量改名即可,类似的还有class,INT等。
- 动态数组定义
类似于这样的
unsigned int size = sizeof(CV_INFO_PDB70) + 1;
CV_INFO_PDB70 *cvinfo70;
char buffer[size];
修改为:
char *buffer =(char*)_alloca(size);
- 宏定义
gcc下的定义:
#define DEBUG(msg, args...) \
do \
{ \
if (record_debug != 0) \
fprintf_unfiltered(gdb_stdlog, \
"[btrace] " msg "\n",##args); \
vs下的定义:
#define DEBUG(msg,...) \
do \
{ \
if (record_debug!= 0) \
fprintf_unfiltered (gdb_stdlog, \
"[btrace]" msg"\n",__VA_ARGS__); \
- 结构体初始化
gcc:
const struct cplus_struct_type cplus_struct_default = { };
vs:
const struct cplus_struct_type cplus_struct_default = {0 };
- init.c
这个文件是动态生成的,根据不同的配置自动加上需要的初始化函数,需要根据实际情况进行修改,如默认情况下gdb是支持tui的,但tui需要curses库,而这个库是不支持vs的,因此只能去除其中的tui初始化模块。
- 文件打开方式
在fopen_same.h中定义了打开文件时使用的方式:
#define FOPEN_RB "r"
#define FOPEN_WB "w"
#define FOPEN_AB "a"
#define FOPEN_RUB "r+"
#define FOPEN_WUB "w+"
#define FOPEN_AUB "a+"
在VS下必须为:
#define FOPEN_RB "rb"
#define FOPEN_WB "wb"
#define FOPEN_AB "ab"
#define FOPEN_RUB "r+b"
#define FOPEN_WUB "w+b"
#define FOPEN_AUB "a+b"
否则将无法进行文件的分析
- readdir相关函数
在VS下没有此函数,直接找一个别人实现的代码:
// dirent.c
#include <stdio.h>
#include <windows.h>
#include "dirent.h"
static HANDLE hFind;
DIR *opendir(const char *name)
{
DIR *dir;
WIN32_FIND_DATAFindData;
char namebuf[512];
sprintf(namebuf,"%s\\*.*", name);
hFind =FindFirstFile(namebuf, &FindData);
if (hFind ==INVALID_HANDLE_VALUE)
{
printf("FindFirstFilefailed (%d)\n", GetLastError());
return 0;
}
dir = (DIR*)malloc(sizeof(DIR));
if (!dir)
{
printf("DIRmemory allocate fail\n");
return 0;
}
memset(dir, 0,sizeof(DIR));
dir->dd_fd =0; // simulate return
return dir;
}
struct dirent *readdir(DIR *d)
{
int i;
static struct direntdirent;
BOOL bf;
WIN32_FIND_DATAFileData;
if (!d)
{
return 0;
}
bf =FindNextFile(hFind, &FileData);
//fail or end
if (!bf)
{
return 0;
}
for (i = 0; i <256; i++)
{
dirent.d_name[i]= FileData.cFileName[i];
if(FileData.cFileName[i] == ‘\0‘) break;
}
dirent.d_reclen = i;
dirent.d_reclen =FileData.nFileSizeLow;
//check there is fileor directory
if(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
dirent.d_type= 2;
}
else
{
dirent.d_type= 1;
}
return (&dirent);
}
int closedir(DIR *d)
{
if (!d) return -1;
hFind = 0;
free(d);
return 0;
}
- input.c
这个文件需要定义__MINGW32__宏,才能正确地接受键盘输入。
从上面可以看出,其实所需要的修改并不多,不是吗?
??