~xnox/ubuntu/trusty/gcc-arm-linux-androideabi/dima

« back to all changes in this revision

Viewing changes to android/build/tools/atree/atree.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-07-05 10:12:24 UTC
  • Revision ID: package-import@ubuntu.com-20130705101224-6qo3e8jbz8p31aa1
Tags: upstream-0.20130705.1
ImportĀ upstreamĀ versionĀ 0.20130705.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
#include <unistd.h>
 
5
#include <stdarg.h>
 
6
#include "options.h"
 
7
#include "files.h"
 
8
#include "fs.h"
 
9
#include <set>
 
10
#include <iostream>
 
11
#include <sstream>
 
12
 
 
13
using namespace std;
 
14
 
 
15
bool g_debug = getenv("ATREE_DEBUG") != NULL;
 
16
vector<string> g_listFiles;
 
17
vector<string> g_inputBases;
 
18
map<string, string> g_variables;
 
19
string g_outputBase;
 
20
string g_dependency;
 
21
bool g_useHardLinks = false;
 
22
 
 
23
const char* USAGE =
 
24
"\n"
 
25
"Usage: atree OPTIONS\n"
 
26
"\n"
 
27
"Options:\n"
 
28
"  -f FILELIST    Specify one or more files containing the\n"
 
29
"                 list of files to copy.\n"
 
30
"  -I INPUTDIR    Specify one or more base directories in\n"
 
31
"                 which to look for the files\n"
 
32
"  -o OUTPUTDIR   Specify the directory to copy all of the\n"
 
33
"                 output files to.\n"
 
34
"  -l             Use hard links instead of copying the files.\n"
 
35
"  -m DEPENDENCY  Output a make-formatted file containing the list.\n"
 
36
"                 of files included.  It sets the variable ATREE_FILES.\n"
 
37
"  -v VAR=VAL     Replaces ${VAR} by VAL when reading input files.\n"
 
38
"  -d             Verbose debug mode.\n"
 
39
"\n"
 
40
"FILELIST file format:\n"
 
41
"  The FILELIST files contain the list of files that will end up\n"
 
42
"  in the final OUTPUTDIR.  Atree will look for files in the INPUTDIR\n"
 
43
"  directories in the order they are specified.\n"
 
44
"\n"
 
45
"  In a FILELIST file, comment lines start with a #.  Other lines\n"
 
46
"  are of the format:\n"
 
47
"\n"
 
48
"    [rm|strip] DEST\n"
 
49
"    SRC [strip] DEST\n"
 
50
"    -SRCPATTERN\n"
 
51
"\n"
 
52
"  DEST should be path relative to the output directory.\n"
 
53
"  'rm DEST' removes the destination file and fails if it's missing.\n"
 
54
"  'strip DEST' strips the binary destination file.\n"
 
55
"  If SRC is supplied, the file names can be different.\n"
 
56
"  SRCPATTERN is a pattern for the filenames.\n"
 
57
"\n";
 
58
 
 
59
int usage()
 
60
{
 
61
    fwrite(USAGE, strlen(USAGE), 1, stderr);
 
62
    return 1;
 
63
}
 
64
 
 
65
static bool
 
66
add_variable(const char* arg) {
 
67
    const char* p = arg;
 
68
    while (*p && *p != '=') p++;
 
69
 
 
70
    if (*p == 0 || p == arg || p[1] == 0) {
 
71
        return false;
 
72
    }
 
73
 
 
74
    ostringstream var;
 
75
    var << "${" << string(arg, p-arg) << "}";
 
76
    g_variables[var.str()] = string(p+1);
 
77
    return true;
 
78
}
 
79
 
 
80
static void
 
81
debug_printf(const char* format, ...)
 
82
{
 
83
    if (g_debug) {
 
84
        fflush(stderr);
 
85
        va_list ap;
 
86
        va_start(ap, format);
 
87
        vprintf(format, ap);
 
88
        va_end(ap);
 
89
        fflush(stdout);
 
90
    }
 
91
}
 
92
 
 
93
int
 
94
main(int argc, char* const* argv)
 
95
{
 
96
    int err;
 
97
    bool done = false;
 
98
    while (!done) {
 
99
        int opt = getopt(argc, argv, "f:I:o:hlm:v:d");
 
100
        switch (opt)
 
101
        {
 
102
            case -1:
 
103
                done = true;
 
104
                break;
 
105
            case 'f':
 
106
                g_listFiles.push_back(string(optarg));
 
107
                break;
 
108
            case 'I':
 
109
                g_inputBases.push_back(string(optarg));
 
110
                break;
 
111
            case 'o':
 
112
                if (g_outputBase.length() != 0) {
 
113
                    fprintf(stderr, "%s: -o may only be supplied once -- "
 
114
                                "-o %s\n", argv[0], optarg);
 
115
                    return usage();
 
116
                }
 
117
                g_outputBase = optarg;
 
118
                break;
 
119
            case 'l':
 
120
                g_useHardLinks = true;
 
121
                break;
 
122
            case 'm':
 
123
                if (g_dependency.length() != 0) {
 
124
                    fprintf(stderr, "%s: -m may only be supplied once -- "
 
125
                                "-m %s\n", argv[0], optarg);
 
126
                    return usage();
 
127
                }
 
128
                g_dependency = optarg;
 
129
                break;
 
130
            case 'v':
 
131
                if (!add_variable(optarg)) {
 
132
                    fprintf(stderr, "%s Invalid expression in '-v %s': "
 
133
                            "expected format is '-v VAR=VALUE'.\n",
 
134
                            argv[0], optarg);
 
135
                    return usage();
 
136
                }
 
137
                break;
 
138
            case 'd':
 
139
                g_debug = true;
 
140
                break;
 
141
            default:
 
142
            case '?':
 
143
            case 'h':
 
144
                return usage();
 
145
        }
 
146
    }
 
147
    if (optind != argc) {
 
148
        fprintf(stderr, "%s: invalid argument -- %s\n", argv[0], argv[optind]);
 
149
        return usage();
 
150
    }
 
151
 
 
152
    if (g_listFiles.size() == 0) {
 
153
        fprintf(stderr, "%s: At least one -f option must be supplied.\n",
 
154
                 argv[0]);
 
155
        return usage();
 
156
    }
 
157
 
 
158
    if (g_inputBases.size() == 0) {
 
159
        fprintf(stderr, "%s: At least one -I option must be supplied.\n",
 
160
                 argv[0]);
 
161
        return usage();
 
162
    }
 
163
 
 
164
    if (g_outputBase.length() == 0) {
 
165
        fprintf(stderr, "%s: -o option must be supplied.\n", argv[0]);
 
166
        return usage();
 
167
    }
 
168
 
 
169
 
 
170
#if 0
 
171
    for (vector<string>::iterator it=g_listFiles.begin();
 
172
                                it!=g_listFiles.end(); it++) {
 
173
        printf("-f \"%s\"\n", it->c_str());
 
174
    }
 
175
    for (vector<string>::iterator it=g_inputBases.begin();
 
176
                                it!=g_inputBases.end(); it++) {
 
177
        printf("-I \"%s\"\n", it->c_str());
 
178
    }
 
179
    printf("-o \"%s\"\n", g_outputBase.c_str());
 
180
    if (g_useHardLinks) {
 
181
        printf("-l\n");
 
182
    }
 
183
#endif
 
184
 
 
185
    vector<FileRecord> files;
 
186
    vector<FileRecord> more;
 
187
    vector<string> excludes;
 
188
    set<string> directories;
 
189
    set<string> deleted;
 
190
 
 
191
    // read file lists
 
192
    for (vector<string>::iterator it=g_listFiles.begin();
 
193
                                 it!=g_listFiles.end(); it++) {
 
194
        err = read_list_file(*it, g_variables, &files, &excludes);
 
195
        if (err != 0) {
 
196
            return err;
 
197
        }
 
198
    }
 
199
 
 
200
    // look for input files
 
201
    err = 0;
 
202
    for (vector<FileRecord>::iterator it=files.begin();
 
203
                                it!=files.end(); it++) {
 
204
        err |= locate(&(*it), g_inputBases);
 
205
    }
 
206
 
 
207
    // expand the directories that we should copy into a list of files
 
208
    for (vector<FileRecord>::iterator it=files.begin();
 
209
                                it!=files.end(); it++) {
 
210
        if (it->sourceIsDir) {
 
211
            err |= list_dir(*it, excludes, &more);
 
212
        }
 
213
    }
 
214
    for (vector<FileRecord>::iterator it=more.begin();
 
215
                                it!=more.end(); it++) {
 
216
        files.push_back(*it);
 
217
    }
 
218
 
 
219
    // get the name and modtime of the output files
 
220
    for (vector<FileRecord>::iterator it=files.begin();
 
221
                                it!=files.end(); it++) {
 
222
        stat_out(g_outputBase, &(*it));
 
223
    }
 
224
 
 
225
    if (err != 0) {
 
226
        return 1;
 
227
    }
 
228
 
 
229
    // gather directories
 
230
    for (vector<FileRecord>::iterator it=files.begin();
 
231
                                it!=files.end(); it++) {
 
232
        if (it->sourceIsDir) {
 
233
            directories.insert(it->outPath);
 
234
        } else {
 
235
            string s = dir_part(it->outPath);
 
236
            if (s != ".") {
 
237
                directories.insert(s);
 
238
            }
 
239
        }
 
240
    }
 
241
 
 
242
    // gather files that should become directores
 
243
    // and directories that should become files
 
244
    for (vector<FileRecord>::iterator it=files.begin();
 
245
                                it!=files.end(); it++) {
 
246
        if (it->outMod != 0 && it->sourceIsDir != it->outIsDir) {
 
247
            deleted.insert(it->outPath);
 
248
        }
 
249
    }
 
250
 
 
251
    // delete files
 
252
    for (set<string>::iterator it=deleted.begin();
 
253
                                it!=deleted.end(); it++) {
 
254
        debug_printf("deleting %s\n", it->c_str());
 
255
        err = remove_recursively(*it);
 
256
        if (err != 0) {
 
257
            return err;
 
258
        }
 
259
    }
 
260
 
 
261
    // remove all files or directories as requested from the input atree file.
 
262
    // must be done before create new directories.
 
263
    for (vector<FileRecord>::iterator it=files.begin();
 
264
                                it!=files.end(); it++) {
 
265
        if (!it->sourceIsDir) {
 
266
            if (it->fileOp == FILE_OP_REMOVE &&
 
267
                    deleted.count(it->outPath) == 0) {
 
268
                debug_printf("remove %s\n", it->outPath.c_str());
 
269
                err = remove_recursively(it->outPath);
 
270
                if (err != 0) {
 
271
                    return err;
 
272
                }
 
273
            }
 
274
        }
 
275
    }
 
276
 
 
277
    // make directories
 
278
    for (set<string>::iterator it=directories.begin();
 
279
                                it!=directories.end(); it++) {
 
280
        debug_printf("mkdir %s\n", it->c_str());
 
281
        err = mkdir_recursively(*it);
 
282
        if (err != 0) {
 
283
            return err;
 
284
        }
 
285
    }
 
286
 
 
287
    // copy (or link) files that are newer or of different size
 
288
    for (vector<FileRecord>::iterator it=files.begin();
 
289
                                it!=files.end(); it++) {
 
290
        if (!it->sourceIsDir) {
 
291
            if (it->fileOp == FILE_OP_REMOVE) {
 
292
                continue;
 
293
            }
 
294
 
 
295
            debug_printf("copy %s(%ld) ==> %s(%ld)",
 
296
                it->sourcePath.c_str(), it->sourceMod,
 
297
                it->outPath.c_str(), it->outMod);
 
298
 
 
299
            if (it->outSize != it->sourceSize || it->outMod < it->sourceMod) {
 
300
                err = copy_file(it->sourcePath, it->outPath);
 
301
                debug_printf(" done.\n");
 
302
                if (err != 0) {
 
303
                    return err;
 
304
                }
 
305
            } else {
 
306
                debug_printf(" skipping.\n");
 
307
            }
 
308
 
 
309
            if (it->fileOp == FILE_OP_STRIP) {
 
310
                debug_printf("strip %s\n", it->outPath.c_str());
 
311
                err = strip_file(it->outPath);
 
312
                if (err != 0) {
 
313
                    return err;
 
314
                }
 
315
            }
 
316
        }
 
317
    }
 
318
 
 
319
    // output the dependency file
 
320
    if (g_dependency.length() != 0) {
 
321
        FILE *f = fopen(g_dependency.c_str(), "w");
 
322
        if (f != NULL) {
 
323
            fprintf(f, "ATREE_FILES := $(ATREE_FILES) \\\n");
 
324
            for (vector<FileRecord>::iterator it=files.begin();
 
325
                                it!=files.end(); it++) {
 
326
                if (!it->sourceIsDir) {
 
327
                    fprintf(f, "%s \\\n", it->sourcePath.c_str());
 
328
                }
 
329
            }
 
330
            fprintf(f, "\n");
 
331
            fclose(f);
 
332
        } else {
 
333
            fprintf(stderr, "error opening manifest file for write: %s\n",
 
334
                    g_dependency.c_str());
 
335
        }
 
336
    }
 
337
 
 
338
    return 0;
 
339
}