]> git.saurik.com Git - apple/icu.git/blob - icuSources/tools/pkgdata/pkgdata.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / tools / pkgdata / pkgdata.cpp
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /******************************************************************************
4 * Copyright (C) 2000-2016, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *******************************************************************************
7 * file name: pkgdata.cpp
8 * encoding: ANSI X3.4 (1968)
9 * tab size: 8 (not used)
10 * indentation:4
11 *
12 * created on: 2000may15
13 * created by: Steven \u24C7 Loomis
14 *
15 * This program packages the ICU data into different forms
16 * (DLL, common data, etc.)
17 */
18
19 // Defines _XOPEN_SOURCE for access to POSIX functions.
20 // Must be before any other #includes.
21 #include "uposixdefs.h"
22
23 #include "unicode/utypes.h"
24
25 #include "unicode/putil.h"
26 #include "putilimp.h"
27
28 #if U_HAVE_POPEN
29 #if (U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__)
30 /* popen/pclose aren't defined in strict ANSI on Cygwin and MinGW */
31 #undef __STRICT_ANSI__
32 #endif
33 #endif
34
35 #include "cmemory.h"
36 #include "cstring.h"
37 #include "filestrm.h"
38 #include "toolutil.h"
39 #include "unicode/uclean.h"
40 #include "unewdata.h"
41 #include "uoptions.h"
42 #include "package.h"
43 #include "pkg_icu.h"
44 #include "pkg_genc.h"
45 #include "pkg_gencmn.h"
46 #include "flagparser.h"
47 #include "filetools.h"
48 #include "charstr.h"
49
50 #if U_HAVE_POPEN
51 # include <unistd.h>
52 #endif
53
54 #include <stdio.h>
55 #include <stdlib.h>
56
57 U_CDECL_BEGIN
58 #include "pkgtypes.h"
59 U_CDECL_END
60
61 #if U_HAVE_POPEN
62
63 using icu::LocalPointerBase;
64
65 U_DEFINE_LOCAL_OPEN_POINTER(LocalPipeFilePointer, FILE, pclose);
66
67 #endif
68
69 using icu::LocalMemory;
70
71 static void loadLists(UPKGOptions *o, UErrorCode *status);
72
73 static int32_t pkg_executeOptions(UPKGOptions *o);
74
75 #ifdef WINDOWS_WITH_MSVC
76 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
77 #endif
78 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=FALSE);
79 static int32_t pkg_installLibrary(const char *installDir, const char *dir, UBool noVersion);
80 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
81 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName);
82
83 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
84 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
85 #endif
86
87 #ifdef CAN_WRITE_OBJ_CODE
88 static void pkg_createOptMatchArch(char *optMatchArch);
89 static void pkg_destroyOptMatchArch(char *optMatchArch);
90 #endif
91
92 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
93 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL, UBool specialHandling=FALSE);
94 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
95 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion);
96 static int32_t initializePkgDataFlags(UPKGOptions *o);
97
98 static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option);
99 static int runCommand(const char* command, UBool specialHandling=FALSE);
100
101 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
102 #define IN_DLL_MODE(mode) (mode == 'd' || mode == 'l')
103 #define IN_STATIC_MODE(mode) (mode == 's')
104 #define IN_FILES_MODE(mode) (mode == 'f')
105
106 enum {
107 NAME,
108 BLDOPT,
109 MODE,
110 HELP,
111 HELP_QUESTION_MARK,
112 VERBOSE,
113 COPYRIGHT,
114 COMMENT,
115 DESTDIR,
116 REBUILD,
117 TEMPDIR,
118 INSTALL,
119 SOURCEDIR,
120 ENTRYPOINT,
121 REVISION,
122 FORCE_PREFIX,
123 LIBNAME,
124 QUIET,
125 WITHOUT_ASSEMBLY,
126 PDS_BUILD,
127 WIN_UWP_BUILD,
128 WIN_DLL_ARCH,
129 WIN_DYNAMICBASE
130 };
131
132 /* This sets the modes that are available */
133 static struct {
134 const char *name, *alt_name;
135 const char *desc;
136 } modes[] = {
137 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
138 #if U_PLATFORM_HAS_WIN32_API
139 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
140 { "common", "archive", "Generates just the common file, <package>.dat"},
141 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
142 #else
143 #ifdef UDATA_SO_SUFFIX
144 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX },
145 #endif
146 { "common", "archive", "Generates one common data file, <package>.dat" },
147 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
148 #endif
149 };
150
151 static UOption options[]={
152 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG),
153 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
154 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG),
155 /*03*/ UOPTION_HELP_H, /* -h */
156 /*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */
157 /*05*/ UOPTION_VERBOSE, /* -v */
158 /*06*/ UOPTION_COPYRIGHT, /* -c */
159 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
160 /*08*/ UOPTION_DESTDIR, /* -d */
161 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
162 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
163 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
164 /*14*/ UOPTION_SOURCEDIR ,
165 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
166 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
167 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
168 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
169 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG),
170 /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG),
171 /*21*/ UOPTION_DEF("zos-pds-build", 'z', UOPT_NO_ARG),
172 /*22*/ UOPTION_DEF("windows-uwp-build", 'u', UOPT_NO_ARG),
173 /*23*/ UOPTION_DEF("windows-DLL-arch", 'a', UOPT_REQUIRES_ARG),
174 /*24*/ UOPTION_DEF("windows-dynamicbase", 'b', UOPT_NO_ARG),
175 };
176
177 /* This enum and the following char array should be kept in sync. */
178 enum {
179 GENCCODE_ASSEMBLY_TYPE,
180 SO_EXT,
181 SOBJ_EXT,
182 A_EXT,
183 LIBPREFIX,
184 LIB_EXT_ORDER,
185 COMPILER,
186 LIBFLAGS,
187 GENLIB,
188 LDICUDTFLAGS,
189 LD_SONAME,
190 RPATH_FLAGS,
191 BIR_FLAGS,
192 AR,
193 ARFLAGS,
194 RANLIB,
195 INSTALL_CMD,
196 PKGDATA_FLAGS_SIZE
197 };
198 static const char* FLAG_NAMES[PKGDATA_FLAGS_SIZE] = {
199 "GENCCODE_ASSEMBLY_TYPE",
200 "SO",
201 "SOBJ",
202 "A",
203 "LIBPREFIX",
204 "LIB_EXT_ORDER",
205 "COMPILE",
206 "LIBFLAGS",
207 "GENLIB",
208 "LDICUDTFLAGS",
209 "LD_SONAME",
210 "RPATH_FLAGS",
211 "BIR_LDFLAGS",
212 "AR",
213 "ARFLAGS",
214 "RANLIB",
215 "INSTALL_CMD"
216 };
217 static char **pkgDataFlags = NULL;
218
219 enum {
220 LIB_FILE,
221 LIB_FILE_VERSION_MAJOR,
222 LIB_FILE_VERSION,
223 LIB_FILE_VERSION_TMP,
224 #if U_PLATFORM == U_PF_CYGWIN
225 LIB_FILE_CYGWIN,
226 LIB_FILE_CYGWIN_VERSION,
227 #elif U_PLATFORM == U_PF_MINGW
228 LIB_FILE_MINGW,
229 #elif U_PLATFORM == U_PF_OS390
230 LIB_FILE_OS390BATCH_MAJOR,
231 LIB_FILE_OS390BATCH_VERSION,
232 #endif
233 LIB_FILENAMES_SIZE
234 };
235 static char libFileNames[LIB_FILENAMES_SIZE][256];
236
237 static UPKGOptions *pkg_checkFlag(UPKGOptions *o);
238
239 const char options_help[][320]={
240 "Set the data name",
241 #ifdef U_MAKE_IS_NMAKE
242 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
243 #else
244 "Specify options for the builder.",
245 #endif
246 "Specify the mode of building (see below; default: common)",
247 "This usage text",
248 "This usage text",
249 "Make the output verbose",
250 "Use the standard ICU copyright",
251 "Use a custom comment (instead of the copyright)",
252 "Specify the destination directory for files",
253 "Force rebuilding of all data",
254 "Specify temporary dir (default: output dir)",
255 "Install the data (specify target)",
256 "Specify a custom source directory",
257 "Specify a custom entrypoint name (default: short name)",
258 "Specify a version when packaging in dll or static mode",
259 "Add package to all file names if not present",
260 "Library name to build (if different than package name)",
261 "Quiet mode. (e.g. Do not output a readme file for static libraries)",
262 "Build the data without assembly code",
263 "Build PDS dataset (zOS build only)",
264 "Build for Universal Windows Platform (Windows build only)",
265 "Specify the DLL machine architecture for LINK.exe (Windows build only)",
266 "Ignored. Enable DYNAMICBASE on the DLL. This is now the default. (Windows build only)",
267 };
268
269 const char *progname = "PKGDATA";
270
271 int
272 main(int argc, char* argv[]) {
273 int result = 0;
274 /* FileStream *out; */
275 UPKGOptions o;
276 CharList *tail;
277 UBool needsHelp = FALSE;
278 UErrorCode status = U_ZERO_ERROR;
279 /* char tmp[1024]; */
280 uint32_t i;
281 int32_t n;
282
283 U_MAIN_INIT_ARGS(argc, argv);
284
285 progname = argv[0];
286
287 options[MODE].value = "common";
288
289 /* read command line options */
290 argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options);
291
292 /* error handling, printing usage message */
293 /* I've decided to simply print an error and quit. This tool has too
294 many options to just display them all of the time. */
295
296 if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
297 needsHelp = TRUE;
298 }
299 else {
300 if(!needsHelp && argc<0) {
301 fprintf(stderr,
302 "%s: error in command line argument \"%s\"\n",
303 progname,
304 argv[-argc]);
305 fprintf(stderr, "Run '%s --help' for help.\n", progname);
306 return 1;
307 }
308
309
310 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
311 if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) {
312 if (pkg_getOptionsFromICUConfig(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) {
313 fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n");
314 fprintf(stderr, "Run '%s --help' for help.\n", progname);
315 return 1;
316 }
317 }
318 #else
319 if(options[BLDOPT].doesOccur) {
320 fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
321 }
322 #endif
323
324 if(!options[NAME].doesOccur) /* -O we already have - don't report it. */
325 {
326 fprintf(stderr, " required parameter -p is missing \n");
327 fprintf(stderr, "Run '%s --help' for help.\n", progname);
328 return 1;
329 }
330
331 if(argc == 1) {
332 fprintf(stderr,
333 "No input files specified.\n"
334 "Run '%s --help' for help.\n", progname);
335 return 1;
336 }
337 } /* end !needsHelp */
338
339 if(argc<0 || needsHelp ) {
340 fprintf(stderr,
341 "usage: %s [-options] [-] [packageFile] \n"
342 "\tProduce packaged ICU data from the given list(s) of files.\n"
343 "\t'-' by itself means to read from stdin.\n"
344 "\tpackageFile is a text file containing the list of files to package.\n",
345 progname);
346
347 fprintf(stderr, "\n options:\n");
348 for(i=0;i<UPRV_LENGTHOF(options);i++) {
349 fprintf(stderr, "%-5s -%c %s%-10s %s\n",
350 (i<1?"[REQ]":""),
351 options[i].shortName,
352 options[i].longName ? "or --" : " ",
353 options[i].longName ? options[i].longName : "",
354 options_help[i]);
355 }
356
357 fprintf(stderr, "modes: (-m option)\n");
358 for(i=0;i<UPRV_LENGTHOF(modes);i++) {
359 fprintf(stderr, " %-9s ", modes[i].name);
360 if (modes[i].alt_name) {
361 fprintf(stderr, "/ %-9s", modes[i].alt_name);
362 } else {
363 fprintf(stderr, " ");
364 }
365 fprintf(stderr, " %s\n", modes[i].desc);
366 }
367 return 1;
368 }
369
370 /* OK, fill in the options struct */
371 uprv_memset(&o, 0, sizeof(o));
372
373 o.mode = options[MODE].value;
374 o.version = options[REVISION].doesOccur ? options[REVISION].value : 0;
375
376 o.shortName = options[NAME].value;
377 {
378 int32_t len = (int32_t)uprv_strlen(o.shortName);
379 char *csname, *cp;
380 const char *sp;
381
382 cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
383 if (*(sp = o.shortName)) {
384 *cp++ = isalpha(*sp) ? * sp : '_';
385 for (++sp; *sp; ++sp) {
386 *cp++ = isalnum(*sp) ? *sp : '_';
387 }
388 }
389 *cp = 0;
390
391 o.cShortName = csname;
392 }
393
394 if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */
395 o.libName = options[LIBNAME].value;
396 } else {
397 o.libName = o.shortName;
398 }
399
400 if(options[QUIET].doesOccur) {
401 o.quiet = TRUE;
402 } else {
403 o.quiet = FALSE;
404 }
405
406 if(options[PDS_BUILD].doesOccur) {
407 #if U_PLATFORM == U_PF_OS390
408 o.pdsbuild = TRUE;
409 #else
410 o.pdsbuild = FALSE;
411 fprintf(stdout, "Warning: You are using the -z option which only works on z/OS.\n");
412
413 #endif
414 } else {
415 o.pdsbuild = FALSE;
416 }
417
418 o.verbose = options[VERBOSE].doesOccur;
419
420
421 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
422 if (options[BLDOPT].doesOccur) {
423 o.options = options[BLDOPT].value;
424 } else {
425 o.options = NULL;
426 }
427 #endif
428 if(options[COPYRIGHT].doesOccur) {
429 o.comment = U_COPYRIGHT_STRING;
430 } else if (options[COMMENT].doesOccur) {
431 o.comment = options[COMMENT].value;
432 }
433
434 if( options[DESTDIR].doesOccur ) {
435 o.targetDir = options[DESTDIR].value;
436 } else {
437 o.targetDir = "."; /* cwd */
438 }
439
440 o.rebuild = options[REBUILD].doesOccur;
441
442 if( options[TEMPDIR].doesOccur ) {
443 o.tmpDir = options[TEMPDIR].value;
444 } else {
445 o.tmpDir = o.targetDir;
446 }
447
448 if( options[INSTALL].doesOccur ) {
449 o.install = options[INSTALL].value;
450 } else {
451 o.install = NULL;
452 }
453
454 if( options[SOURCEDIR].doesOccur ) {
455 o.srcDir = options[SOURCEDIR].value;
456 } else {
457 o.srcDir = ".";
458 }
459
460 if( options[ENTRYPOINT].doesOccur ) {
461 o.entryName = options[ENTRYPOINT].value;
462 } else {
463 o.entryName = o.cShortName;
464 }
465
466 o.withoutAssembly = FALSE;
467 if (options[WITHOUT_ASSEMBLY].doesOccur) {
468 #ifndef BUILD_DATA_WITHOUT_ASSEMBLY
469 fprintf(stdout, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n");
470 fprintf(stdout, "Warning: This option will be ignored.\n");
471 #else
472 o.withoutAssembly = TRUE;
473 #endif
474 }
475
476 if (options[WIN_DYNAMICBASE].doesOccur) {
477 fprintf(stdout, "Note: Ignoring option -b (windows-dynamicbase).\n");
478 }
479
480 /* OK options are set up. Now the file lists. */
481 tail = NULL;
482 for( n=1; n<argc; n++) {
483 o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
484 }
485
486 /* load the files */
487 loadLists(&o, &status);
488 if( U_FAILURE(status) ) {
489 fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
490 return 2;
491 }
492
493 result = pkg_executeOptions(&o);
494
495 if (pkgDataFlags != NULL) {
496 for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
497 if (pkgDataFlags[n] != NULL) {
498 uprv_free(pkgDataFlags[n]);
499 }
500 }
501 uprv_free(pkgDataFlags);
502 }
503
504 if (o.cShortName != NULL) {
505 uprv_free((char *)o.cShortName);
506 }
507 if (o.fileListFiles != NULL) {
508 pkg_deleteList(o.fileListFiles);
509 }
510 if (o.filePaths != NULL) {
511 pkg_deleteList(o.filePaths);
512 }
513 if (o.files != NULL) {
514 pkg_deleteList(o.files);
515 }
516 return result;
517 }
518
519 static int runCommand(const char* command, UBool specialHandling) {
520 char *cmd = NULL;
521 char cmdBuffer[SMALL_BUFFER_MAX_SIZE];
522 int32_t len = static_cast<int32_t>(strlen(command));
523
524 if (len == 0) {
525 return 0;
526 }
527
528 if (!specialHandling) {
529 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400
530 if ((len + BUFFER_PADDING_SIZE) >= SMALL_BUFFER_MAX_SIZE) {
531 cmd = (char *)uprv_malloc(len + BUFFER_PADDING_SIZE);
532 } else {
533 cmd = cmdBuffer;
534 }
535 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
536 sprintf(cmd, "bash -c \"%s\"", command);
537
538 #elif U_PLATFORM == U_PF_OS400
539 sprintf(cmd, "QSH CMD('%s')", command);
540 #endif
541 #else
542 goto normal_command_mode;
543 #endif
544 } else {
545 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
546 normal_command_mode:
547 #endif
548 cmd = (char *)command;
549 }
550
551 printf("pkgdata: %s\n", cmd);
552 int result = system(cmd);
553 if (result != 0) {
554 fprintf(stderr, "-- return status = %d\n", result);
555 result = 1; // system() result code is platform specific.
556 }
557
558 if (cmd != cmdBuffer && cmd != command) {
559 uprv_free(cmd);
560 }
561
562 return result;
563 }
564
565 #define LN_CMD "ln -s"
566 #define RM_CMD "rm -f"
567
568 static int32_t pkg_executeOptions(UPKGOptions *o) {
569 int32_t result = 0;
570
571 const char mode = o->mode[0];
572 char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
573 char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
574 char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
575 char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
576 char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
577
578 initializePkgDataFlags(o);
579
580 if (IN_FILES_MODE(mode)) {
581 /* Copy the raw data to the installation directory. */
582 if (o->install != NULL) {
583 uprv_strcpy(targetDir, o->install);
584 if (o->shortName != NULL) {
585 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
586 uprv_strcat(targetDir, o->shortName);
587 }
588
589 if(o->verbose) {
590 fprintf(stdout, "# Install: Files mode, copying files to %s..\n", targetDir);
591 }
592 result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
593 }
594 return result;
595 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
596 UBool noVersion = FALSE;
597
598 uprv_strcpy(targetDir, o->targetDir);
599 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
600
601 uprv_strcpy(tmpDir, o->tmpDir);
602 uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
603
604 uprv_strcpy(datFileNamePath, tmpDir);
605
606 uprv_strcpy(datFileName, o->shortName);
607 uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
608
609 uprv_strcat(datFileNamePath, datFileName);
610
611 if(o->verbose) {
612 fprintf(stdout, "# Writing package file %s ..\n", datFileNamePath);
613 }
614 result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_CHARSET_FAMILY ? 'e' : U_IS_BIG_ENDIAN ? 'b' : 'l');
615 if (result != 0) {
616 fprintf(stderr,"Error writing package dat file.\n");
617 return result;
618 }
619
620 if (IN_COMMON_MODE(mode)) {
621 char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
622
623 uprv_strcpy(targetFileNamePath, targetDir);
624 uprv_strcat(targetFileNamePath, datFileName);
625
626 /* Move the dat file created to the target directory. */
627 if (uprv_strcmp(datFileNamePath, targetFileNamePath) != 0) {
628 if (T_FileStream_file_exists(targetFileNamePath)) {
629 if ((result = remove(targetFileNamePath)) != 0) {
630 fprintf(stderr, "Unable to remove old dat file: %s\n",
631 targetFileNamePath);
632 return result;
633 }
634 }
635
636 result = rename(datFileNamePath, targetFileNamePath);
637
638 if (o->verbose) {
639 fprintf(stdout, "# Moving package file to %s ..\n",
640 targetFileNamePath);
641 }
642 if (result != 0) {
643 fprintf(
644 stderr,
645 "Unable to move dat file (%s) to target location (%s).\n",
646 datFileNamePath, targetFileNamePath);
647 return result;
648 }
649 }
650
651 if (o->install != NULL) {
652 result = pkg_installCommonMode(o->install, targetFileNamePath);
653 }
654
655 return result;
656 } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ {
657 char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
658 char version_major[10] = "";
659 UBool reverseExt = FALSE;
660
661 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
662 /* Get the version major number. */
663 if (o->version != NULL) {
664 for (uint32_t i = 0;i < sizeof(version_major);i++) {
665 if (o->version[i] == '.') {
666 version_major[i] = 0;
667 break;
668 }
669 version_major[i] = o->version[i];
670 }
671 } else {
672 noVersion = TRUE;
673 if (IN_DLL_MODE(mode)) {
674 fprintf(stdout, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n");
675 }
676 }
677
678 #if U_PLATFORM != U_PF_OS400
679 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
680 * reverseExt is FALSE if the suffix should be the version number.
681 */
682 if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
683 reverseExt = TRUE;
684 }
685 #endif
686 /* Using the base libName and version number, generate the library file names. */
687 createFileNames(o, mode, version_major, o->version == NULL ? "" : o->version, o->libName, reverseExt, noVersion);
688
689 if ((o->version!=NULL || IN_STATIC_MODE(mode)) && o->rebuild == FALSE && o->pdsbuild == FALSE) {
690 /* Check to see if a previous built data library file exists and check if it is the latest. */
691 sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]);
692 if (T_FileStream_file_exists(checkLibFile)) {
693 if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) {
694 if (o->install != NULL) {
695 if(o->verbose) {
696 fprintf(stdout, "# Installing already-built library into %s\n", o->install);
697 }
698 result = pkg_installLibrary(o->install, targetDir, noVersion);
699 } else {
700 if(o->verbose) {
701 printf("# Not rebuilding %s - up to date.\n", checkLibFile);
702 }
703 }
704 return result;
705 } else if (o->verbose && (o->install!=NULL)) {
706 fprintf(stdout, "# Not installing up-to-date library %s into %s\n", checkLibFile, o->install);
707 }
708 } else if(o->verbose && (o->install!=NULL)) {
709 fprintf(stdout, "# Not installing missing %s into %s\n", checkLibFile, o->install);
710 }
711 }
712
713 if (pkg_checkFlag(o) == NULL) {
714 /* Error occurred. */
715 return result;
716 }
717 #endif
718
719 if (!o->withoutAssembly && pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
720 const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
721
722 if(o->verbose) {
723 fprintf(stdout, "# Generating assembly code %s of type %s ..\n", gencFilePath, genccodeAssembly);
724 }
725
726 /* Offset genccodeAssembly by 3 because "-a " */
727 if (genccodeAssembly &&
728 (uprv_strlen(genccodeAssembly)>3) &&
729 checkAssemblyHeaderName(genccodeAssembly+3)) {
730 writeAssemblyCode(
731 datFileNamePath,
732 o->tmpDir,
733 o->entryName,
734 NULL,
735 gencFilePath,
736 sizeof(gencFilePath));
737
738 result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
739 if (result != 0) {
740 fprintf(stderr, "Error generating assembly code for data.\n");
741 return result;
742 } else if (IN_STATIC_MODE(mode)) {
743 if(o->install != NULL) {
744 if(o->verbose) {
745 fprintf(stdout, "# Installing static library into %s\n", o->install);
746 }
747 result = pkg_installLibrary(o->install, targetDir, noVersion);
748 }
749 return result;
750 }
751 } else {
752 fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
753 return -1;
754 }
755 } else {
756 if(o->verbose) {
757 fprintf(stdout, "# Writing object code to %s ..\n", gencFilePath);
758 }
759 if (o->withoutAssembly) {
760 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
761 result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
762 #else
763 /* This error should not occur. */
764 fprintf(stderr, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
765 #endif
766 } else {
767 #ifdef CAN_WRITE_OBJ_CODE
768 /* Try to detect the arch type, use NULL if unsuccessful */
769 char optMatchArch[10] = { 0 };
770 pkg_createOptMatchArch(optMatchArch);
771 writeObjectCode(
772 datFileNamePath,
773 o->tmpDir,
774 o->entryName,
775 (optMatchArch[0] == 0 ? NULL : optMatchArch),
776 NULL,
777 gencFilePath,
778 sizeof(gencFilePath));
779 pkg_destroyOptMatchArch(optMatchArch);
780 #if U_PLATFORM_IS_LINUX_BASED
781 result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
782 #elif defined(WINDOWS_WITH_MSVC)
783 result = pkg_createWindowsDLL(mode, gencFilePath, o);
784 #endif
785 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
786 result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
787 #else
788 fprintf(stderr, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
789 return 1;
790 #endif
791 }
792
793 if (result != 0) {
794 fprintf(stderr, "Error generating package data.\n");
795 return result;
796 }
797 }
798 #if !U_PLATFORM_USES_ONLY_WIN32_API
799 if(!IN_STATIC_MODE(mode)) {
800 /* Certain platforms uses archive library. (e.g. AIX) */
801 if(o->verbose) {
802 fprintf(stdout, "# Creating data archive library file ..\n");
803 }
804 result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
805 if (result != 0) {
806 fprintf(stderr, "Error creating data archive library file.\n");
807 return result;
808 }
809 #if U_PLATFORM != U_PF_OS400
810 if (!noVersion) {
811 /* Create symbolic links for the final library file. */
812 #if U_PLATFORM == U_PF_OS390
813 result = pkg_createSymLinks(targetDir, o->pdsbuild);
814 #else
815 result = pkg_createSymLinks(targetDir, noVersion);
816 #endif
817 if (result != 0) {
818 fprintf(stderr, "Error creating symbolic links of the data library file.\n");
819 return result;
820 }
821 }
822 #endif
823 } /* !IN_STATIC_MODE */
824 #endif
825
826 #if !U_PLATFORM_USES_ONLY_WIN32_API
827 /* Install the libraries if option was set. */
828 if (o->install != NULL) {
829 if(o->verbose) {
830 fprintf(stdout, "# Installing library file to %s ..\n", o->install);
831 }
832 result = pkg_installLibrary(o->install, targetDir, noVersion);
833 if (result != 0) {
834 fprintf(stderr, "Error installing the data library.\n");
835 return result;
836 }
837 }
838 #endif
839 }
840 }
841 return result;
842 }
843
844 /* Initialize the pkgDataFlags with the option file given. */
845 static int32_t initializePkgDataFlags(UPKGOptions *o) {
846 UErrorCode status = U_ZERO_ERROR;
847 int32_t result = 0;
848 int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE;
849 int32_t tmpResult = 0;
850
851 /* Initialize pkgdataFlags */
852 pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
853
854 /* If we run out of space, allocate more */
855 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
856 do {
857 #endif
858 if (pkgDataFlags != NULL) {
859 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
860 pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize);
861 if (pkgDataFlags[i] != NULL) {
862 pkgDataFlags[i][0] = 0;
863 } else {
864 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
865 /* If an error occurs, ensure that the rest of the array is NULL */
866 for (int32_t n = i + 1; n < PKGDATA_FLAGS_SIZE; n++) {
867 pkgDataFlags[n] = NULL;
868 }
869 return -1;
870 }
871 }
872 } else {
873 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
874 return -1;
875 }
876
877 if (o->options == NULL) {
878 return result;
879 }
880
881 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
882 /* Read in options file. */
883 if(o->verbose) {
884 fprintf(stdout, "# Reading options file %s\n", o->options);
885 }
886 status = U_ZERO_ERROR;
887 tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, FLAG_NAMES, (int32_t)PKGDATA_FLAGS_SIZE, &status);
888 if (status == U_BUFFER_OVERFLOW_ERROR) {
889 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
890 if (pkgDataFlags[i]) {
891 uprv_free(pkgDataFlags[i]);
892 pkgDataFlags[i] = NULL;
893 }
894 }
895 currentBufferSize = tmpResult;
896 } else if (U_FAILURE(status)) {
897 fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status));
898 return -1;
899 }
900 #endif
901 if(o->verbose) {
902 fprintf(stdout, "# pkgDataFlags=\n");
903 for(int32_t i=0;i<PKGDATA_FLAGS_SIZE;i++) {
904 fprintf(stdout, " [%d] %s: %s\n", i, FLAG_NAMES[i], pkgDataFlags[i]);
905 }
906 fprintf(stdout, "\n");
907 }
908 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
909 } while (status == U_BUFFER_OVERFLOW_ERROR);
910 #endif
911
912 return result;
913 }
914
915
916 /*
917 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
918 * Depending on the configuration, the library name may either end with version number or shared object suffix.
919 */
920 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt, UBool noVersion) {
921 const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
922 const char* FILE_SUFFIX = pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "";
923
924 #if U_PLATFORM == U_PF_MINGW
925 /* MinGW does not need the library prefix when building in dll mode. */
926 if (IN_DLL_MODE(mode)) {
927 sprintf(libFileNames[LIB_FILE], "%s", libName);
928 } else {
929 sprintf(libFileNames[LIB_FILE], "%s%s%s",
930 (strstr(libName, "icudt") ? "lib" : ""),
931 pkgDataFlags[LIBPREFIX],
932 libName);
933 }
934 #else
935 sprintf(libFileNames[LIB_FILE], "%s%s",
936 pkgDataFlags[LIBPREFIX],
937 libName);
938 #endif
939
940 if(o->verbose) {
941 fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]);
942 }
943
944 #if U_PLATFORM == U_PF_MINGW
945 // Name the import library lib*.dll.a
946 sprintf(libFileNames[LIB_FILE_MINGW], "lib%s.dll.a", libName);
947 #elif U_PLATFORM == U_PF_CYGWIN
948 sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s%s%s",
949 libName,
950 FILE_EXTENSION_SEP,
951 pkgDataFlags[SO_EXT]);
952 sprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], "cyg%s%s%s%s",
953 libName,
954 version_major,
955 FILE_EXTENSION_SEP,
956 pkgDataFlags[SO_EXT]);
957
958 uprv_strcat(pkgDataFlags[SO_EXT], ".");
959 uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
960 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
961 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
962 libFileNames[LIB_FILE],
963 FILE_EXTENSION_SEP,
964 pkgDataFlags[SOBJ_EXT]);
965 #elif U_PLATFORM == U_PF_OS390
966 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s%s%s",
967 libFileNames[LIB_FILE],
968 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
969 reverseExt ? version : pkgDataFlags[SOBJ_EXT],
970 FILE_EXTENSION_SEP,
971 reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
972
973 sprintf(libFileNames[LIB_FILE_OS390BATCH_VERSION], "%s%s.x",
974 libFileNames[LIB_FILE],
975 version);
976 sprintf(libFileNames[LIB_FILE_OS390BATCH_MAJOR], "%s%s.x",
977 libFileNames[LIB_FILE],
978 version_major);
979 #else
980 if (noVersion && !reverseExt) {
981 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s",
982 libFileNames[LIB_FILE],
983 FILE_SUFFIX,
984 pkgDataFlags[SOBJ_EXT]);
985 } else {
986 sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s%s%s",
987 libFileNames[LIB_FILE],
988 FILE_SUFFIX,
989 reverseExt ? version : pkgDataFlags[SOBJ_EXT],
990 FILE_EXTENSION_SEP,
991 reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
992 }
993 #endif
994 if (noVersion && !reverseExt) {
995 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s",
996 libFileNames[LIB_FILE],
997 FILE_SUFFIX,
998 pkgDataFlags[SO_EXT]);
999
1000 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s",
1001 libFileNames[LIB_FILE],
1002 FILE_SUFFIX,
1003 pkgDataFlags[SO_EXT]);
1004 } else {
1005 sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s%s%s",
1006 libFileNames[LIB_FILE],
1007 FILE_SUFFIX,
1008 reverseExt ? version_major : pkgDataFlags[SO_EXT],
1009 FILE_EXTENSION_SEP,
1010 reverseExt ? pkgDataFlags[SO_EXT] : version_major);
1011
1012 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s%s%s",
1013 libFileNames[LIB_FILE],
1014 FILE_SUFFIX,
1015 reverseExt ? version : pkgDataFlags[SO_EXT],
1016 FILE_EXTENSION_SEP,
1017 reverseExt ? pkgDataFlags[SO_EXT] : version);
1018 }
1019
1020 if(o->verbose) {
1021 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]);
1022 }
1023
1024 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1025 /* Cygwin and MinGW only deals with the version major number. */
1026 uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
1027 #endif
1028
1029 if(IN_STATIC_MODE(mode)) {
1030 sprintf(libFileNames[LIB_FILE_VERSION], "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]);
1031 libFileNames[LIB_FILE_VERSION_MAJOR][0]=0;
1032 if(o->verbose) {
1033 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames[LIB_FILE_VERSION]);
1034 }
1035 }
1036 }
1037
1038 /* Create the symbolic links for the final library file. */
1039 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) {
1040 int32_t result = 0;
1041 char cmd[LARGE_BUFFER_MAX_SIZE];
1042 char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */
1043 char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */
1044 const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
1045
1046 #if U_PLATFORM != U_PF_CYGWIN
1047 /* No symbolic link to make. */
1048 if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 ||
1049 uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
1050 return result;
1051 }
1052
1053 sprintf(cmd, "cd %s && %s %s && %s %s %s",
1054 targetDir,
1055 RM_CMD,
1056 libFileNames[LIB_FILE_VERSION_MAJOR],
1057 LN_CMD,
1058 libFileNames[LIB_FILE_VERSION],
1059 libFileNames[LIB_FILE_VERSION_MAJOR]);
1060 result = runCommand(cmd);
1061 if (result != 0) {
1062 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
1063 return result;
1064 }
1065 #endif
1066
1067 if (specialHandling) {
1068 #if U_PLATFORM == U_PF_CYGWIN
1069 sprintf(name1, "%s", libFileNames[LIB_FILE_CYGWIN]);
1070 sprintf(name2, "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
1071 #elif U_PLATFORM == U_PF_OS390
1072 /* Create the symbolic links for the import data */
1073 /* Use the cmd buffer to store path to import data file to check its existence */
1074 sprintf(cmd, "%s/%s", targetDir, libFileNames[LIB_FILE_OS390BATCH_VERSION]);
1075 if (T_FileStream_file_exists(cmd)) {
1076 sprintf(cmd, "cd %s && %s %s && %s %s %s",
1077 targetDir,
1078 RM_CMD,
1079 libFileNames[LIB_FILE_OS390BATCH_MAJOR],
1080 LN_CMD,
1081 libFileNames[LIB_FILE_OS390BATCH_VERSION],
1082 libFileNames[LIB_FILE_OS390BATCH_MAJOR]);
1083 result = runCommand(cmd);
1084 if (result != 0) {
1085 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
1086 return result;
1087 }
1088
1089 sprintf(cmd, "cd %s && %s %s.x && %s %s %s.x",
1090 targetDir,
1091 RM_CMD,
1092 libFileNames[LIB_FILE],
1093 LN_CMD,
1094 libFileNames[LIB_FILE_OS390BATCH_VERSION],
1095 libFileNames[LIB_FILE]);
1096 result = runCommand(cmd);
1097 if (result != 0) {
1098 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
1099 return result;
1100 }
1101 }
1102
1103 /* Needs to be set here because special handling skips it */
1104 sprintf(name1, "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
1105 sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
1106 #else
1107 goto normal_symlink_mode;
1108 #endif
1109 } else {
1110 #if U_PLATFORM != U_PF_CYGWIN
1111 normal_symlink_mode:
1112 #endif
1113 sprintf(name1, "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
1114 sprintf(name2, "%s", libFileNames[LIB_FILE_VERSION]);
1115 }
1116
1117 sprintf(cmd, "cd %s && %s %s && %s %s %s",
1118 targetDir,
1119 RM_CMD,
1120 name1,
1121 LN_CMD,
1122 name2,
1123 name1);
1124
1125 result = runCommand(cmd);
1126
1127 return result;
1128 }
1129
1130 static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, UBool noVersion) {
1131 int32_t result = 0;
1132 char cmd[SMALL_BUFFER_MAX_SIZE];
1133
1134 sprintf(cmd, "cd %s && %s %s %s%s%s",
1135 targetDir,
1136 pkgDataFlags[INSTALL_CMD],
1137 libFileNames[LIB_FILE_VERSION],
1138 installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
1139 );
1140
1141 result = runCommand(cmd);
1142
1143 if (result != 0) {
1144 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1145 return result;
1146 }
1147
1148 #ifdef CYGWINMSVC
1149 sprintf(cmd, "cd %s && %s %s.lib %s",
1150 targetDir,
1151 pkgDataFlags[INSTALL_CMD],
1152 libFileNames[LIB_FILE],
1153 installDir
1154 );
1155 result = runCommand(cmd);
1156
1157 if (result != 0) {
1158 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1159 return result;
1160 }
1161 #elif U_PLATFORM == U_PF_CYGWIN
1162 sprintf(cmd, "cd %s && %s %s %s",
1163 targetDir,
1164 pkgDataFlags[INSTALL_CMD],
1165 libFileNames[LIB_FILE_CYGWIN_VERSION],
1166 installDir
1167 );
1168 result = runCommand(cmd);
1169
1170 if (result != 0) {
1171 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1172 return result;
1173 }
1174
1175 #elif U_PLATFORM == U_PF_OS390
1176 if (T_FileStream_file_exists(libFileNames[LIB_FILE_OS390BATCH_VERSION])) {
1177 sprintf(cmd, "%s %s %s",
1178 pkgDataFlags[INSTALL_CMD],
1179 libFileNames[LIB_FILE_OS390BATCH_VERSION],
1180 installDir
1181 );
1182 result = runCommand(cmd);
1183
1184 if (result != 0) {
1185 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1186 return result;
1187 }
1188 }
1189 #endif
1190
1191 if (noVersion) {
1192 return result;
1193 } else {
1194 return pkg_createSymLinks(installDir, TRUE);
1195 }
1196 }
1197
1198 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) {
1199 int32_t result = 0;
1200 char cmd[SMALL_BUFFER_MAX_SIZE] = "";
1201
1202 if (!T_FileStream_file_exists(installDir)) {
1203 UErrorCode status = U_ZERO_ERROR;
1204
1205 uprv_mkdir(installDir, &status);
1206 if (U_FAILURE(status)) {
1207 fprintf(stderr, "Error creating installation directory: %s\n", installDir);
1208 return -1;
1209 }
1210 }
1211 #ifndef U_WINDOWS_WITH_MSVC
1212 sprintf(cmd, "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir);
1213 #else
1214 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS);
1215 #endif
1216
1217 result = runCommand(cmd);
1218 if (result != 0) {
1219 fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
1220 }
1221
1222 return result;
1223 }
1224
1225 #ifdef U_WINDOWS_MSVC
1226 /* Copy commands for installing the raw data files on Windows. */
1227 #define WIN_INSTALL_CMD "xcopy"
1228 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
1229 #endif
1230 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
1231 int32_t result = 0;
1232 char cmd[SMALL_BUFFER_MAX_SIZE] = "";
1233
1234 if (!T_FileStream_file_exists(installDir)) {
1235 UErrorCode status = U_ZERO_ERROR;
1236
1237 uprv_mkdir(installDir, &status);
1238 if (U_FAILURE(status)) {
1239 fprintf(stderr, "Error creating installation directory: %s\n", installDir);
1240 return -1;
1241 }
1242 }
1243 #ifndef U_WINDOWS_WITH_MSVC
1244 char buffer[SMALL_BUFFER_MAX_SIZE] = "";
1245 int32_t bufferLength = 0;
1246
1247 FileStream *f = T_FileStream_open(fileListName, "r");
1248 if (f != NULL) {
1249 for(;;) {
1250 if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
1251 bufferLength = static_cast<int32_t>(uprv_strlen(buffer));
1252 /* Remove new line character. */
1253 if (bufferLength > 0) {
1254 buffer[bufferLength-1] = 0;
1255 }
1256
1257 sprintf(cmd, "%s %s%s%s %s%s%s",
1258 pkgDataFlags[INSTALL_CMD],
1259 srcDir, PKGDATA_FILE_SEP_STRING, buffer,
1260 installDir, PKGDATA_FILE_SEP_STRING, buffer);
1261
1262 result = runCommand(cmd);
1263 if (result != 0) {
1264 fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
1265 break;
1266 }
1267 } else {
1268 if (!T_FileStream_eof(f)) {
1269 fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
1270 result = -1;
1271 }
1272 break;
1273 }
1274 }
1275 T_FileStream_close(f);
1276 } else {
1277 result = -1;
1278 fprintf(stderr, "Unable to open list file: %s\n", fileListName);
1279 }
1280 #else
1281 sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
1282 result = runCommand(cmd);
1283 if (result != 0) {
1284 fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
1285 }
1286 #endif
1287
1288 return result;
1289 }
1290
1291 /* Archiving of the library file may be needed depending on the platform and options given.
1292 * If archiving is not needed, copy over the library file name.
1293 */
1294 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
1295 int32_t result = 0;
1296 char cmd[LARGE_BUFFER_MAX_SIZE];
1297
1298 /* If the shared object suffix and the final object suffix is different and the final object suffix and the
1299 * archive file suffix is the same, then the final library needs to be archived.
1300 */
1301 if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
1302 sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
1303 libFileNames[LIB_FILE],
1304 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
1305 reverseExt ? version : pkgDataFlags[SO_EXT],
1306 reverseExt ? pkgDataFlags[SO_EXT] : version);
1307
1308 sprintf(cmd, "%s %s %s%s %s%s",
1309 pkgDataFlags[AR],
1310 pkgDataFlags[ARFLAGS],
1311 targetDir,
1312 libFileNames[LIB_FILE_VERSION],
1313 targetDir,
1314 libFileNames[LIB_FILE_VERSION_TMP]);
1315
1316 result = runCommand(cmd);
1317 if (result != 0) {
1318 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
1319 return result;
1320 }
1321
1322 sprintf(cmd, "%s %s%s",
1323 pkgDataFlags[RANLIB],
1324 targetDir,
1325 libFileNames[LIB_FILE_VERSION]);
1326
1327 result = runCommand(cmd);
1328 if (result != 0) {
1329 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
1330 return result;
1331 }
1332
1333 /* Remove unneeded library file. */
1334 sprintf(cmd, "%s %s%s",
1335 RM_CMD,
1336 targetDir,
1337 libFileNames[LIB_FILE_VERSION_TMP]);
1338
1339 result = runCommand(cmd);
1340 if (result != 0) {
1341 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
1342 return result;
1343 }
1344
1345 } else {
1346 uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
1347 }
1348
1349 return result;
1350 }
1351
1352 /*
1353 * Using the compiler information from the configuration file set by -O option, generate the library file.
1354 * command may be given to allow for a larger buffer for cmd.
1355 */
1356 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command, UBool specialHandling) {
1357 int32_t result = 0;
1358 char *cmd = NULL;
1359 UBool freeCmd = FALSE;
1360 int32_t length = 0;
1361
1362 (void)specialHandling; // Suppress unused variable compiler warnings on platforms where all usage
1363 // of this parameter is #ifdefed out.
1364
1365 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
1366 * containing many object files and so the calling function should supply a command buffer that is large
1367 * enough to handle this. Otherwise, use the default size.
1368 */
1369 if (command != NULL) {
1370 cmd = command;
1371 }
1372
1373 if (IN_STATIC_MODE(mode)) {
1374 if (cmd == NULL) {
1375 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) +
1376 uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE);
1377 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
1378 fprintf(stderr, "Unable to allocate memory for command.\n");
1379 return -1;
1380 }
1381 freeCmd = TRUE;
1382 }
1383 sprintf(cmd, "%s %s %s%s %s",
1384 pkgDataFlags[AR],
1385 pkgDataFlags[ARFLAGS],
1386 targetDir,
1387 libFileNames[LIB_FILE_VERSION],
1388 objectFile);
1389
1390 result = runCommand(cmd);
1391 if (result == 0) {
1392 sprintf(cmd, "%s %s%s",
1393 pkgDataFlags[RANLIB],
1394 targetDir,
1395 libFileNames[LIB_FILE_VERSION]);
1396
1397 result = runCommand(cmd);
1398 }
1399 } else /* if (IN_DLL_MODE(mode)) */ {
1400 if (cmd == NULL) {
1401 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) +
1402 ((uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP])) * 2) +
1403 uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) +
1404 uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) +
1405 uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE);
1406 #if U_PLATFORM == U_PF_CYGWIN
1407 length += static_cast<int32_t>(uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]));
1408 #elif U_PLATFORM == U_PF_MINGW
1409 length += static_cast<int32_t>(uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_MINGW]));
1410 #endif
1411 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == NULL) {
1412 fprintf(stderr, "Unable to allocate memory for command.\n");
1413 return -1;
1414 }
1415 freeCmd = TRUE;
1416 }
1417 #if U_PLATFORM == U_PF_MINGW
1418 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
1419 pkgDataFlags[GENLIB],
1420 targetDir,
1421 libFileNames[LIB_FILE_MINGW],
1422 pkgDataFlags[LDICUDTFLAGS],
1423 targetDir,
1424 libFileNames[LIB_FILE_VERSION_TMP],
1425 #elif U_PLATFORM == U_PF_CYGWIN
1426 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
1427 pkgDataFlags[GENLIB],
1428 targetDir,
1429 libFileNames[LIB_FILE_VERSION_TMP],
1430 pkgDataFlags[LDICUDTFLAGS],
1431 targetDir,
1432 libFileNames[LIB_FILE_CYGWIN_VERSION],
1433 #elif U_PLATFORM == U_PF_AIX
1434 sprintf(cmd, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
1435 RM_CMD,
1436 targetDir,
1437 libFileNames[LIB_FILE_VERSION_TMP],
1438 pkgDataFlags[GENLIB],
1439 pkgDataFlags[LDICUDTFLAGS],
1440 targetDir,
1441 libFileNames[LIB_FILE_VERSION_TMP],
1442 #else
1443 sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
1444 pkgDataFlags[GENLIB],
1445 pkgDataFlags[LDICUDTFLAGS],
1446 targetDir,
1447 libFileNames[LIB_FILE_VERSION_TMP],
1448 #endif
1449 objectFile,
1450 pkgDataFlags[LD_SONAME],
1451 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
1452 pkgDataFlags[RPATH_FLAGS],
1453 pkgDataFlags[BIR_FLAGS]);
1454
1455 /* Generate the library file. */
1456 result = runCommand(cmd);
1457
1458 #if U_PLATFORM == U_PF_OS390
1459 char *env_tmp;
1460 char PDS_LibName[512];
1461 char PDS_Name[512];
1462
1463 PDS_Name[0] = 0;
1464 PDS_LibName[0] = 0;
1465 if (specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) {
1466 if (env_tmp = getenv("ICU_PDS_NAME")) {
1467 sprintf(PDS_Name, "%s%s",
1468 env_tmp,
1469 "DA");
1470 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
1471 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
1472 sprintf(PDS_Name, "%s%s",
1473 env_tmp,
1474 U_ICU_VERSION_SHORT "DA");
1475 } else {
1476 sprintf(PDS_Name, "%s%s",
1477 "IXMI",
1478 U_ICU_VERSION_SHORT "DA");
1479 }
1480 } else if (!specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) {
1481 if (env_tmp = getenv("ICU_PDS_NAME")) {
1482 sprintf(PDS_Name, "%s%s",
1483 env_tmp,
1484 "D1");
1485 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
1486 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
1487 sprintf(PDS_Name, "%s%s",
1488 env_tmp,
1489 U_ICU_VERSION_SHORT "D1");
1490 } else {
1491 sprintf(PDS_Name, "%s%s",
1492 "IXMI",
1493 U_ICU_VERSION_SHORT "D1");
1494 }
1495 }
1496
1497 if (PDS_Name[0]) {
1498 sprintf(PDS_LibName,"%s%s%s%s%s",
1499 "\"//'",
1500 getenv("LOADMOD"),
1501 "(",
1502 PDS_Name,
1503 ")'\"");
1504 sprintf(cmd, "%s %s -o %s %s %s%s %s %s",
1505 pkgDataFlags[GENLIB],
1506 pkgDataFlags[LDICUDTFLAGS],
1507 PDS_LibName,
1508 objectFile,
1509 pkgDataFlags[LD_SONAME],
1510 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
1511 pkgDataFlags[RPATH_FLAGS],
1512 pkgDataFlags[BIR_FLAGS]);
1513
1514 result = runCommand(cmd);
1515 }
1516 #endif
1517 }
1518
1519 if (result != 0) {
1520 fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd);
1521 }
1522
1523 if (freeCmd) {
1524 uprv_free(cmd);
1525 }
1526
1527 return result;
1528 }
1529
1530 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
1531 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
1532 int32_t result = 0;
1533 int32_t length = 0;
1534
1535 /* Remove the ending .s and replace it with .o for the new object file. */
1536 uprv_strcpy(tempObjectFile, gencFilePath);
1537 tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
1538
1539 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
1540 + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE);
1541
1542 LocalMemory<char> cmd((char *)uprv_malloc(sizeof(char) * length));
1543 if (cmd.isNull()) {
1544 return -1;
1545 }
1546
1547 /* Generate the object file. */
1548 sprintf(cmd.getAlias(), "%s %s -o %s %s",
1549 pkgDataFlags[COMPILER],
1550 pkgDataFlags[LIBFLAGS],
1551 tempObjectFile,
1552 gencFilePath);
1553
1554 result = runCommand(cmd.getAlias());
1555
1556 if (result != 0) {
1557 fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd.getAlias());
1558 return result;
1559 }
1560
1561 return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
1562 }
1563
1564 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
1565 /*
1566 * Generation of the data library without assembly code needs to compile each data file
1567 * individually and then link it all together.
1568 * Note: Any update to the directory structure of the data needs to be reflected here.
1569 */
1570 enum {
1571 DATA_PREFIX_BRKITR,
1572 DATA_PREFIX_COLL,
1573 DATA_PREFIX_CURR,
1574 DATA_PREFIX_LANG,
1575 DATA_PREFIX_RBNF,
1576 DATA_PREFIX_REGION,
1577 DATA_PREFIX_TRANSLIT,
1578 DATA_PREFIX_ZONE,
1579 DATA_PREFIX_UNIT,
1580 DATA_PREFIX_LENGTH
1581 };
1582
1583 const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
1584 "brkitr",
1585 "coll",
1586 "curr",
1587 "lang",
1588 "rbnf",
1589 "region",
1590 "translit",
1591 "zone",
1592 "unit"
1593 };
1594
1595 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
1596 int32_t result = 0;
1597 CharList *list = o->filePaths;
1598 CharList *listNames = o->files;
1599 int32_t listSize = pkg_countCharList(list);
1600 char *buffer;
1601 char *cmd;
1602 char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
1603 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
1604 #ifdef USE_SINGLE_CCODE_FILE
1605 char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
1606 FileStream *icudtAllFile = NULL;
1607
1608 sprintf(icudtAll, "%s%s%sall.c",
1609 o->tmpDir,
1610 PKGDATA_FILE_SEP_STRING,
1611 libFileNames[LIB_FILE]);
1612 /* Remove previous icudtall.c file. */
1613 if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
1614 fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
1615 return result;
1616 }
1617
1618 if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==NULL) {
1619 fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll);
1620 return result;
1621 }
1622 #endif
1623
1624 if (list == NULL || listNames == NULL) {
1625 /* list and listNames should never be NULL since we are looping through the CharList with
1626 * the given size.
1627 */
1628 return -1;
1629 }
1630
1631 if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
1632 fprintf(stderr, "Unable to allocate memory for cmd.\n");
1633 return -1;
1634 } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
1635 fprintf(stderr, "Unable to allocate memory for buffer.\n");
1636 uprv_free(cmd);
1637 return -1;
1638 }
1639
1640 for (int32_t i = 0; i < (listSize + 1); i++) {
1641 const char *file ;
1642 const char *name;
1643
1644 if (i == 0) {
1645 /* The first iteration calls the gencmn function and initailizes the buffer. */
1646 createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
1647 buffer[0] = 0;
1648 #ifdef USE_SINGLE_CCODE_FILE
1649 uprv_strcpy(tempObjectFile, gencmnFile);
1650 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
1651
1652 sprintf(cmd, "%s %s -o %s %s",
1653 pkgDataFlags[COMPILER],
1654 pkgDataFlags[LIBFLAGS],
1655 tempObjectFile,
1656 gencmnFile);
1657
1658 result = runCommand(cmd);
1659 if (result != 0) {
1660 break;
1661 }
1662
1663 sprintf(buffer, "%s",tempObjectFile);
1664 #endif
1665 } else {
1666 char newName[SMALL_BUFFER_MAX_SIZE];
1667 char dataName[SMALL_BUFFER_MAX_SIZE];
1668 char dataDirName[SMALL_BUFFER_MAX_SIZE];
1669 const char *pSubstring;
1670 file = list->str;
1671 name = listNames->str;
1672
1673 newName[0] = dataName[0] = 0;
1674 for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
1675 dataDirName[0] = 0;
1676 sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
1677 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
1678 pSubstring = uprv_strstr(name, dataDirName);
1679 if (pSubstring != NULL) {
1680 char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
1681 const char *p = name + uprv_strlen(dataDirName);
1682 for (int32_t i = 0;;i++) {
1683 if (p[i] == '.') {
1684 newNameTmp[i] = '_';
1685 continue;
1686 }
1687 newNameTmp[i] = p[i];
1688 if (p[i] == 0) {
1689 break;
1690 }
1691 }
1692 sprintf(newName, "%s_%s",
1693 DATA_PREFIX[n],
1694 newNameTmp);
1695 sprintf(dataName, "%s_%s",
1696 o->shortName,
1697 DATA_PREFIX[n]);
1698 }
1699 if (newName[0] != 0) {
1700 break;
1701 }
1702 }
1703
1704 if(o->verbose) {
1705 printf("# Generating %s \n", gencmnFile);
1706 }
1707
1708 writeCCode(
1709 file,
1710 o->tmpDir,
1711 dataName[0] != 0 ? dataName : o->shortName,
1712 newName[0] != 0 ? newName : NULL,
1713 gencmnFile,
1714 sizeof(gencmnFile));
1715
1716 #ifdef USE_SINGLE_CCODE_FILE
1717 sprintf(cmd, "#include \"%s\"\n", gencmnFile);
1718 T_FileStream_writeLine(icudtAllFile, cmd);
1719 /* don't delete the file */
1720 #endif
1721 }
1722
1723 #ifndef USE_SINGLE_CCODE_FILE
1724 uprv_strcpy(tempObjectFile, gencmnFile);
1725 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
1726
1727 sprintf(cmd, "%s %s -o %s %s",
1728 pkgDataFlags[COMPILER],
1729 pkgDataFlags[LIBFLAGS],
1730 tempObjectFile,
1731 gencmnFile);
1732 result = runCommand(cmd);
1733 if (result != 0) {
1734 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
1735 break;
1736 }
1737
1738 uprv_strcat(buffer, " ");
1739 uprv_strcat(buffer, tempObjectFile);
1740
1741 #endif
1742
1743 if (i > 0) {
1744 list = list->next;
1745 listNames = listNames->next;
1746 }
1747 }
1748
1749 #ifdef USE_SINGLE_CCODE_FILE
1750 T_FileStream_close(icudtAllFile);
1751 uprv_strcpy(tempObjectFile, icudtAll);
1752 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
1753
1754 sprintf(cmd, "%s %s -I. -o %s %s",
1755 pkgDataFlags[COMPILER],
1756 pkgDataFlags[LIBFLAGS],
1757 tempObjectFile,
1758 icudtAll);
1759
1760 result = runCommand(cmd);
1761 if (result == 0) {
1762 uprv_strcat(buffer, " ");
1763 uprv_strcat(buffer, tempObjectFile);
1764 } else {
1765 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
1766 }
1767 #endif
1768
1769 if (result == 0) {
1770 /* Generate the library file. */
1771 #if U_PLATFORM == U_PF_OS390
1772 result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd, (o->pdsbuild && IN_DLL_MODE(mode)));
1773 #else
1774 result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
1775 #endif
1776 }
1777
1778 uprv_free(buffer);
1779 uprv_free(cmd);
1780
1781 return result;
1782 }
1783 #endif
1784
1785 #ifdef WINDOWS_WITH_MSVC
1786 #define LINK_CMD "link.exe /nologo /release /out:"
1787 #define LINK_FLAGS "/NXCOMPAT /DYNAMICBASE /DLL /NOENTRY /MANIFEST:NO /implib:"
1788
1789 #define LINK_EXTRA_UWP_FLAGS "/APPCONTAINER "
1790 #define LINK_EXTRA_UWP_FLAGS_X86_ONLY "/SAFESEH "
1791
1792 #define LINK_EXTRA_FLAGS_MACHINE "/MACHINE:"
1793 #define LIB_CMD "LIB.exe /nologo /out:"
1794 #define LIB_FILE "icudt.lib"
1795 #define LIB_EXT UDATA_LIB_SUFFIX
1796 #define DLL_EXT UDATA_SO_SUFFIX
1797
1798 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
1799 int32_t result = 0;
1800 char cmd[LARGE_BUFFER_MAX_SIZE];
1801 if (IN_STATIC_MODE(mode)) {
1802 char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1803
1804 #ifdef CYGWINMSVC
1805 sprintf(staticLibFilePath, "%s%s%s%s%s",
1806 o->targetDir,
1807 PKGDATA_FILE_SEP_STRING,
1808 pkgDataFlags[LIBPREFIX],
1809 o->libName,
1810 LIB_EXT);
1811 #else
1812 sprintf(staticLibFilePath, "%s%s%s%s%s",
1813 o->targetDir,
1814 PKGDATA_FILE_SEP_STRING,
1815 (strstr(o->libName, "icudt") ? "s" : ""),
1816 o->libName,
1817 LIB_EXT);
1818 #endif
1819
1820 sprintf(cmd, "%s\"%s\" \"%s\"",
1821 LIB_CMD,
1822 staticLibFilePath,
1823 gencFilePath);
1824 } else if (IN_DLL_MODE(mode)) {
1825 char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1826 char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1827 char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1828 char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1829
1830 #ifdef CYGWINMSVC
1831 uprv_strcpy(dllFilePath, o->targetDir);
1832 #else
1833 uprv_strcpy(dllFilePath, o->srcDir);
1834 #endif
1835 uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
1836 uprv_strcpy(libFilePath, dllFilePath);
1837
1838 #ifdef CYGWINMSVC
1839 uprv_strcat(libFilePath, o->libName);
1840 uprv_strcat(libFilePath, ".lib");
1841
1842 uprv_strcat(dllFilePath, o->libName);
1843 uprv_strcat(dllFilePath, o->version);
1844 #else
1845 if (strstr(o->libName, "icudt")) {
1846 uprv_strcat(libFilePath, LIB_FILE);
1847 } else {
1848 uprv_strcat(libFilePath, o->libName);
1849 uprv_strcat(libFilePath, ".lib");
1850 }
1851 uprv_strcat(dllFilePath, o->entryName);
1852 #endif
1853 uprv_strcat(dllFilePath, DLL_EXT);
1854
1855 uprv_strcpy(tmpResFilePath, o->tmpDir);
1856 uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
1857 uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
1858
1859 if (T_FileStream_file_exists(tmpResFilePath)) {
1860 sprintf(resFilePath, "\"%s\"", tmpResFilePath);
1861 }
1862
1863 /* Check if dll file and lib file exists and that it is not newer than genc file. */
1864 if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
1865 (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
1866 if(o->verbose) {
1867 printf("# Not rebuilding %s - up to date.\n", gencFilePath);
1868 }
1869 return 0;
1870 }
1871
1872 char extraFlags[SMALL_BUFFER_MAX_SIZE] = "";
1873 #ifdef WINDOWS_WITH_MSVC
1874 if (options[WIN_UWP_BUILD].doesOccur) {
1875 uprv_strcat(extraFlags, LINK_EXTRA_UWP_FLAGS);
1876
1877 if (options[WIN_DLL_ARCH].doesOccur) {
1878 if (uprv_strcmp(options[WIN_DLL_ARCH].value, "X86") == 0) {
1879 uprv_strcat(extraFlags, LINK_EXTRA_UWP_FLAGS_X86_ONLY);
1880 }
1881 }
1882 }
1883
1884 if (options[WIN_DLL_ARCH].doesOccur) {
1885 uprv_strcat(extraFlags, LINK_EXTRA_FLAGS_MACHINE);
1886 uprv_strcat(extraFlags, options[WIN_DLL_ARCH].value);
1887 }
1888
1889 #endif
1890 sprintf(cmd, "%s\"%s\" %s %s\"%s\" \"%s\" %s",
1891 LINK_CMD,
1892 dllFilePath,
1893 extraFlags,
1894 LINK_FLAGS,
1895 libFilePath,
1896 gencFilePath,
1897 resFilePath
1898 );
1899 }
1900
1901 result = runCommand(cmd, TRUE);
1902 if (result != 0) {
1903 fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd);
1904 }
1905
1906 return result;
1907 }
1908 #endif
1909
1910 static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
1911 #if U_PLATFORM == U_PF_AIX
1912 /* AIX needs a map file. */
1913 char *flag = NULL;
1914 int32_t length = 0;
1915 char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
1916 const char MAP_FILE_EXT[] = ".map";
1917 FileStream *f = NULL;
1918 char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
1919 int32_t start = -1;
1920 uint32_t count = 0;
1921 const char rm_cmd[] = "rm -f all ;";
1922
1923 flag = pkgDataFlags[GENLIB];
1924
1925 /* This portion of the code removes 'rm -f all' in the GENLIB.
1926 * Only occurs in AIX.
1927 */
1928 if (uprv_strstr(flag, rm_cmd) != NULL) {
1929 char *tmpGenlibFlagBuffer = NULL;
1930 int32_t i, offset;
1931
1932 length = static_cast<int32_t>(uprv_strlen(flag) + 1);
1933 tmpGenlibFlagBuffer = (char *)uprv_malloc(length);
1934 if (tmpGenlibFlagBuffer == NULL) {
1935 /* Memory allocation error */
1936 fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length);
1937 return NULL;
1938 }
1939
1940 uprv_strcpy(tmpGenlibFlagBuffer, flag);
1941
1942 offset = static_cast<int32_t>(uprv_strlen(rm_cmd));
1943
1944 for (i = 0; i < (length - offset); i++) {
1945 flag[i] = tmpGenlibFlagBuffer[offset + i];
1946 }
1947
1948 /* Zero terminate the string */
1949 flag[i] = 0;
1950
1951 uprv_free(tmpGenlibFlagBuffer);
1952 }
1953
1954 flag = pkgDataFlags[BIR_FLAGS];
1955 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[BIR_FLAGS]));
1956
1957 for (int32_t i = 0; i < length; i++) {
1958 if (flag[i] == MAP_FILE_EXT[count]) {
1959 if (count == 0) {
1960 start = i;
1961 }
1962 count++;
1963 } else {
1964 count = 0;
1965 }
1966
1967 if (count == uprv_strlen(MAP_FILE_EXT)) {
1968 break;
1969 }
1970 }
1971
1972 if (start >= 0) {
1973 int32_t index = 0;
1974 for (int32_t i = 0;;i++) {
1975 if (i == start) {
1976 for (int32_t n = 0;;n++) {
1977 if (o->shortName[n] == 0) {
1978 break;
1979 }
1980 tmpbuffer[index++] = o->shortName[n];
1981 }
1982 }
1983
1984 tmpbuffer[index++] = flag[i];
1985
1986 if (flag[i] == 0) {
1987 break;
1988 }
1989 }
1990
1991 uprv_memset(flag, 0, length);
1992 uprv_strcpy(flag, tmpbuffer);
1993
1994 uprv_strcpy(mapFile, o->shortName);
1995 uprv_strcat(mapFile, MAP_FILE_EXT);
1996
1997 f = T_FileStream_open(mapFile, "w");
1998 if (f == NULL) {
1999 fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
2000 return NULL;
2001 } else {
2002 sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
2003
2004 T_FileStream_writeLine(f, tmpbuffer);
2005
2006 T_FileStream_close(f);
2007 }
2008 }
2009 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
2010 /* Cygwin needs to change flag options. */
2011 char *flag = NULL;
2012 int32_t length = 0;
2013
2014 flag = pkgDataFlags[GENLIB];
2015 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[GENLIB]));
2016
2017 int32_t position = length - 1;
2018
2019 for(;position >= 0;position--) {
2020 if (flag[position] == '=') {
2021 position++;
2022 break;
2023 }
2024 }
2025
2026 uprv_memset(flag + position, 0, length - position);
2027 #elif U_PLATFORM == U_PF_OS400
2028 /* OS/400 needs to fix the ld options (swap single quote with double quote) */
2029 char *flag = NULL;
2030 int32_t length = 0;
2031
2032 flag = pkgDataFlags[GENLIB];
2033 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[GENLIB]));
2034
2035 int32_t position = length - 1;
2036
2037 for(int32_t i = 0; i < length; i++) {
2038 if (flag[i] == '\'') {
2039 flag[i] = '\"';
2040 }
2041 }
2042 #endif
2043 // Don't really need a return value, just need to stop compiler warnings about
2044 // the unused parameter 'o' on platforms where it is not otherwise used.
2045 return o;
2046 }
2047
2048 static void loadLists(UPKGOptions *o, UErrorCode *status)
2049 {
2050 CharList *l, *tail = NULL, *tail2 = NULL;
2051 FileStream *in;
2052 char line[16384];
2053 char *linePtr, *lineNext;
2054 const uint32_t lineMax = 16300;
2055 char *tmp;
2056 int32_t tmpLength = 0;
2057 char *s;
2058 int32_t ln=0; /* line number */
2059
2060 for(l = o->fileListFiles; l; l = l->next) {
2061 if(o->verbose) {
2062 fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
2063 }
2064 /* TODO: stdin */
2065 in = T_FileStream_open(l->str, "r"); /* open files list */
2066
2067 if(!in) {
2068 fprintf(stderr, "Error opening <%s>.\n", l->str);
2069 *status = U_FILE_ACCESS_ERROR;
2070 return;
2071 }
2072
2073 while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
2074 ln++;
2075 if(uprv_strlen(line)>lineMax) {
2076 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
2077 exit(1);
2078 }
2079 /* remove spaces at the beginning */
2080 linePtr = line;
2081 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */
2082 #if U_PLATFORM != U_PF_OS390
2083 while(isspace(*linePtr)) {
2084 linePtr++;
2085 }
2086 #endif
2087 s=linePtr;
2088 /* remove trailing newline characters */
2089 while(*s!=0) {
2090 if(*s=='\r' || *s=='\n') {
2091 *s=0;
2092 break;
2093 }
2094 ++s;
2095 }
2096 if((*linePtr == 0) || (*linePtr == '#')) {
2097 continue; /* comment or empty line */
2098 }
2099
2100 /* Now, process the line */
2101 lineNext = NULL;
2102
2103 while(linePtr && *linePtr) { /* process space-separated items */
2104 while(*linePtr == ' ') {
2105 linePtr++;
2106 }
2107 /* Find the next quote */
2108 if(linePtr[0] == '"')
2109 {
2110 lineNext = uprv_strchr(linePtr+1, '"');
2111 if(lineNext == NULL) {
2112 fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
2113 l->str, (int)ln);
2114 exit(1);
2115 } else {
2116 lineNext++;
2117 if(*lineNext) {
2118 if(*lineNext != ' ') {
2119 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
2120 l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
2121 exit(1);
2122 }
2123 *lineNext = 0;
2124 lineNext++;
2125 }
2126 }
2127 } else {
2128 lineNext = uprv_strchr(linePtr, ' ');
2129 if(lineNext) {
2130 *lineNext = 0; /* terminate at space */
2131 lineNext++;
2132 }
2133 }
2134
2135 /* add the file */
2136 s = (char*)getLongPathname(linePtr);
2137
2138 /* normal mode.. o->files is just the bare list without package names */
2139 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
2140 if(uprv_pathIsAbsolute(s) || s[0] == '.') {
2141 fprintf(stderr, "pkgdata: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, s);
2142 exit(U_ILLEGAL_ARGUMENT_ERROR);
2143 }
2144 /* The +5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
2145 tmpLength = static_cast<int32_t>(uprv_strlen(o->srcDir) + uprv_strlen(s) + 5);
2146 if((tmp = (char *)uprv_malloc(tmpLength)) == NULL) {
2147 fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength);
2148 exit(U_MEMORY_ALLOCATION_ERROR);
2149 }
2150 uprv_strcpy(tmp, o->srcDir);
2151 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING);
2152 uprv_strcat(tmp, s);
2153 o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp);
2154 linePtr = lineNext;
2155 } /* for each entry on line */
2156 } /* for each line */
2157 T_FileStream_close(in);
2158 } /* for each file list file */
2159 }
2160
2161 /* Try calling icu-config directly to get the option file. */
2162 static int32_t pkg_getOptionsFromICUConfig(UBool verbose, UOption *option) {
2163 #if U_HAVE_POPEN
2164 LocalPipeFilePointer p;
2165 size_t n;
2166 static char buf[512] = "";
2167 icu::CharString cmdBuf;
2168 UErrorCode status = U_ZERO_ERROR;
2169 const char cmd[] = "icu-config --incpkgdatafile";
2170 char dirBuf[1024] = "";
2171 /* #1 try the same path where pkgdata was called from. */
2172 findDirname(progname, dirBuf, UPRV_LENGTHOF(dirBuf), &status);
2173 if(U_SUCCESS(status)) {
2174 cmdBuf.append(dirBuf, status);
2175 if (cmdBuf[0] != 0) {
2176 cmdBuf.append( U_FILE_SEP_STRING, status );
2177 }
2178 cmdBuf.append( cmd, status );
2179
2180 if(verbose) {
2181 fprintf(stdout, "# Calling icu-config: %s\n", cmdBuf.data());
2182 }
2183 p.adoptInstead(popen(cmdBuf.data(), "r"));
2184 }
2185
2186 if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) {
2187 if(verbose) {
2188 fprintf(stdout, "# Calling icu-config: %s\n", cmd);
2189 }
2190
2191 p.adoptInstead(popen(cmd, "r"));
2192 if(p.isNull() || (n = fread(buf, 1, UPRV_LENGTHOF(buf)-1, p.getAlias())) <= 0) {
2193 fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
2194 return -1;
2195 }
2196 }
2197
2198 for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
2199 if (buf[length] == '\n' || buf[length] == ' ') {
2200 buf[length] = 0;
2201 } else {
2202 break;
2203 }
2204 }
2205
2206 if(buf[strlen(buf)-1]=='\n')
2207 {
2208 buf[strlen(buf)-1]=0;
2209 }
2210
2211 if(buf[0] == 0)
2212 {
2213 fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
2214 return -1;
2215 }
2216
2217 if(verbose) {
2218 fprintf(stdout, "# icu-config said: %s\n", buf);
2219 }
2220
2221 option->value = buf;
2222 option->doesOccur = TRUE;
2223
2224 return 0;
2225 #else
2226 return -1;
2227 #endif
2228 }
2229
2230 #ifdef CAN_WRITE_OBJ_CODE
2231 /* Create optMatchArch for genccode architecture detection */
2232 static void pkg_createOptMatchArch(char *optMatchArch) {
2233 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
2234 const char* code = "void oma(){}";
2235 const char* source = "oma.c";
2236 const char* obj = "oma.obj";
2237 FileStream* stream = NULL;
2238
2239 stream = T_FileStream_open(source,"w");
2240 if (stream != NULL) {
2241 T_FileStream_writeLine(stream, code);
2242 T_FileStream_close(stream);
2243
2244 char cmd[LARGE_BUFFER_MAX_SIZE];
2245 sprintf(cmd, "%s %s -o %s",
2246 pkgDataFlags[COMPILER],
2247 source,
2248 obj);
2249
2250 if (runCommand(cmd) == 0){
2251 sprintf(optMatchArch, "%s", obj);
2252 }
2253 else {
2254 fprintf(stderr, "Failed to compile %s\n", source);
2255 }
2256 if(!T_FileStream_remove(source)){
2257 fprintf(stderr, "T_FileStream_remove failed to delete %s\n", source);
2258 }
2259 }
2260 else {
2261 fprintf(stderr, "T_FileStream_open failed to open %s for writing\n", source);
2262 }
2263 #endif
2264 }
2265 static void pkg_destroyOptMatchArch(char *optMatchArch) {
2266 if(T_FileStream_file_exists(optMatchArch) && !T_FileStream_remove(optMatchArch)){
2267 fprintf(stderr, "T_FileStream_remove failed to delete %s\n", optMatchArch);
2268 }
2269 }
2270 #endif