遍历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;

}