遍历Android makefile文件

/***********************************************
 * List Android modules according to Android.mk
 * 2015, all rights reserved.
 ***********************************************/
#include <ctype.h>
#include <dirent.h>
#include <getopt.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define MKFILE_1    "Android.mk"
#define MKFILE_2    "NativeCode.mk"

#define SM_START    "CLEAR_VARS"

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#endif

typedef struct match_table {
    const char *match_string;
    const char *log_file;
    char cli_arg[64];
} match_table;

struct match_table match_tables[] = {
    {"BUILD_PREBUILT", "./oem_modules/prebuilt.txt", {0}},
    {"BUILD_SHARED_LIBRARY", "./oem_modules/shared.txt", {0}},
    {"BUILD_STATIC_LIBRARY", "./oem_modules/static.txt", {0}},
    {"BUILD_EXECUTABLE", "./oem_modules/binary.txt", {0}},
    {"BUILD_JAVA_LIBRARY", "./oem_modules/jar.txt", {0}},
    {"BUILD_PACKAGE", "./oem_modules/app.txt", {0}},
    {"BUILD_HOST_SHARED_LIBRARY", "./oem_modules/host_jar.txt", {0}},
};

static char proc_name_arg[64];

static int droid_mk_count = 0;
static int nativecode_mk_count = 0;

static int my_printf(const char *fmt, ...)
{
    va_list arg;
    char buf[1024];
    FILE *fp;
    int rc;

    va_start(arg, fmt);
    rc = vsnprintf(buf, 1023, fmt, arg);
    va_end(arg);

    printf("%s", buf);
    return rc;
}

static void print_usage(void)
{
    const char *usage =
        "Usage: %s [OPTION...]\n"
        "    -p, --prebuilt=PREBUILT_NAME\tlist prebuilt makefile path\n"
        "    -d, --so=SHARED_NAME\t\tlist shared makefile path\n"
        "    -s, --static=STATIC_NAME\t\tlist static makefile path\n"
        "    -b, --bin=BINARY\t\t\tlist binary makefile path\n"
        "    -j, --jar=JAR_NAME\t\t\tlist jar makefile path\n"
        "    -a, --apk=APP_NAME\t\t\tlist apk makefile path\n"
        "    -r, --jar_host=HOST_JAR_NAME\tlist jar host makefile path\n"
        "    -h, --help\t\t\t\tprint the usage\n\n"
        "HOW-TO:\n"
        "Copy this command to the Android source code "
        "directory which includes the Android.mk, such as "
        "<system/core>\n\n"
        "For example:\n"
        "    ./%s\n"
        "    ./%s  -b diag_uart_log\n\n";

    my_printf(usage, proc_name_arg, proc_name_arg, proc_name_arg);
}

static void write_file_string(const char *log_file, const char *str)
{
    FILE *fp;

    fp = fopen(log_file, "a+");
    if (fp) {
        fputs(str, fp);
        fclose(fp);
    }
}

static bool is_local_module(char *s)
{
    char *ptr;
    char *tmp;

    if (strstr(s, "LOCAL_PACKAGE_NAME")) {
        return true;
    }

    tmp = s;
    while (isspace(*tmp)) tmp++;
    if (strstr(tmp, "LOCAL_MODULE")) {
        ptr = tmp + strlen("LOCAL_MODULE");
        while(isspace(*ptr)) ptr++;
        if ((*ptr == ':') ||
                (*ptr == '=')) {
            return true;
        }
        return false;
    }
    return false;
}

static void save_module_name(char *mkfile_with_path, char *module_name,
        match_table *mt, bool *manual_check)
{
    char buf[256];

    write_file_string(mt->log_file, module_name);

    if (strlen(mt->cli_arg) > 1) {
        snprintf(buf, 255, "%s\n", mkfile_with_path);

        if (!strncmp(mt->cli_arg, "all", 3)) {
            write_file_string(mt->log_file, buf);
        } else if (!strncmp(module_name, mt->cli_arg, strlen(mt->cli_arg))) {
            write_file_string(mt->log_file, buf);
        }
    }

    if (*manual_check) {
        *manual_check = false;
        snprintf(buf, 255,
                "###check this [%s] manually###\n", mkfile_with_path);
        write_file_string(mt->log_file, buf);
    }
}

static void get_all_module_names(char *mkfile_with_path)
{
    FILE *fp;
    int i;
    char buf[256];
    char module_name[256];
    char *ptr;
    bool pattern_match = false;
    bool manual_check = false;

    fp = fopen(mkfile_with_path, "r");
    if (fp) {
        while (fgets(buf, 255, fp)) {
            if (strstr(buf, SM_START)) {
                pattern_match = false;
                manual_check = false;
            }

            if (!pattern_match) {
                if (is_local_module(buf)) {
                    ptr = strchr(buf, '=');
                    ptr++;
                    while (isspace(*ptr)) ptr++;

                    snprintf(module_name, 255, "%s", ptr);
                    if (strchr(module_name, '$')) {
                        manual_check = true;
                    }
                    pattern_match = true;
                }
            } else if (pattern_match) {
                for (i = 0; i < ARRAY_SIZE(match_tables); i++) {
                    if (strstr(buf, match_tables[i].match_string)) {
                        pattern_match = false;

                        save_module_name(mkfile_with_path,
                                module_name, &match_tables[i], &manual_check);
                    }
                } /* end of for_loop */
            } /* end of else_if */
        } /* end of  while */
        fclose(fp);
    } /* end of if (fp) */
}

static void list_modules(char *scanned_dir)
{
    DIR *d;
    struct dirent *de;
    char buf[256];

    d = opendir(scanned_dir);
    if (d) {
        while (NULL != (de = readdir(d))) {
            if (de->d_name[0] == '.') {
                continue;
            }

            snprintf(buf, 255, "%s/%s", scanned_dir, de->d_name);
            if (de->d_type == DT_DIR) {
                list_modules(buf);
            } else if(!strncmp(de->d_name, MKFILE_1, strlen(MKFILE_1)) ||
                    !strncmp(de->d_name, MKFILE_2, strlen(MKFILE_2))) {
                if (!strcasecmp(de->d_name, MKFILE_1)) {
                    droid_mk_count++;
                } else {
                    nativecode_mk_count++;
                }

                my_printf("%s: %d found, "
                        "%s: %d found\r",
                        MKFILE_1, droid_mk_count,
                        MKFILE_2, nativecode_mk_count);
                get_all_module_names(buf);
            }
        }
        closedir(d);
    }
}

static void rm_dir(const char *scanned_dir)
{
    DIR *d;
    struct dirent *de;
    char buf[256];

    d = opendir(scanned_dir);
    if (d) {
        while (NULL != (de = readdir(d))) {
            if (de->d_name[0] == '.') {
                continue;
            }

            snprintf(buf, 255, "%s/%s", scanned_dir, de->d_name);
            if (de->d_type == DT_DIR) {
                rm_dir(buf);
            } else {
                unlink(buf);
            }
        }
        closedir(d);
    }
    rmdir(scanned_dir);
}

static void parse_args(int argc, char **argv)
{
    char *p = NULL;
    int opt = 0;
    struct option long_options[] = {
        {"so", required_argument, 0, 'd'},
        {"static", required_argument, 0, 's'},
        {"bin", required_argument, 0, 'b'},
        {"apk", required_argument, 0, 'a'},
        {"prebuilt", required_argument, 0, 'p'},
        {"jar", required_argument, 0, 'j'},
        {"jar_host", required_argument, 0, 'r'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };

    if (strchr(argv[0], '/')) {
        p = strchr(argv[0], '/');
        p++;
    }
    strcpy(proc_name_arg, p);

    while ((opt = getopt_long(argc, argv, "p:d:s:b:j:a:r:h",
                    long_options, NULL)) != -1) {
        switch(opt) {
            case 'p': /* prebuilt */
                strncpy(match_tables[0].cli_arg, optarg, 63);
                break;
            case 'd': /* shared */
                strncpy(match_tables[1].cli_arg, optarg, 63);
                break;
            case 's': /* static */
                strncpy(match_tables[2].cli_arg, optarg, 63);
                break;
            case 'b': /* binary */
                strncpy(match_tables[3].cli_arg, optarg, 63);
                break;
            case 'j': /* jar */
                strncpy(match_tables[4].cli_arg, optarg, 63);
                break;
            case 'a': /* application */
                strncpy(match_tables[5].cli_arg, optarg, 63);
                break;
            case 'r': /* host jar */
                strncpy(match_tables[6].cli_arg, optarg, 63);
                break;
            case 'h':
                print_usage();
                exit(0);
        }
    }
}

int main(int argc, char **argv)
{
    rm_dir("./oem_modules");
    mkdir("./oem_modules", 0777);
    my_printf("\nout directory: ./oem_modules\n\n");

    parse_args(argc, argv);

    list_modules("./");
    my_printf("\n\n");

    return 0;
}

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值