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