Chinaunix首页 | 论坛 | 博客
  • 博客访问: 450619
  • 博文数量: 45
  • 博客积分: 2526
  • 博客等级: 少校
  • 技术积分: 478
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-12 21:04
文章分类

全部博文(45)

文章存档

2014年(1)

2011年(1)

2010年(3)

2009年(22)

2008年(18)

我的朋友

分类: C/C++

2008-06-05 13:46:37

逛论坛看到一个帖子: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

阅读(2763) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~