您的位置:首页 > 运维架构 > Linux

分享实用工具源码--实现Windows IDE中查看Linux下编译信息

2014-10-30 22:47 645 查看
作者:fbysss 

msn:jameslastchina@hotmail.com
blog:blog.csdn.net/fbysss 

声明:本文由fbysss原创,转载请注明出处

关键字: 实用工具源码  Windows下查看Linux编译信息
一、背景:本人写C程序不多,更不用说Linux下了。偶然一个机会,接了个这样的活,vi我用的还马马虎虎,但程序超过一千行,看起来就有些眼花了。于是只好在VC下编写代码,ftp传到Linux服务器,再用gcc编译,出错了再到VC下修改,再上传,如此这般,颇为费劲。Linux图形界面下安装一个C的开发工具?还是算了,我的Linux是虚拟机,在本机上使用Shell我都用的SecureCRT,就是不想切换来切换去。那有什么方式能更自动化一点呢?似乎没有比较贴心的方案,犹豫再三,花了一个下午写了这个工具,完全满足了自己的要求。在此分享给大家,希望对读者有所帮助。
二、设计思路:在Linux下运行一个守护进程,Windows下提供一个客户端供IDE调用,传递gcc命令行、文件名、文件内容(最开始考虑用ftp,后来一不做二不休,想让一切更简单些,索性把文件内容也通过Socket传过去了。)
三、源代码:

1.Linux下守护程序compileDaemon.c


#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/wait.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/time.h>

#include <sys/types.h>

#include <netdb.h>

#include <pthread.h>

#include <sys/stat.h>

/*******************************************************

文件名:compileDaemon.c

功能:Windows下查看Linux下编译信息--Linux下编译守护程序

编写人:fbysss

blog:blog.csdn.net/fbysss

email:jameslastchina@hotmail.com

********************************************************/

#define SPLIT  "###SPLIT###"

#define BUFLEN 1024*128

#define THREAD_NUM 1

pthread_mutex_t sock_mutex;

pthread_cond_t sock_cond;

#define MAXSIZE 512

#define resultFile "compile.log"

/**

所需参数:shellCommand,由client传递

包括gcc +参数  里面包含c源程序和目标文件名

*/

/********处理每个连接*******/

void * dealEachConn(void * arg)

{ char buf[MAXSIZE];

 char recvBuf[BUFLEN];

 //int filesize;//实际上没有使用。

 FILE * fdSrcFile;

 char cmdLine[MAXSIZE]={0};

 int len;

 

 char * recvBufHead;

 char * recvBufP;

 char  filepath[256];

 char compileStr[1024]={0}; 

 struct stat file_stat;

 int each_conn_fd=(int) arg; 

 len = recv(each_conn_fd, recvBuf, BUFLEN, 0);

 if (len < 0)

 {

  perror("nothing recieved.");

  return;

 }

 recvBufHead = recvBuf;

 recvBufP = recvBuf; 

 sprintf(cmdLine,"%s",recvBufP);

 recvBufP+=strlen(cmdLine);

 recvBufP++;//字符串结束符

 recvBufP+=strlen(SPLIT);

 //得到文件名

 sprintf(filepath,"%s",recvBufP);

 printf("filepath :%s/n",filepath);

 recvBufP+=strlen(filepath);

 recvBufP++;//字符串结束符

 recvBufP+=strlen(SPLIT); 

 

 //写文件

 fdSrcFile = fopen(filepath,"w");

 fwrite(recvBufP,len-(recvBufP-recvBufHead)-1,1,fdSrcFile);

 fclose(fdSrcFile);

 printf("file total %d bytes writed,/n",len-(recvBufP-recvBufHead));

 //组装命令行

 strcat(cmdLine," 2>&1|tee ");

 strcat(cmdLine,resultFile);

 printf("commandLine is:%s/n",cmdLine);

 system(cmdLine);

 FILE * fd = fopen(resultFile,"r");

 while(fgets(buf, MAXSIZE, fd)!=NULL)

 {

  strcat(compileStr,buf);

 }

 printf("compileStr is:%s/n",compileStr);

 int rtValue = send(each_conn_fd, compileStr, strlen(compileStr), 0);

 fclose(fd);

 close(each_conn_fd);

}

//启动一个线程

void startThreadPro(void * proc,void *arg)

{

 /* initialize */

    pthread_t* arr_pid = (pthread_t*)malloc(sizeof(pthread_t) * THREAD_NUM);

    pthread_mutex_init(&sock_mutex, NULL);

    pthread_cond_init(&sock_cond, NULL);

 printf("create thread a proc .../n");

 pthread_create(&arr_pid, NULL, proc, arg);

}

/**************************主程序*******************************/

int main(int argc, char **argv)

{

    int each_conn_fd;

 int sockfd;

    socklen_t len;

    struct sockaddr_in my_addr, their_addr;

    unsigned int myport, lisnum;

 /*****************************************初始化*****************************************/

    if (argv[1])

        myport = atoi(argv[1]);

    else

        myport = 4444;

    if (argv[2])

        lisnum = atoi(argv[2]);

    else

        lisnum = 2;

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {

        perror("socket");

        exit(1);

    }

    bzero(&my_addr, sizeof(my_addr));

    my_addr.sin_family = PF_INET;

    my_addr.sin_port = htons(myport);

    if (argv[3])//第三个参数为ip地址,指定绑定到哪个ip地址上。

        my_addr.sin_addr.s_addr = inet_addr(argv[3]);

    else

        my_addr.sin_addr.s_addr = INADDR_ANY;

/*******************************端口绑定bind**************************************************/

    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))

        == -1) {

        perror("bind");

        exit(1);

    }

/***********************************侦听*****************************************************/

    if (listen(sockfd, lisnum) == -1) {

        perror("listen");

        exit(1);

    }

    while (1) {//while 1   //循环侦测客户端连接          

        len = sizeof(struct sockaddr);

        if ((each_conn_fd =

             accept(sockfd, (struct sockaddr *) &their_addr,//通过accept能够取得跟服务器连接的客户机地址their_addr,返回new_fd

                    &len)) == -1) {

   if (errno == EINTR){//避免信号对accept的影响 

    continue;

   }

            perror("accept");

            exit(errno);

        } else

  {

            printf("server: got connection from ip:%s, port: %d, socketfd: %d/n",

                   inet_ntoa(their_addr.sin_addr),

                   ntohs(their_addr.sin_port), each_conn_fd);

   

  }

  /* 开始处理每个新连接上的数据收发 */

 startThreadPro(dealEachConn,(void*)each_conn_fd);

    }//end while

 printf("start to close main socket.../n");

    close(sockfd);

    return 0;

}
2.Windows下客户端程序compileClient.c

#include "winsock.h"

#include "stdio.h"

/*******************************************************

文件名:compileClient.c

功能:Windows下查看Linux下编译信息--Windows 客户端

编写人:fbysss

blog:blog.csdn.net/fbysss

email:jameslastchina@hotmail.com

********************************************************/

#define BUFLEN 1024*128//这里一定要足够大。考虑到能够传送一般的c文件

#define LENGTH128 128

#define SPLIT  "###SPLIT###"

#define resultFile "compile.log"

void SocketError(char * call)

{

    fprintf(stderr," WinSock Error# function: %s, error code:%ld/n",call,WSAGetLastError());

}

/**

argv[1]:server ip

argv[2]:server port

argv[3]:send command

argv[4]:send file dir

argv[5]:send filename

*/

main(int argc,char ** argv)

{

    int index;

 int iRes,iPort,iTmp;

 char * rt;

    SOCKET sockfd;

    SOCKADDR_IN sin;

    WSADATA wsad;

    WORD wVersionReq;

 FILE * fp;

 FILE * fdSrcFile ;

 int sendLen;

    char sendBuf[BUFLEN]={0};

    char recvBuf[BUFLEN]={0};

 char * sdBufHead = sendBuf;

 char * sdBufferP = sendBuf;

 char filename[LENGTH128];

 char buf[LENGTH128]={0};

  if(argc<5)

  {

   fprintf(stderr,"Usage:winLinuxGcc <host> <port> <commandStr> <dir> <filename>/n");

   return -1;

  }

  if(inet_addr(argv[1])==INADDR_NONE)

  {

   fprintf(stderr,"Wrong ip :/n");

   return -1;

  }

  iPort=0;

  iPort=atoi(argv[2]);

  sin.sin_addr.s_addr=inet_addr(argv[1]);

  sin.sin_family=PF_INET;

  sin.sin_port=htons(iPort);

  if(iPort<=0)

  {

   fprintf(stderr,"must specify a number for port/n");

   return -1;

  }

  wVersionReq=MAKEWORD(1,1);

  iRes=WSAStartup(wVersionReq,&wsad);

  if(iRes!=0)

  {

   SocketError("WSAStartup()");

   return -1;

  }

   sockfd=socket(PF_INET,SOCK_STREAM,0);

  if(sockfd==INVALID_SOCKET)

  {

   SocketError("socket()");

   return -1;

  }

  iTmp=sizeof(sin);

  fprintf(stderr,"WinSock Client Start....../n");

  if(connect(sockfd,(LPSOCKADDR)&sin,iTmp)==SOCKET_ERROR)

  {

   SocketError("connect()");

   closesocket(sockfd);

   WSACleanup();

   return -1;

  }

  //printf("debug1/n");

  strcpy(sdBufferP,argv[3]);//命令行

  //写分隔符

  sdBufferP+=strlen(argv[3]); 

  sdBufferP++;//字符串结束符

  memcpy(sdBufferP,SPLIT,strlen(SPLIT));

  sdBufferP+=strlen(SPLIT);

  //写文件名

  memcpy(sdBufferP,argv[5],strlen(argv[5]));

  sdBufferP+=strlen(argv[5]);

  //写分隔符

  sdBufferP++;  

  memcpy(sdBufferP,SPLIT,strlen(SPLIT));

  sdBufferP+=strlen(SPLIT);

  //写文件内容

  strcpy(filename,argv[4]);

  strcat(filename,"//");

  strcat(filename,argv[5]);

  printf("debug:filename is:%s/n",filename);

  fdSrcFile = fopen(filename,"r");

  if(fdSrcFile<0)

  {

   perror("open file error:");

  }

  rt="1";

  index = 0;

  while(rt!=NULL)

  //while(rt!=NULL)

  { memset(buf,0,LENGTH128);

   index ++;

   rt=fgets(buf, LENGTH128, fdSrcFile);   

   memcpy(sdBufferP,buf,strlen(buf));    

   sdBufferP+=strlen(buf);

   

  }

  sendLen = sdBufferP - sdBufHead;//计算发包长度

  iRes=send(sockfd,sendBuf,sendLen,0);

  if(iRes==SOCKET_ERROR)

  {

   SocketError("send()");

   closesocket(sockfd);

   WSACleanup();

   return -1;

  }

  fp =fopen(resultFile,"a+b");

  if(fp==NULL)

   return -1;

  //读取返回的编译信息

  iRes=recv(sockfd,recvBuf,BUFLEN,0);

  while(iRes!=SOCKET_ERROR&&iRes!=0)

  {

   printf("Received %d bytes,Data:/n------------------/n%s/n------------------/n",iRes,recvBuf);

   fwrite(recvBuf,sizeof(char),iRes,fp);//写日志文件

   iRes=recv(sockfd,recvBuf,BUFLEN,0);

  }

  fclose(fp);

  closesocket(sockfd);

  WSACleanup();

  return 0;

}

四.编译运行守护程序


上传compileDaemon到Linux;

在Linux shell下,运行gcc -o compileDaemon compileDaemon.c编译程序;

再输入./compileDaemon 4444 1,运行成功,进入守护监听状态。

五.客户端与VC集成配置

首先建立一个工程,winLinuxGcc,加入文件compileClient.c,build之后,生成winLinuxGcc.exe。

tools->customize..-tools,添加Menu Contents,输入LinuxGCC,command输入winLinuxGcc.exe,Arguments输入<host>
<port> "gcc -o ttt $(FileName)$(FileExt)" $(FileDir) $(FileName)$(FileExt)  (注意:<host> <port>请根据实际情况进行修改),并选中Use Output Window






任意打开一个需要在Linux下编译的程序,点击菜单tools,可以看到增加了一个菜单项“LinuxGcc”,点击该菜单,即可可以看到IDE下方输出窗口中的编译信息。



 
六、结束语:

本程序是针对GCC编写的, 客户端的第三个参数可以根据实际情况进行灵活配置。可以完全把Linux命令行格式放置到客户端,这样,不仅仅是gcc,其他编译器也可以适用(服务端稍作改动即可)。

另外,除了VC,Editplus、UtraEdit以及其他可加入扩展命令的IDE同样适用本工具。进一步,不仅仅是C语言,其他语言,同样可以采用本工具来达到类似效果。

局限性:本工具的编写主要是出于“背景”所述原因,满足的需求有限,并不能完成真正意义的交互调试,我不过是抛砖引玉,希望这样的尝试,能给大家带来更多启示,如果有人能把gdb的交互调试也在vc下实现了,那必定很酷。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IDE linux