38
38
/* This sets the modes that are available */
41
const char *name, *alt_name;
41
const char *name, *alt_name;
46
{ "files", 0, pkg_mode_files, "Uses raw data files (no effect). Installation copies all files to the target location." },
46
{ "files", 0, pkg_mode_files, "Uses raw data files (no effect). Installation copies all files to the target location." },
48
{ "dll", "library", pkg_mode_windows, "Generates one common data file and one shared library, <package>.dll"},
49
{ "common", "archive", pkg_mode_windows, "Generates just the common file, <package>.dat"}
48
{ "dll", "library", pkg_mode_windows, "Generates one common data file and one shared library, <package>.dll"},
49
{ "common", "archive", pkg_mode_windows, "Generates just the common file, <package>.dat"},
50
{ "static", "static", pkg_mode_windows, "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
50
51
#else /*#ifdef WIN32*/
51
52
#ifdef UDATA_SO_SUFFIX
52
{ "dll", "library", pkg_mode_dll, "Generates one shared library, <package>" UDATA_SO_SUFFIX },
53
{ "dll", "library", pkg_mode_dll, "Generates one shared library, <package>" UDATA_SO_SUFFIX },
54
{ "common", "archive", pkg_mode_common, "Generates one common data file, <package>.dat" },
55
{ "static", "static", pkg_mode_static, "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
55
{ "common", "archive", pkg_mode_common, "Generates one common data file, <package>.dat" },
56
{ "static", "static", pkg_mode_static, "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
56
57
#endif /*#ifdef WIN32*/
59
60
static UOption options[]={
60
/*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG),
61
/*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
62
/*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG),
63
/*03*/ UOPTION_HELP_H, /* -h */
64
/*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */
65
/*05*/ UOPTION_VERBOSE, /* -v */
66
/*06*/ UOPTION_COPYRIGHT, /* -c */
67
/*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
68
/*08*/ UOPTION_DESTDIR, /* -d */
69
/*09*/ UOPTION_DEF( "clean", 'k', UOPT_NO_ARG),
70
/*10*/ UOPTION_DEF( "nooutput",'n', UOPT_NO_ARG),
71
/*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
72
/*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
73
/*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
74
/*14*/ UOPTION_SOURCEDIR ,
75
/*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
76
/*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
77
/*17*/ UOPTION_DEF( 0, 'M', UOPT_REQUIRES_ARG)
61
/*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG),
62
/*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
63
/*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG),
64
/*03*/ UOPTION_HELP_H, /* -h */
65
/*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */
66
/*05*/ UOPTION_VERBOSE, /* -v */
67
/*06*/ UOPTION_COPYRIGHT, /* -c */
68
/*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
69
/*08*/ UOPTION_DESTDIR, /* -d */
70
/*09*/ UOPTION_DEF( "clean", 'k', UOPT_NO_ARG),
71
/*10*/ UOPTION_DEF( "nooutput",'n', UOPT_NO_ARG),
72
/*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
73
/*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
74
/*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
75
/*14*/ UOPTION_SOURCEDIR ,
76
/*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
77
/*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
78
/*17*/ UOPTION_DEF( 0, 'M', UOPT_REQUIRES_ARG)
80
81
const char options_help[][160]={
83
"R:icupath for release version or D:icupath for debug version, where icupath is the directory where ICU is located",
84
"R:icupath for release version or D:icupath for debug version, where icupath is the directory where ICU is located",
85
"Specify options for the builder",
86
"Specify options for the builder",
87
"Specify the mode of building (see below; default: common)",
90
"Make the output verbose",
91
"Use the standard ICU copyright",
92
"Use a custom comment (instead of the copyright)",
93
"Specify the destination directory for files",
94
"Clean out generated & temporary files",
95
"Suppress output of data, just list files to be created",
96
"Force rebuilding of all data",
97
"Specify temporary dir (default: output dir)",
98
"Install the data (specify target)",
99
"Specify a custom source directory",
100
"Specify a custom entrypoint name (default: short name)",
101
"Specify a version when packaging in DLL mode",
102
"Pass the next argument to make(1)"
88
"Specify the mode of building (see below; default: common)",
91
"Make the output verbose",
92
"Use the standard ICU copyright",
93
"Use a custom comment (instead of the copyright)",
94
"Specify the destination directory for files",
95
"Clean out generated & temporary files",
96
"Suppress output of data, just list files to be created",
97
"Force rebuilding of all data",
98
"Specify temporary dir (default: output dir)",
99
"Install the data (specify target)",
100
"Specify a custom source directory",
101
"Specify a custom entrypoint name (default: short name)",
102
"Specify a version when packaging in DLL or static mode",
103
"Pass the next argument to make(1)"
106
107
main(int argc, char* argv[]) {
110
const char *progname;
111
UBool needsHelp = FALSE;
112
UErrorCode status = U_ZERO_ERROR;
118
options[2].value = "common";
119
options[17].value = "";
121
/* read command line options */
122
argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
124
/* error handling, printing usage message */
125
/* I've decided to simply print an error and quit. This tool has too
126
many options to just display them all of the time. */
128
if(options[3].doesOccur || options[4].doesOccur) {
132
if(!needsHelp && argc<0) {
134
"%s: error in command line argument \"%s\"\n",
137
fprintf(stderr, "Run '%s --help' for help.\n", progname);
140
if(! (options[0].doesOccur && options[1].doesOccur) ) {
141
fprintf(stderr, " required parameters are missing: -p and -O are required \n");
142
fprintf(stderr, "Run '%s --help' for help.\n", progname);
148
"No input files specified.\n"
149
"Run '%s --help' for help.\n", progname);
152
} /* end !needsHelp */
154
if(argc<0 || needsHelp ) {
111
const char *progname;
112
UBool needsHelp = FALSE;
113
UErrorCode status = U_ZERO_ERROR;
117
U_MAIN_INIT_ARGS(argc, argv);
121
options[2].value = "common";
122
options[17].value = "";
124
/* read command line options */
125
argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
127
/* error handling, printing usage message */
128
/* I've decided to simply print an error and quit. This tool has too
129
many options to just display them all of the time. */
131
if(options[3].doesOccur || options[4].doesOccur) {
135
if(!needsHelp && argc<0) {
137
"%s: error in command line argument \"%s\"\n",
140
fprintf(stderr, "Run '%s --help' for help.\n", progname);
143
if(! (options[0].doesOccur && options[1].doesOccur) ) {
144
fprintf(stderr, " required parameters are missing: -p and -O are required \n");
145
fprintf(stderr, "Run '%s --help' for help.\n", progname);
151
"No input files specified.\n"
152
"Run '%s --help' for help.\n", progname);
155
} /* end !needsHelp */
157
if(argc<0 || needsHelp ) {
156
159
"usage: %s [-options] [-] [packageFile] \n"
157
160
"\tProduce packaged ICU data from the given list(s) of files.\n"
158
161
"\t'-' by itself means to read from stdin.\n"
159
162
"\tpackageFile is a text file containing the list of files to package.\n",
162
fprintf(stderr, "\n options:\n");
163
for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
164
fprintf(stderr, "%-5s -%c %s%-10s %s\n",
166
options[i].shortName,
167
options[i].longName ? "or --" : " ",
168
options[i].longName ? options[i].longName : "",
172
fprintf(stderr, "modes: (-m option)\n");
173
for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
174
fprintf(stderr, " %-9s ", modes[i].name);
175
if (modes[i].alt_name) {
176
fprintf(stderr, "/ %-9s", modes[i].alt_name);
178
fprintf(stderr, " ");
180
fprintf(stderr, " %s\n", modes[i].desc);
185
/* OK, fill in the options struct */
186
uprv_memset(&o, 0, sizeof(o));
188
o.mode = options[2].value;
189
o.version = options[16].doesOccur ? options[16].value : 0;
190
o.makeArgs = options[17].value;
194
for(i=0;i<sizeof(modes)/sizeof(modes[0]);i++) {
195
if(!uprv_strcmp(modes[i].name, o.mode)) {
196
o.fcn = modes[i].fcn;
198
} else if (modes[i].alt_name && !uprv_strcmp(modes[i].alt_name, o.mode)) {
199
o.mode = modes[i].name;
200
o.fcn = modes[i].fcn;
206
fprintf(stderr, "Error: invalid mode '%s' specified. Run '%s --help' to list valid modes.\n", o.mode, progname);
210
o.shortName = options[0].value;
165
fprintf(stderr, "\n options:\n");
166
for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
167
fprintf(stderr, "%-5s -%c %s%-10s %s\n",
169
options[i].shortName,
170
options[i].longName ? "or --" : " ",
171
options[i].longName ? options[i].longName : "",
175
fprintf(stderr, "modes: (-m option)\n");
176
for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
177
fprintf(stderr, " %-9s ", modes[i].name);
178
if (modes[i].alt_name) {
179
fprintf(stderr, "/ %-9s", modes[i].alt_name);
181
fprintf(stderr, " ");
183
fprintf(stderr, " %s\n", modes[i].desc);
188
/* OK, fill in the options struct */
189
uprv_memset(&o, 0, sizeof(o));
191
o.mode = options[2].value;
192
o.version = options[16].doesOccur ? options[16].value : 0;
193
o.makeArgs = options[17].value;
197
for(i=0;i<sizeof(modes)/sizeof(modes[0]);i++) {
198
if(!uprv_strcmp(modes[i].name, o.mode)) {
199
o.fcn = modes[i].fcn;
201
} else if (modes[i].alt_name && !uprv_strcmp(modes[i].alt_name, o.mode)) {
202
o.mode = modes[i].name;
203
o.fcn = modes[i].fcn;
209
fprintf(stderr, "Error: invalid mode '%s' specified. Run '%s --help' to list valid modes.\n", o.mode, progname);
213
o.shortName = options[0].value;
215
int len = uprv_strlen(o.shortName);
219
cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
220
if (*(sp = o.shortName)) {
221
*cp++ = isalpha(*sp) ? * sp : '_';
222
for (++sp; *sp; ++sp) {
223
*cp++ = isalnum(*sp) ? *sp : '_';
228
o.cShortName = csname;
211
231
#ifdef WIN32 /* format is R:pathtoICU or D:pathtoICU */
213
char *pathstuff = (char *)options[1].value;
214
if(options[1].value[uprv_strlen(options[1].value)-1] == '\\') {
215
pathstuff[uprv_strlen(options[1].value)-1] = '\0';
217
if(*pathstuff == 'R' || *pathstuff == 'D') {
218
o.options = pathstuff;
220
if(*pathstuff == ':') {
233
char *pathstuff = (char *)options[1].value;
234
if(options[1].value[uprv_strlen(options[1].value)-1] == '\\') {
235
pathstuff[uprv_strlen(options[1].value)-1] = '\0';
237
if(*pathstuff == 'R' || *pathstuff == 'D') {
238
o.options = pathstuff;
240
if(*pathstuff == ':') {
244
fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n", o.mode, progname);
224
248
fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n", o.mode, progname);
228
fprintf(stderr, "Error: invalid windows build mode, should be R (release) or D (debug).\n", o.mode, progname);
231
o.icuroot = pathstuff;
251
o.icuroot = pathstuff;
233
253
#else /* on UNIX, we'll just include the file... */
234
o.options = options[1].value;
254
o.options = options[1].value;
236
o.verbose = options[5].doesOccur;
237
if(options[6].doesOccur) {
238
o.comment = U_COPYRIGHT_STRING;
239
} else if (options[7].doesOccur) {
240
o.comment = options[7].value;
243
if( options[8].doesOccur ) {
244
o.targetDir = options[8].value;
246
o.targetDir = ""; /* cwd */
249
o.clean = options[9].doesOccur;
250
o.nooutput = options[10].doesOccur;
251
o.rebuild = options[11].doesOccur;
253
if( options[12].doesOccur ) {
254
o.tmpDir = options[12].value;
256
o.tmpDir = o.targetDir;
259
if( options[13].doesOccur ) {
260
o.install = options[13].value;
263
if( options[14].doesOccur ) {
264
o.srcDir = options[14].value;
269
if( options[15].doesOccur ) {
270
o.entryName = options[15].value;
272
o.entryName = o.shortName;
275
/* OK options are set up. Now the file lists. */
277
for( i=1; i<argc; i++) {
278
if ( !uprv_strcmp(argv[i] , "-") ) {
280
if( o.hadStdin == TRUE ) {
281
fprintf(stderr, "Error: can't specify '-' twice!\n"
282
"Run '%s --help' for help.\n", progname);
288
o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[i]));
292
loadLists(&o, &status);
293
if( U_FAILURE(status) ) {
294
fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
298
/* Makefile pathname */
299
uprv_strcpy(tmp, o.tmpDir);
300
uprv_strcat(tmp, U_FILE_SEP_STRING);
301
uprv_strcat(tmp, o.shortName);
302
uprv_strcat(tmp, "_");
303
uprv_strcat(tmp, o.mode);
304
uprv_strcat(tmp, ".mak"); /* MAY NEED TO CHANGE PER PLATFORM */
306
o.makeFile = uprv_strdup(tmp);
308
out = T_FileStream_open(o.makeFile, "w");
310
pkg_mak_writeHeader(out, &o); /* need to take status */
311
o.fcn(&o, out, &status);
312
pkg_mak_writeFooter(out, &o);
313
T_FileStream_close(out);
315
fprintf(stderr, "warning: couldn't create %s, will use existing file if any\n", o.makeFile);
316
/*status = U_FILE_ACCESS_ERROR;*/
319
if(U_FAILURE(status)) {
320
fprintf(stderr, "Error creating makefile [%s]: %s\n", o.mode,
256
o.verbose = options[5].doesOccur;
257
if(options[6].doesOccur) {
258
o.comment = U_COPYRIGHT_STRING;
259
} else if (options[7].doesOccur) {
260
o.comment = options[7].value;
263
if( options[8].doesOccur ) {
264
o.targetDir = options[8].value;
266
o.targetDir = ""; /* cwd */
269
o.clean = options[9].doesOccur;
270
o.nooutput = options[10].doesOccur;
271
o.rebuild = options[11].doesOccur;
273
if( options[12].doesOccur ) {
274
o.tmpDir = options[12].value;
276
o.tmpDir = o.targetDir;
279
if( options[13].doesOccur ) {
280
o.install = options[13].value;
283
if( options[14].doesOccur ) {
284
o.srcDir = options[14].value;
289
if( options[15].doesOccur ) {
290
o.entryName = options[15].value;
292
o.entryName = o.cShortName;
295
/* OK options are set up. Now the file lists. */
297
for( i=1; i<argc; i++) {
298
if ( !uprv_strcmp(argv[i] , "-") ) {
300
if( o.hadStdin == TRUE ) {
301
fprintf(stderr, "Error: can't specify '-' twice!\n"
302
"Run '%s --help' for help.\n", progname);
308
o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[i]));
312
loadLists(&o, &status);
313
if( U_FAILURE(status) ) {
314
fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
318
/* Makefile pathname */
319
uprv_strcpy(tmp, o.tmpDir);
320
uprv_strcat(tmp, U_FILE_SEP_STRING);
321
uprv_strcat(tmp, o.shortName);
322
uprv_strcat(tmp, "_");
323
uprv_strcat(tmp, o.mode);
324
uprv_strcat(tmp, ".mak"); /* MAY NEED TO CHANGE PER PLATFORM */
326
o.makeFile = uprv_strdup(tmp);
328
out = T_FileStream_open(o.makeFile, "w");
330
pkg_mak_writeHeader(out, &o); /* need to take status */
331
o.fcn(&o, out, &status);
332
pkg_mak_writeFooter(out, &o);
333
T_FileStream_close(out);
335
fprintf(stderr, "warning: couldn't create %s, will use existing file if any\n", o.makeFile);
336
/*status = U_FILE_ACCESS_ERROR;*/
339
if(U_FAILURE(status)) {
340
fprintf(stderr, "Error creating makefile [%s]: %s\n", o.mode,
321
341
u_errorName(status));
325
if(o.nooutput == TRUE) {
326
return 0; /* nothing to do. */
329
return executeMakefile(&o);
345
if(o.nooutput == TRUE) {
346
return 0; /* nothing to do. */
349
return executeMakefile(&o);
332
352
/* POSIX - execute makefile */
333
353
static int executeMakefile(const UPKGOptions *o)
340
make = getenv("MAKE");
342
if(!make || !make[0]) {
346
/*getcwd(pwd, 1024);*/
360
make = getenv("MAKE");
362
if(!make || !make[0]) {
366
/*getcwd(pwd, 1024);*/
348
sprintf(cmd, "%s %s%s -f \"%s\" %s %s %s %s",
350
o->install ? "INSTALLTO=" : "",
351
o->install ? o->install : "",
353
o->clean ? "clean" : "",
354
o->rebuild ? "rebuild" : "",
355
o->install ? "install" : "",
368
sprintf(cmd, "%s %s%s -f \"%s\" %s %s %s %s",
370
o->install ? "INSTALLTO=" : "",
371
o->install ? o->install : "",
373
o->clean ? "clean" : "",
374
o->rebuild ? "rebuild" : "",
375
o->install ? "install" : "",
358
sprintf(cmd, "CALL GNU/GMAKE PARM(%s%s%s '-f' '%s' %s %s %s %s)",
359
o->install ? "'INSTALLTO=" : "",
360
o->install ? o->install : "",
361
o->install ? "'" : "",
363
o->clean ? "'clean'" : "",
364
o->rebuild ? "'rebuild'" : "",
365
o->install ? "'install'" : "",
378
sprintf(cmd, "CALL GNU/GMAKE PARM(%s%s%s '-f' '%s' %s %s %s %s)",
379
o->install ? "'INSTALLTO=" : "",
380
o->install ? o->install : "",
381
o->install ? "'" : "",
383
o->clean ? "'clean'" : "",
384
o->rebuild ? "'rebuild'" : "",
385
o->install ? "'install'" : "",
368
sprintf(cmd, "%s %s%s -f %s %s %s %s %s",
370
o->install ? "INSTALLTO=" : "",
371
o->install ? o->install : "",
373
o->clean ? "clean" : "",
374
o->rebuild ? "rebuild" : "",
375
o->install ? "install" : "",
388
sprintf(cmd, "%s %s%s -f %s %s %s %s %s",
390
o->install ? "INSTALLTO=" : "",
391
o->install ? o->install : "",
393
o->clean ? "clean" : "",
394
o->rebuild ? "rebuild" : "",
395
o->install ? "install" : "",
385
fprintf(stderr, "# Failed, rc=%d\n", rc);
387
return rc < 128 ? rc : (rc >> 8);
405
fprintf(stderr, "# Failed, rc=%d\n", rc);
408
return rc < 128 ? rc : (rc >> 8);
391
412
static void loadLists(UPKGOptions *o, UErrorCode *status)
393
CharList *l, *tail = NULL, *tail2 = NULL;
397
const char* baseName;
400
for(l = o->fileListFiles; l; l = l->next) {
402
fprintf(stdout, "# Reading %s..\n", l->str);
406
in = T_FileStream_open(l->str, "r");
409
fprintf(stderr, "Error opening <%s>.\n", l->str);
410
*status = U_FILE_ACCESS_ERROR;
414
while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) {
415
/* remove trailing newline characters */
418
if(*s=='\r' || *s=='\n') {
424
if((*line == 0) || (*line == '#')) {
425
continue; /* comment or empty line */
429
s = (char*)getLongPathname(line);
431
baseName = findBasename(s);
433
o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName));
435
if(s != baseName) { /* s was something long, so we leave it as it is */
436
o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(s));
437
} else { /* s was just a basename, we want to prepend source dir*/
438
uprv_strcpy(tmp, o->srcDir);
439
uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING);
441
o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
445
T_FileStream_close(in);
414
CharList *l, *tail = NULL, *tail2 = NULL;
418
const char* baseName;
421
for(l = o->fileListFiles; l; l = l->next) {
423
fprintf(stdout, "# Reading %s..\n", l->str);
426
in = T_FileStream_open(l->str, "r");
429
fprintf(stderr, "Error opening <%s>.\n", l->str);
430
*status = U_FILE_ACCESS_ERROR;
434
while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) {
435
/* remove trailing newline characters */
438
if(*s=='\r' || *s=='\n') {
444
if((*line == 0) || (*line == '#')) {
445
continue; /* comment or empty line */
449
s = (char*)getLongPathname(line);
451
baseName = findBasename(s);
453
o->files = pkg_appendToList(o->files, &tail, uprv_strdup(baseName));
455
if(s != baseName) { /* s was something long, so we leave it as it is */
456
o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(s));
457
} else { /* s was just a basename, we want to prepend source dir*/
458
uprv_strcpy(tmp, o->srcDir);
459
uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1]==U_FILE_SEP_CHAR?"":U_FILE_SEP_STRING);
461
o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
465
T_FileStream_close(in);