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)
12 * created on: 2000may15
13 * created by: Steven \u24C7 Loomis
15 * This program packages the ICU data into different forms
16 * (DLL, common data, etc.)
19 // Defines _XOPEN_SOURCE for access to POSIX functions.
20 // Must be before any other #includes.
21 #include "uposixdefs.h"
23 #include "unicode/utypes.h"
25 #include "unicode/putil.h"
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__
39 #include "unicode/uclean.h"
45 #include "pkg_gencmn.h"
46 #include "flagparser.h"
47 #include "filetools.h"
63 using icu::LocalPointerBase
;
65 U_DEFINE_LOCAL_OPEN_POINTER(LocalPipeFilePointer
, FILE, pclose
);
69 using icu::LocalMemory
;
71 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
);
73 static int32_t pkg_executeOptions(UPKGOptions
*o
);
75 #ifdef WINDOWS_WITH_MSVC
76 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
);
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
);
83 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
84 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
);
87 #ifdef CAN_WRITE_OBJ_CODE
88 static void pkg_createOptMatchArch(char *optMatchArch
);
89 static void pkg_destroyOptMatchArch(char *optMatchArch
);
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
);
98 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
);
99 static int runCommand(const char* command
, UBool specialHandling
=FALSE
);
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')
132 /* This sets the modes that are available */
134 const char *name
, *alt_name
;
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
}
143 #ifdef UDATA_SO_SUFFIX
144 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX
},
146 { "common", "archive", "Generates one common data file, <package>.dat" },
147 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
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
),
177 /* This enum and the following char array should be kept in sync. */
179 GENCCODE_ASSEMBLY_TYPE
,
198 static const char* FLAG_NAMES
[PKGDATA_FLAGS_SIZE
] = {
199 "GENCCODE_ASSEMBLY_TYPE",
217 static char **pkgDataFlags
= NULL
;
221 LIB_FILE_VERSION_MAJOR
,
223 LIB_FILE_VERSION_TMP
,
224 #if U_PLATFORM == U_PF_CYGWIN
226 LIB_FILE_CYGWIN_VERSION
,
227 #elif U_PLATFORM == U_PF_MINGW
229 #elif U_PLATFORM == U_PF_OS390
230 LIB_FILE_OS390BATCH_MAJOR
,
231 LIB_FILE_OS390BATCH_VERSION
,
235 static char libFileNames
[LIB_FILENAMES_SIZE
][256];
237 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
);
239 const char options_help
[][320]={
241 #ifdef U_MAKE_IS_NMAKE
242 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
244 "Specify options for the builder.",
246 "Specify the mode of building (see below; default: common)",
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)",
269 const char *progname
= "PKGDATA";
272 main(int argc
, char* argv
[]) {
274 /* FileStream *out; */
277 UBool needsHelp
= FALSE
;
278 UErrorCode status
= U_ZERO_ERROR
;
279 /* char tmp[1024]; */
283 U_MAIN_INIT_ARGS(argc
, argv
);
287 options
[MODE
].value
= "common";
289 /* read command line options */
290 argc
=u_parseArgs(argc
, argv
, UPRV_LENGTHOF(options
), options
);
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. */
296 if(options
[HELP
].doesOccur
|| options
[HELP_QUESTION_MARK
].doesOccur
) {
300 if(!needsHelp
&& argc
<0) {
302 "%s: error in command line argument \"%s\"\n",
305 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
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
);
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");
324 if(!options
[NAME
].doesOccur
) /* -O we already have - don't report it. */
326 fprintf(stderr
, " required parameter -p is missing \n");
327 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
333 "No input files specified.\n"
334 "Run '%s --help' for help.\n", progname
);
337 } /* end !needsHelp */
339 if(argc
<0 || needsHelp
) {
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",
347 fprintf(stderr
, "\n options:\n");
348 for(i
=0;i
<UPRV_LENGTHOF(options
);i
++) {
349 fprintf(stderr
, "%-5s -%c %s%-10s %s\n",
351 options
[i
].shortName
,
352 options
[i
].longName
? "or --" : " ",
353 options
[i
].longName
? options
[i
].longName
: "",
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
);
363 fprintf(stderr
, " ");
365 fprintf(stderr
, " %s\n", modes
[i
].desc
);
370 /* OK, fill in the options struct */
371 uprv_memset(&o
, 0, sizeof(o
));
373 o
.mode
= options
[MODE
].value
;
374 o
.version
= options
[REVISION
].doesOccur
? options
[REVISION
].value
: 0;
376 o
.shortName
= options
[NAME
].value
;
378 int32_t len
= (int32_t)uprv_strlen(o
.shortName
);
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
: '_';
391 o
.cShortName
= csname
;
394 if(options
[LIBNAME
].doesOccur
) { /* get libname from shortname, or explicit -L parameter */
395 o
.libName
= options
[LIBNAME
].value
;
397 o
.libName
= o
.shortName
;
400 if(options
[QUIET
].doesOccur
) {
406 if(options
[PDS_BUILD
].doesOccur
) {
407 #if U_PLATFORM == U_PF_OS390
411 fprintf(stdout
, "Warning: You are using the -z option which only works on z/OS.\n");
418 o
.verbose
= options
[VERBOSE
].doesOccur
;
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
;
428 if(options
[COPYRIGHT
].doesOccur
) {
429 o
.comment
= U_COPYRIGHT_STRING
;
430 } else if (options
[COMMENT
].doesOccur
) {
431 o
.comment
= options
[COMMENT
].value
;
434 if( options
[DESTDIR
].doesOccur
) {
435 o
.targetDir
= options
[DESTDIR
].value
;
437 o
.targetDir
= "."; /* cwd */
440 o
.rebuild
= options
[REBUILD
].doesOccur
;
442 if( options
[TEMPDIR
].doesOccur
) {
443 o
.tmpDir
= options
[TEMPDIR
].value
;
445 o
.tmpDir
= o
.targetDir
;
448 if( options
[INSTALL
].doesOccur
) {
449 o
.install
= options
[INSTALL
].value
;
454 if( options
[SOURCEDIR
].doesOccur
) {
455 o
.srcDir
= options
[SOURCEDIR
].value
;
460 if( options
[ENTRYPOINT
].doesOccur
) {
461 o
.entryName
= options
[ENTRYPOINT
].value
;
463 o
.entryName
= o
.cShortName
;
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");
472 o
.withoutAssembly
= TRUE
;
476 if (options
[WIN_DYNAMICBASE
].doesOccur
) {
477 fprintf(stdout
, "Note: Ignoring option -b (windows-dynamicbase).\n");
480 /* OK options are set up. Now the file lists. */
482 for( n
=1; n
<argc
; n
++) {
483 o
.fileListFiles
= pkg_appendToList(o
.fileListFiles
, &tail
, uprv_strdup(argv
[n
]));
487 loadLists(&o
, &status
);
488 if( U_FAILURE(status
) ) {
489 fprintf(stderr
, "error loading input file lists: %s\n", u_errorName(status
));
493 result
= pkg_executeOptions(&o
);
495 if (pkgDataFlags
!= NULL
) {
496 for (n
= 0; n
< PKGDATA_FLAGS_SIZE
; n
++) {
497 if (pkgDataFlags
[n
] != NULL
) {
498 uprv_free(pkgDataFlags
[n
]);
501 uprv_free(pkgDataFlags
);
504 if (o
.cShortName
!= NULL
) {
505 uprv_free((char *)o
.cShortName
);
507 if (o
.fileListFiles
!= NULL
) {
508 pkg_deleteList(o
.fileListFiles
);
510 if (o
.filePaths
!= NULL
) {
511 pkg_deleteList(o
.filePaths
);
513 if (o
.files
!= NULL
) {
514 pkg_deleteList(o
.files
);
519 static int runCommand(const char* command
, UBool specialHandling
) {
521 char cmdBuffer
[SMALL_BUFFER_MAX_SIZE
];
522 int32_t len
= static_cast<int32_t>(strlen(command
));
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
);
535 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
536 sprintf(cmd
, "bash -c \"%s\"", command
);
538 #elif U_PLATFORM == U_PF_OS400
539 sprintf(cmd
, "QSH CMD('%s')", command
);
542 goto normal_command_mode
;
545 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
548 cmd
= (char *)command
;
551 printf("pkgdata: %s\n", cmd
);
552 int result
= system(cmd
);
554 fprintf(stderr
, "-- return status = %d\n", result
);
555 result
= 1; // system() result code is platform specific.
558 if (cmd
!= cmdBuffer
&& cmd
!= command
) {
565 #define LN_CMD "ln -s"
566 #define RM_CMD "rm -f"
568 static int32_t pkg_executeOptions(UPKGOptions
*o
) {
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
] = "";
578 initializePkgDataFlags(o
);
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
);
590 fprintf(stdout
, "# Install: Files mode, copying files to %s..\n", targetDir
);
592 result
= pkg_installFileMode(targetDir
, o
->srcDir
, o
->fileListFiles
->str
);
595 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
596 UBool noVersion
= FALSE
;
598 uprv_strcpy(targetDir
, o
->targetDir
);
599 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
601 uprv_strcpy(tmpDir
, o
->tmpDir
);
602 uprv_strcat(tmpDir
, PKGDATA_FILE_SEP_STRING
);
604 uprv_strcpy(datFileNamePath
, tmpDir
);
606 uprv_strcpy(datFileName
, o
->shortName
);
607 uprv_strcat(datFileName
, UDATA_CMN_SUFFIX
);
609 uprv_strcat(datFileNamePath
, datFileName
);
612 fprintf(stdout
, "# Writing package file %s ..\n", datFileNamePath
);
614 result
= writePackageDatFile(datFileNamePath
, o
->comment
, o
->srcDir
, o
->fileListFiles
->str
, NULL
, U_CHARSET_FAMILY
? 'e' : U_IS_BIG_ENDIAN
? 'b' : 'l');
616 fprintf(stderr
,"Error writing package dat file.\n");
620 if (IN_COMMON_MODE(mode
)) {
621 char targetFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
623 uprv_strcpy(targetFileNamePath
, targetDir
);
624 uprv_strcat(targetFileNamePath
, datFileName
);
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",
636 result
= rename(datFileNamePath
, targetFileNamePath
);
639 fprintf(stdout
, "# Moving package file to %s ..\n",
645 "Unable to move dat file (%s) to target location (%s).\n",
646 datFileNamePath
, targetFileNamePath
);
651 if (o
->install
!= NULL
) {
652 result
= pkg_installCommonMode(o
->install
, targetFileNamePath
);
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
;
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;
669 version_major
[i
] = o
->version
[i
];
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");
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.
682 if (pkgDataFlags
[LIB_EXT_ORDER
][uprv_strlen(pkgDataFlags
[LIB_EXT_ORDER
])-1] == pkgDataFlags
[SO_EXT
][uprv_strlen(pkgDataFlags
[SO_EXT
])-1]) {
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
);
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
) {
696 fprintf(stdout
, "# Installing already-built library into %s\n", o
->install
);
698 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
701 printf("# Not rebuilding %s - up to date.\n", checkLibFile
);
705 } else if (o
->verbose
&& (o
->install
!=NULL
)) {
706 fprintf(stdout
, "# Not installing up-to-date library %s into %s\n", checkLibFile
, o
->install
);
708 } else if(o
->verbose
&& (o
->install
!=NULL
)) {
709 fprintf(stdout
, "# Not installing missing %s into %s\n", checkLibFile
, o
->install
);
713 if (pkg_checkFlag(o
) == NULL
) {
714 /* Error occurred. */
719 if (!o
->withoutAssembly
&& pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
][0] != 0) {
720 const char* genccodeAssembly
= pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
];
723 fprintf(stdout
, "# Generating assembly code %s of type %s ..\n", gencFilePath
, genccodeAssembly
);
726 /* Offset genccodeAssembly by 3 because "-a " */
727 if (genccodeAssembly
&&
728 (uprv_strlen(genccodeAssembly
)>3) &&
729 checkAssemblyHeaderName(genccodeAssembly
+3)) {
736 sizeof(gencFilePath
));
738 result
= pkg_createWithAssemblyCode(targetDir
, mode
, gencFilePath
);
740 fprintf(stderr
, "Error generating assembly code for data.\n");
742 } else if (IN_STATIC_MODE(mode
)) {
743 if(o
->install
!= NULL
) {
745 fprintf(stdout
, "# Installing static library into %s\n", o
->install
);
747 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
752 fprintf(stderr
,"Assembly type \"%s\" is unknown.\n", genccodeAssembly
);
757 fprintf(stdout
, "# Writing object code to %s ..\n", gencFilePath
);
759 if (o
->withoutAssembly
) {
760 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
761 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
763 /* This error should not occur. */
764 fprintf(stderr
, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
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
);
775 (optMatchArch
[0] == 0 ? NULL
: optMatchArch
),
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
);
785 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
786 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
788 fprintf(stderr
, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
794 fprintf(stderr
, "Error generating package data.\n");
798 #if !U_PLATFORM_USES_ONLY_WIN32_API
799 if(!IN_STATIC_MODE(mode
)) {
800 /* Certain platforms uses archive library. (e.g. AIX) */
802 fprintf(stdout
, "# Creating data archive library file ..\n");
804 result
= pkg_archiveLibrary(targetDir
, o
->version
, reverseExt
);
806 fprintf(stderr
, "Error creating data archive library file.\n");
809 #if U_PLATFORM != U_PF_OS400
811 /* Create symbolic links for the final library file. */
812 #if U_PLATFORM == U_PF_OS390
813 result
= pkg_createSymLinks(targetDir
, o
->pdsbuild
);
815 result
= pkg_createSymLinks(targetDir
, noVersion
);
818 fprintf(stderr
, "Error creating symbolic links of the data library file.\n");
823 } /* !IN_STATIC_MODE */
826 #if !U_PLATFORM_USES_ONLY_WIN32_API
827 /* Install the libraries if option was set. */
828 if (o
->install
!= NULL
) {
830 fprintf(stdout
, "# Installing library file to %s ..\n", o
->install
);
832 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
834 fprintf(stderr
, "Error installing the data library.\n");
844 /* Initialize the pkgDataFlags with the option file given. */
845 static int32_t initializePkgDataFlags(UPKGOptions
*o
) {
846 UErrorCode status
= U_ZERO_ERROR
;
848 int32_t currentBufferSize
= SMALL_BUFFER_MAX_SIZE
;
849 int32_t tmpResult
= 0;
851 /* Initialize pkgdataFlags */
852 pkgDataFlags
= (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE
);
854 /* If we run out of space, allocate more */
855 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
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;
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
;
873 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
877 if (o
->options
== NULL
) {
881 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
882 /* Read in options file. */
884 fprintf(stdout
, "# Reading options file %s\n", o
->options
);
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
;
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
));
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
]);
906 fprintf(stdout
, "\n");
908 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
909 } while (status
== U_BUFFER_OVERFLOW_ERROR
);
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.
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] == '.' ? "." : "";
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
);
929 sprintf(libFileNames
[LIB_FILE
], "%s%s%s",
930 (strstr(libName
, "icudt") ? "lib" : ""),
931 pkgDataFlags
[LIBPREFIX
],
935 sprintf(libFileNames
[LIB_FILE
], "%s%s",
936 pkgDataFlags
[LIBPREFIX
],
941 fprintf(stdout
, "# libFileName[LIB_FILE] = %s\n", libFileNames
[LIB_FILE
]);
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",
951 pkgDataFlags
[SO_EXT
]);
952 sprintf(libFileNames
[LIB_FILE_CYGWIN_VERSION
], "cyg%s%s%s%s",
956 pkgDataFlags
[SO_EXT
]);
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
],
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
],
971 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
973 sprintf(libFileNames
[LIB_FILE_OS390BATCH_VERSION
], "%s%s.x",
974 libFileNames
[LIB_FILE
],
976 sprintf(libFileNames
[LIB_FILE_OS390BATCH_MAJOR
], "%s%s.x",
977 libFileNames
[LIB_FILE
],
980 if (noVersion
&& !reverseExt
) {
981 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s",
982 libFileNames
[LIB_FILE
],
984 pkgDataFlags
[SOBJ_EXT
]);
986 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s%s%s",
987 libFileNames
[LIB_FILE
],
989 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
991 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
994 if (noVersion
&& !reverseExt
) {
995 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s",
996 libFileNames
[LIB_FILE
],
998 pkgDataFlags
[SO_EXT
]);
1000 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s",
1001 libFileNames
[LIB_FILE
],
1003 pkgDataFlags
[SO_EXT
]);
1005 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s%s%s",
1006 libFileNames
[LIB_FILE
],
1008 reverseExt
? version_major
: pkgDataFlags
[SO_EXT
],
1010 reverseExt
? pkgDataFlags
[SO_EXT
] : version_major
);
1012 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s%s%s",
1013 libFileNames
[LIB_FILE
],
1015 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
1017 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
1021 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames
[LIB_FILE_VERSION
]);
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
]);
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;
1033 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames
[LIB_FILE_VERSION
]);
1038 /* Create the symbolic links for the final library file. */
1039 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
) {
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 ? "" : ".";
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) {
1053 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1056 libFileNames
[LIB_FILE_VERSION_MAJOR
],
1058 libFileNames
[LIB_FILE_VERSION
],
1059 libFileNames
[LIB_FILE_VERSION_MAJOR
]);
1060 result
= runCommand(cmd
);
1062 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
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",
1079 libFileNames
[LIB_FILE_OS390BATCH_MAJOR
],
1081 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1082 libFileNames
[LIB_FILE_OS390BATCH_MAJOR
]);
1083 result
= runCommand(cmd
);
1085 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1089 sprintf(cmd
, "cd %s && %s %s.x && %s %s %s.x",
1092 libFileNames
[LIB_FILE
],
1094 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1095 libFileNames
[LIB_FILE
]);
1096 result
= runCommand(cmd
);
1098 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
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
]);
1107 goto normal_symlink_mode
;
1110 #if U_PLATFORM != U_PF_CYGWIN
1111 normal_symlink_mode
:
1113 sprintf(name1
, "%s%s%s", libFileNames
[LIB_FILE
], FILE_EXTENSION_SEP
, pkgDataFlags
[SO_EXT
]);
1114 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
1117 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1125 result
= runCommand(cmd
);
1130 static int32_t pkg_installLibrary(const char *installDir
, const char *targetDir
, UBool noVersion
) {
1132 char cmd
[SMALL_BUFFER_MAX_SIZE
];
1134 sprintf(cmd
, "cd %s && %s %s %s%s%s",
1136 pkgDataFlags
[INSTALL_CMD
],
1137 libFileNames
[LIB_FILE_VERSION
],
1138 installDir
, PKGDATA_FILE_SEP_STRING
, libFileNames
[LIB_FILE_VERSION
]
1141 result
= runCommand(cmd
);
1144 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1149 sprintf(cmd
, "cd %s && %s %s.lib %s",
1151 pkgDataFlags
[INSTALL_CMD
],
1152 libFileNames
[LIB_FILE
],
1155 result
= runCommand(cmd
);
1158 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1161 #elif U_PLATFORM == U_PF_CYGWIN
1162 sprintf(cmd
, "cd %s && %s %s %s",
1164 pkgDataFlags
[INSTALL_CMD
],
1165 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1168 result
= runCommand(cmd
);
1171 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
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
],
1182 result
= runCommand(cmd
);
1185 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1194 return pkg_createSymLinks(installDir
, TRUE
);
1198 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
) {
1200 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1202 if (!T_FileStream_file_exists(installDir
)) {
1203 UErrorCode status
= U_ZERO_ERROR
;
1205 uprv_mkdir(installDir
, &status
);
1206 if (U_FAILURE(status
)) {
1207 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1211 #ifndef U_WINDOWS_WITH_MSVC
1212 sprintf(cmd
, "%s %s %s", pkgDataFlags
[INSTALL_CMD
], fileName
, installDir
);
1214 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, fileName
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1217 result
= runCommand(cmd
);
1219 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
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"
1230 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
) {
1232 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1234 if (!T_FileStream_file_exists(installDir
)) {
1235 UErrorCode status
= U_ZERO_ERROR
;
1237 uprv_mkdir(installDir
, &status
);
1238 if (U_FAILURE(status
)) {
1239 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1243 #ifndef U_WINDOWS_WITH_MSVC
1244 char buffer
[SMALL_BUFFER_MAX_SIZE
] = "";
1245 int32_t bufferLength
= 0;
1247 FileStream
*f
= T_FileStream_open(fileListName
, "r");
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;
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
);
1262 result
= runCommand(cmd
);
1264 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1268 if (!T_FileStream_eof(f
)) {
1269 fprintf(stderr
, "Failed to read line from file: %s\n", fileListName
);
1275 T_FileStream_close(f
);
1278 fprintf(stderr
, "Unable to open list file: %s\n", fileListName
);
1281 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, srcDir
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1282 result
= runCommand(cmd
);
1284 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
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.
1294 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
) {
1296 char cmd
[LARGE_BUFFER_MAX_SIZE
];
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.
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
);
1308 sprintf(cmd
, "%s %s %s%s %s%s",
1310 pkgDataFlags
[ARFLAGS
],
1312 libFileNames
[LIB_FILE_VERSION
],
1314 libFileNames
[LIB_FILE_VERSION_TMP
]);
1316 result
= runCommand(cmd
);
1318 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1322 sprintf(cmd
, "%s %s%s",
1323 pkgDataFlags
[RANLIB
],
1325 libFileNames
[LIB_FILE_VERSION
]);
1327 result
= runCommand(cmd
);
1329 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1333 /* Remove unneeded library file. */
1334 sprintf(cmd
, "%s %s%s",
1337 libFileNames
[LIB_FILE_VERSION_TMP
]);
1339 result
= runCommand(cmd
);
1341 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1346 uprv_strcpy(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_TMP
]);
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.
1356 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
, UBool specialHandling
) {
1359 UBool freeCmd
= FALSE
;
1362 (void)specialHandling
; // Suppress unused variable compiler warnings on platforms where all usage
1363 // of this parameter is #ifdefed out.
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.
1369 if (command
!= NULL
) {
1373 if (IN_STATIC_MODE(mode
)) {
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");
1383 sprintf(cmd
, "%s %s %s%s %s",
1385 pkgDataFlags
[ARFLAGS
],
1387 libFileNames
[LIB_FILE_VERSION
],
1390 result
= runCommand(cmd
);
1392 sprintf(cmd
, "%s %s%s",
1393 pkgDataFlags
[RANLIB
],
1395 libFileNames
[LIB_FILE_VERSION
]);
1397 result
= runCommand(cmd
);
1399 } else /* if (IN_DLL_MODE(mode)) */ {
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
]));
1411 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1412 fprintf(stderr
, "Unable to allocate memory for command.\n");
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
],
1421 libFileNames
[LIB_FILE_MINGW
],
1422 pkgDataFlags
[LDICUDTFLAGS
],
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
],
1429 libFileNames
[LIB_FILE_VERSION_TMP
],
1430 pkgDataFlags
[LDICUDTFLAGS
],
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",
1437 libFileNames
[LIB_FILE_VERSION_TMP
],
1438 pkgDataFlags
[GENLIB
],
1439 pkgDataFlags
[LDICUDTFLAGS
],
1441 libFileNames
[LIB_FILE_VERSION_TMP
],
1443 sprintf(cmd
, "%s %s -o %s%s %s %s%s %s %s",
1444 pkgDataFlags
[GENLIB
],
1445 pkgDataFlags
[LDICUDTFLAGS
],
1447 libFileNames
[LIB_FILE_VERSION_TMP
],
1450 pkgDataFlags
[LD_SONAME
],
1451 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1452 pkgDataFlags
[RPATH_FLAGS
],
1453 pkgDataFlags
[BIR_FLAGS
]);
1455 /* Generate the library file. */
1456 result
= runCommand(cmd
);
1458 #if U_PLATFORM == U_PF_OS390
1460 char PDS_LibName
[512];
1465 if (specialHandling
&& uprv_strcmp(libFileNames
[LIB_FILE
],"libicudata") == 0) {
1466 if (env_tmp
= getenv("ICU_PDS_NAME")) {
1467 sprintf(PDS_Name
, "%s%s",
1470 strcat(PDS_Name
, getenv("ICU_PDS_NAME_SUFFIX"));
1471 } else if (env_tmp
= getenv("PDS_NAME_PREFIX")) {
1472 sprintf(PDS_Name
, "%s%s",
1474 U_ICU_VERSION_SHORT
"DA");
1476 sprintf(PDS_Name
, "%s%s",
1478 U_ICU_VERSION_SHORT
"DA");
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",
1485 strcat(PDS_Name
, getenv("ICU_PDS_NAME_SUFFIX"));
1486 } else if (env_tmp
= getenv("PDS_NAME_PREFIX")) {
1487 sprintf(PDS_Name
, "%s%s",
1489 U_ICU_VERSION_SHORT
"D1");
1491 sprintf(PDS_Name
, "%s%s",
1493 U_ICU_VERSION_SHORT
"D1");
1498 sprintf(PDS_LibName
,"%s%s%s%s%s",
1504 sprintf(cmd
, "%s %s -o %s %s %s%s %s %s",
1505 pkgDataFlags
[GENLIB
],
1506 pkgDataFlags
[LDICUDTFLAGS
],
1509 pkgDataFlags
[LD_SONAME
],
1510 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1511 pkgDataFlags
[RPATH_FLAGS
],
1512 pkgDataFlags
[BIR_FLAGS
]);
1514 result
= runCommand(cmd
);
1520 fprintf(stderr
, "Error generating library file. Failed command: %s\n", cmd
);
1530 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
) {
1531 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
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';
1539 length
= static_cast<int32_t>(uprv_strlen(pkgDataFlags
[COMPILER
]) + uprv_strlen(pkgDataFlags
[LIBFLAGS
])
1540 + uprv_strlen(tempObjectFile
) + uprv_strlen(gencFilePath
) + BUFFER_PADDING_SIZE
);
1542 LocalMemory
<char> cmd((char *)uprv_malloc(sizeof(char) * length
));
1547 /* Generate the object file. */
1548 sprintf(cmd
.getAlias(), "%s %s -o %s %s",
1549 pkgDataFlags
[COMPILER
],
1550 pkgDataFlags
[LIBFLAGS
],
1554 result
= runCommand(cmd
.getAlias());
1557 fprintf(stderr
, "Error creating with assembly code. Failed command: %s\n", cmd
.getAlias());
1561 return pkg_generateLibraryFile(targetDir
, mode
, tempObjectFile
);
1564 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
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.
1577 DATA_PREFIX_TRANSLIT
,
1583 const static char DATA_PREFIX
[DATA_PREFIX_LENGTH
][10] = {
1595 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
) {
1597 CharList
*list
= o
->filePaths
;
1598 CharList
*listNames
= o
->files
;
1599 int32_t listSize
= pkg_countCharList(list
);
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
;
1608 sprintf(icudtAll
, "%s%s%sall.c",
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
);
1618 if((icudtAllFile
= T_FileStream_open(icudtAll
, "w"))==NULL
) {
1619 fprintf(stderr
, "Unable to write to icudtall file: %s\n", icudtAll
);
1624 if (list
== NULL
|| listNames
== NULL
) {
1625 /* list and listNames should never be NULL since we are looping through the CharList with
1631 if ((cmd
= (char *)uprv_malloc((listSize
+ 2) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1632 fprintf(stderr
, "Unable to allocate memory for cmd.\n");
1634 } else if ((buffer
= (char *)uprv_malloc((listSize
+ 1) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1635 fprintf(stderr
, "Unable to allocate memory for buffer.\n");
1640 for (int32_t i
= 0; i
< (listSize
+ 1); i
++) {
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
);
1648 #ifdef USE_SINGLE_CCODE_FILE
1649 uprv_strcpy(tempObjectFile
, gencmnFile
);
1650 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1652 sprintf(cmd
, "%s %s -o %s %s",
1653 pkgDataFlags
[COMPILER
],
1654 pkgDataFlags
[LIBFLAGS
],
1658 result
= runCommand(cmd
);
1663 sprintf(buffer
, "%s",tempObjectFile
);
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
;
1671 name
= listNames
->str
;
1673 newName
[0] = dataName
[0] = 0;
1674 for (int32_t n
= 0; n
< DATA_PREFIX_LENGTH
; n
++) {
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
++) {
1684 newNameTmp
[i
] = '_';
1687 newNameTmp
[i
] = p
[i
];
1692 sprintf(newName
, "%s_%s",
1695 sprintf(dataName
, "%s_%s",
1699 if (newName
[0] != 0) {
1705 printf("# Generating %s \n", gencmnFile
);
1711 dataName
[0] != 0 ? dataName
: o
->shortName
,
1712 newName
[0] != 0 ? newName
: NULL
,
1714 sizeof(gencmnFile
));
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 */
1723 #ifndef USE_SINGLE_CCODE_FILE
1724 uprv_strcpy(tempObjectFile
, gencmnFile
);
1725 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1727 sprintf(cmd
, "%s %s -o %s %s",
1728 pkgDataFlags
[COMPILER
],
1729 pkgDataFlags
[LIBFLAGS
],
1732 result
= runCommand(cmd
);
1734 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1738 uprv_strcat(buffer
, " ");
1739 uprv_strcat(buffer
, tempObjectFile
);
1745 listNames
= listNames
->next
;
1749 #ifdef USE_SINGLE_CCODE_FILE
1750 T_FileStream_close(icudtAllFile
);
1751 uprv_strcpy(tempObjectFile
, icudtAll
);
1752 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1754 sprintf(cmd
, "%s %s -I. -o %s %s",
1755 pkgDataFlags
[COMPILER
],
1756 pkgDataFlags
[LIBFLAGS
],
1760 result
= runCommand(cmd
);
1762 uprv_strcat(buffer
, " ");
1763 uprv_strcat(buffer
, tempObjectFile
);
1765 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
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
)));
1774 result
= pkg_generateLibraryFile(targetDir
,mode
, buffer
, cmd
);
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:"
1789 #define LINK_EXTRA_UWP_FLAGS "/APPCONTAINER "
1790 #define LINK_EXTRA_UWP_FLAGS_X86_ONLY "/SAFESEH "
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
1798 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
) {
1800 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1801 if (IN_STATIC_MODE(mode
)) {
1802 char staticLibFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1805 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1807 PKGDATA_FILE_SEP_STRING
,
1808 pkgDataFlags
[LIBPREFIX
],
1812 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1814 PKGDATA_FILE_SEP_STRING
,
1815 (strstr(o
->libName
, "icudt") ? "s" : ""),
1820 sprintf(cmd
, "%s\"%s\" \"%s\"",
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
] = "";
1831 uprv_strcpy(dllFilePath
, o
->targetDir
);
1833 uprv_strcpy(dllFilePath
, o
->srcDir
);
1835 uprv_strcat(dllFilePath
, PKGDATA_FILE_SEP_STRING
);
1836 uprv_strcpy(libFilePath
, dllFilePath
);
1839 uprv_strcat(libFilePath
, o
->libName
);
1840 uprv_strcat(libFilePath
, ".lib");
1842 uprv_strcat(dllFilePath
, o
->libName
);
1843 uprv_strcat(dllFilePath
, o
->version
);
1845 if (strstr(o
->libName
, "icudt")) {
1846 uprv_strcat(libFilePath
, LIB_FILE
);
1848 uprv_strcat(libFilePath
, o
->libName
);
1849 uprv_strcat(libFilePath
, ".lib");
1851 uprv_strcat(dllFilePath
, o
->entryName
);
1853 uprv_strcat(dllFilePath
, DLL_EXT
);
1855 uprv_strcpy(tmpResFilePath
, o
->tmpDir
);
1856 uprv_strcat(tmpResFilePath
, PKGDATA_FILE_SEP_STRING
);
1857 uprv_strcat(tmpResFilePath
, ICUDATA_RES_FILE
);
1859 if (T_FileStream_file_exists(tmpResFilePath
)) {
1860 sprintf(resFilePath
, "\"%s\"", tmpResFilePath
);
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
))) {
1867 printf("# Not rebuilding %s - up to date.\n", gencFilePath
);
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
);
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
);
1884 if (options
[WIN_DLL_ARCH
].doesOccur
) {
1885 uprv_strcat(extraFlags
, LINK_EXTRA_FLAGS_MACHINE
);
1886 uprv_strcat(extraFlags
, options
[WIN_DLL_ARCH
].value
);
1890 sprintf(cmd
, "%s\"%s\" %s %s\"%s\" \"%s\" %s",
1901 result
= runCommand(cmd
, TRUE
);
1903 fprintf(stderr
, "Error creating Windows DLL library. Failed command: %s\n", cmd
);
1910 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
) {
1911 #if U_PLATFORM == U_PF_AIX
1912 /* AIX needs a map file. */
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
] = "";
1921 const char rm_cmd
[] = "rm -f all ;";
1923 flag
= pkgDataFlags
[GENLIB
];
1925 /* This portion of the code removes 'rm -f all' in the GENLIB.
1926 * Only occurs in AIX.
1928 if (uprv_strstr(flag
, rm_cmd
) != NULL
) {
1929 char *tmpGenlibFlagBuffer
= NULL
;
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
);
1940 uprv_strcpy(tmpGenlibFlagBuffer
, flag
);
1942 offset
= static_cast<int32_t>(uprv_strlen(rm_cmd
));
1944 for (i
= 0; i
< (length
- offset
); i
++) {
1945 flag
[i
] = tmpGenlibFlagBuffer
[offset
+ i
];
1948 /* Zero terminate the string */
1951 uprv_free(tmpGenlibFlagBuffer
);
1954 flag
= pkgDataFlags
[BIR_FLAGS
];
1955 length
= static_cast<int32_t>(uprv_strlen(pkgDataFlags
[BIR_FLAGS
]));
1957 for (int32_t i
= 0; i
< length
; i
++) {
1958 if (flag
[i
] == MAP_FILE_EXT
[count
]) {
1967 if (count
== uprv_strlen(MAP_FILE_EXT
)) {
1974 for (int32_t i
= 0;;i
++) {
1976 for (int32_t n
= 0;;n
++) {
1977 if (o
->shortName
[n
] == 0) {
1980 tmpbuffer
[index
++] = o
->shortName
[n
];
1984 tmpbuffer
[index
++] = flag
[i
];
1991 uprv_memset(flag
, 0, length
);
1992 uprv_strcpy(flag
, tmpbuffer
);
1994 uprv_strcpy(mapFile
, o
->shortName
);
1995 uprv_strcat(mapFile
, MAP_FILE_EXT
);
1997 f
= T_FileStream_open(mapFile
, "w");
1999 fprintf(stderr
,"Unable to create map file: %s.\n", mapFile
);
2002 sprintf(tmpbuffer
, "%s%s ", o
->entryName
, UDATA_CMN_INTERMEDIATE_SUFFIX
);
2004 T_FileStream_writeLine(f
, tmpbuffer
);
2006 T_FileStream_close(f
);
2009 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
2010 /* Cygwin needs to change flag options. */
2014 flag
= pkgDataFlags
[GENLIB
];
2015 length
= static_cast<int32_t>(uprv_strlen(pkgDataFlags
[GENLIB
]));
2017 int32_t position
= length
- 1;
2019 for(;position
>= 0;position
--) {
2020 if (flag
[position
] == '=') {
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) */
2032 flag
= pkgDataFlags
[GENLIB
];
2033 length
= static_cast<int32_t>(uprv_strlen(pkgDataFlags
[GENLIB
]));
2035 int32_t position
= length
- 1;
2037 for(int32_t i
= 0; i
< length
; i
++) {
2038 if (flag
[i
] == '\'') {
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.
2048 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
)
2050 CharList
*l
, *tail
= NULL
, *tail2
= NULL
;
2053 char *linePtr
, *lineNext
;
2054 const uint32_t lineMax
= 16300;
2056 int32_t tmpLength
= 0;
2058 int32_t ln
=0; /* line number */
2060 for(l
= o
->fileListFiles
; l
; l
= l
->next
) {
2062 fprintf(stdout
, "# pkgdata: Reading %s..\n", l
->str
);
2065 in
= T_FileStream_open(l
->str
, "r"); /* open files list */
2068 fprintf(stderr
, "Error opening <%s>.\n", l
->str
);
2069 *status
= U_FILE_ACCESS_ERROR
;
2073 while(T_FileStream_readLine(in
, line
, sizeof(line
))!=NULL
) { /* for each line */
2075 if(uprv_strlen(line
)>lineMax
) {
2076 fprintf(stderr
, "%s:%d - line too long (over %d chars)\n", l
->str
, (int)ln
, (int)lineMax
);
2079 /* remove spaces at the beginning */
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
)) {
2088 /* remove trailing newline characters */
2090 if(*s
=='\r' || *s
=='\n') {
2096 if((*linePtr
== 0) || (*linePtr
== '#')) {
2097 continue; /* comment or empty line */
2100 /* Now, process the line */
2103 while(linePtr
&& *linePtr
) { /* process space-separated items */
2104 while(*linePtr
== ' ') {
2107 /* Find the next quote */
2108 if(linePtr
[0] == '"')
2110 lineNext
= uprv_strchr(linePtr
+1, '"');
2111 if(lineNext
== NULL
) {
2112 fprintf(stderr
, "%s:%d - missing trailing double quote (\")\n",
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');
2128 lineNext
= uprv_strchr(linePtr
, ' ');
2130 *lineNext
= 0; /* terminate at space */
2136 s
= (char*)getLongPathname(linePtr
);
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
);
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
);
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
);
2155 } /* for each entry on line */
2156 } /* for each line */
2157 T_FileStream_close(in
);
2158 } /* for each file list file */
2161 /* Try calling icu-config directly to get the option file. */
2162 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
) {
2164 LocalPipeFilePointer p
;
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
);
2178 cmdBuf
.append( cmd
, status
);
2181 fprintf(stdout
, "# Calling icu-config: %s\n", cmdBuf
.data());
2183 p
.adoptInstead(popen(cmdBuf
.data(), "r"));
2186 if(p
.isNull() || (n
= fread(buf
, 1, UPRV_LENGTHOF(buf
)-1, p
.getAlias())) <= 0) {
2188 fprintf(stdout
, "# Calling icu-config: %s\n", cmd
);
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
);
2198 for (int32_t length
= strlen(buf
) - 1; length
>= 0; length
--) {
2199 if (buf
[length
] == '\n' || buf
[length
] == ' ') {
2206 if(buf
[strlen(buf
)-1]=='\n')
2208 buf
[strlen(buf
)-1]=0;
2213 fprintf(stderr
, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname
);
2218 fprintf(stdout
, "# icu-config said: %s\n", buf
);
2221 option
->value
= buf
;
2222 option
->doesOccur
= TRUE
;
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
;
2239 stream
= T_FileStream_open(source
,"w");
2240 if (stream
!= NULL
) {
2241 T_FileStream_writeLine(stream
, code
);
2242 T_FileStream_close(stream
);
2244 char cmd
[LARGE_BUFFER_MAX_SIZE
];
2245 sprintf(cmd
, "%s %s -o %s",
2246 pkgDataFlags
[COMPILER
],
2250 if (runCommand(cmd
) == 0){
2251 sprintf(optMatchArch
, "%s", obj
);
2254 fprintf(stderr
, "Failed to compile %s\n", source
);
2256 if(!T_FileStream_remove(source
)){
2257 fprintf(stderr
, "T_FileStream_remove failed to delete %s\n", source
);
2261 fprintf(stderr
, "T_FileStream_open failed to open %s for writing\n", source
);
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
);