逛论坛看到一个帖子:linux下对C语言文件进行批量编译 。其实用makefile或者shell等脚本很简单, 大概发帖之人并不知道有Makefile这个东西。既然要求用c语言,那就用c吧。思想都是一样的。都是要在程序中调用外部命令。所以肯定要用到linux标准库下面的execl,execle,execv,execve,execvp等函数。这些命令都可以执行命令,同时传递参数。拿其中的execv来说,先看函数声明:
int execv (const char * path, char * const argv[ ]);
这里execv()用来执行参数path字符串所代表的文件路径。第二个参数利用数组指针来传递给执行文件。如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
我们可以这样使用:
char* cmd_argv[] = {"gcc","-o","output","source.c",(char *)0};
execv("/usr/bin/gcc", cmd_argv)
同时,要注意函数的返回值。如果函数成功不会返回,意思是说程序执行成功这个函数后,并不会回到主程序中继续执行,所以execv后来的程序是不会执行的。
刚开始我的想法就是一个简单的循环调用execv,就可以完成编译某个指定目录下的所有源文件。结果执行一次execv之后,程序就正常退出了。没办法只能调用 fork生成子进程,父进程控制流程,生成的子进程每次完成一次execv。这样程序就搞定了。
附上源码,备用
#include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <stdio.h> #include <signal.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <dirent.h>
int main(int argc, char *argv[]) { DIR *dp; pid_t pid; int status=0; struct dirent *dirp; char name[100][100]; char buf[80]; int i=0; int file_num, result;
char* cmd_argv[] = {"gcc","-o","exec_file","source_file",(char *)0}; const char exec_file_type[] = ".out";
if (NULL == (dp=opendir(argv[1]))) { fprintf(stderr, "Can' open %s directiory\n",argv[1], strerror(errno)); exit(-1); }
while ( NULL != (dirp = readdir(dp))) { const char *p = dirp->d_name; for (; *p && *p != '.'; ++p);
if (0 == strcmp(p, ".c")) { //printf("File name: %s\n", dirp->d_name); strcpy(name[i++], dirp->d_name); } } file_num = i; closedir(dp);
// enter into working directory
chdir(argv[1]); getcwd(buf, sizeof(buf)); printf("Current working directory is %s\n", buf); printf("total %d source files\n\n", file_num);
// Begin to work
for (i=0; i<file_num; i++) { printf("start compile %s\n", name[i]); // set output filename
int len = strlen(name[i]) + sizeof(exec_file_type) + 1; char* temp = malloc( len * sizeof(char)); strcpy(temp, name[i]); cmd_argv[2] = strcat(temp, exec_file_type); // set input filename
cmd_argv[3] = name[i];
pid = fork(); if (pid < 0) { printf("fork failed, try again\n"); exit(1); } else if (pid == 0) { // This is child process //printf("This is child process : %d\n", getpid()); if ( (result=execv("/usr/bin/gcc", cmd_argv)) == -1 ) { printf("compile %s failed\n", name[i]); printf("error: %d\n", errno); } } else { // This is parent process, wait for child process finish.
pid = wait(&status); //printf("child's pid = %d\texit status=%d\n",pid,status);
printf("finish compile %s\n\n", name[i]); if(temp != NULL) free(temp); } }
return 0; }
|
编译,运行结果如下:
e390977@ch71DT4nwhz1x /home/ray/c++/make $gcc -o my_make my_make.c
e390977@ch71DT4nwhz1x /home/ray/c++/make $./my_make.exe test/ Current working directory is /home/ray/c++/make/test total 2 source files
start compile calnumber.c finish compile calnumber.c
start compile my_make.c finish compile my_make.c
e390977@ch71DT4nwhz1x /home/ray/c++/make $ll test/ total 28K -rw-r--r-- 1 e390977 ???????? 291 May 26 13:58 calnumber.c -rwxr-xr-x 1 e390977 mkgroup-l-d 9.2K Jun 5 13:16 calnumber.c.out* -rw-r--r-- 1 e390977 mkgroup-l-d 2.6K Jun 5 13:10 my_make.c -rwxr-xr-x 1 e390977 mkgroup-l-d 14K Jun 5 13:16 my_make.c.out*
e390977@ch71DT4nwhz1x /home/ray/c++/make $file test/* test/calnumber.c: ASCII C program text test/calnumber.c.out: MS-DOS executable PE for MS Windows (console) Intel 80386 32-bit test/my_make.c: ASCII C program text, with CRLF line terminators test/my_make.c.out: MS-DOS executable PE for MS Windows (console) Intel 80386 32-bit
|
阅读(2817) | 评论(0) | 转发(0) |