1 /******************************************************************************
2 * Copyright (C) 2000-2015, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *******************************************************************************
5 * file name: pkgdata.cpp
6 * encoding: ANSI X3.4 (1968)
7 * tab size: 8 (not used)
10 * created on: 2000may15
11 * created by: Steven \u24C7 Loomis
13 * This program packages the ICU data into different forms
14 * (DLL, common data, etc.)
17 // Defines _XOPEN_SOURCE for access to POSIX functions.
18 // Must be before any other #includes.
19 #include "uposixdefs.h"
21 #include "unicode/utypes.h"
23 #include "unicode/putil.h"
27 #if (U_PF_MINGW <= U_PLATFORM || U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__)
28 /* popen/pclose aren't defined in strict ANSI on Cygwin and MinGW */
29 #undef __STRICT_ANSI__
37 #include "unicode/uclean.h"
43 #include "pkg_gencmn.h"
44 #include "flagparser.h"
45 #include "filetools.h"
60 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
);
62 static int32_t pkg_executeOptions(UPKGOptions
*o
);
64 #ifdef WINDOWS_WITH_MSVC
65 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
);
67 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
=FALSE
);
68 static int32_t pkg_installLibrary(const char *installDir
, const char *dir
, UBool noVersion
);
69 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
);
70 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
);
72 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
73 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
);
76 #ifdef CAN_WRITE_OBJ_CODE
77 static void pkg_createOptMatchArch(char *optMatchArch
);
78 static void pkg_destroyOptMatchArch(char *optMatchArch
);
81 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
);
82 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
= NULL
, UBool specialHandling
=FALSE
);
83 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
);
84 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, const UBool reverseExt
, UBool noVersion
);
85 static int32_t initializePkgDataFlags(UPKGOptions
*o
);
87 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
);
88 static int runCommand(const char* command
, UBool specialHandling
=FALSE
);
90 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
91 #define IN_DLL_MODE(mode) (mode == 'd' || mode == 'l')
92 #define IN_STATIC_MODE(mode) (mode == 's')
93 #define IN_FILES_MODE(mode) (mode == 'f')
118 /* This sets the modes that are available */
120 const char *name
, *alt_name
;
123 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
124 #if U_PLATFORM_HAS_WIN32_API
125 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
126 { "common", "archive", "Generates just the common file, <package>.dat"},
127 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
129 #ifdef UDATA_SO_SUFFIX
130 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX
},
132 { "common", "archive", "Generates one common data file, <package>.dat" },
133 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
137 static UOption options
[]={
138 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG
),
139 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG
), /* on Win32 it is release or debug */
140 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG
),
141 /*03*/ UOPTION_HELP_H
, /* -h */
142 /*04*/ UOPTION_HELP_QUESTION_MARK
, /* -? */
143 /*05*/ UOPTION_VERBOSE
, /* -v */
144 /*06*/ UOPTION_COPYRIGHT
, /* -c */
145 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG
),
146 /*08*/ UOPTION_DESTDIR
, /* -d */
147 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG
),
148 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG
),
149 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG
),
150 /*14*/ UOPTION_SOURCEDIR
,
151 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG
),
152 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG
),
153 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG
),
154 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG
),
155 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG
),
156 /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG
),
157 /*21*/ UOPTION_DEF( "zos-pds-build", 'z', UOPT_NO_ARG
)
160 /* This enum and the following char array should be kept in sync. */
162 GENCCODE_ASSEMBLY_TYPE
,
181 static const char* FLAG_NAMES
[PKGDATA_FLAGS_SIZE
] = {
182 "GENCCODE_ASSEMBLY_TYPE",
200 static char **pkgDataFlags
= NULL
;
204 LIB_FILE_VERSION_MAJOR
,
206 LIB_FILE_VERSION_TMP
,
207 #if U_PLATFORM == U_PF_CYGWIN
209 LIB_FILE_CYGWIN_VERSION
,
210 #elif U_PLATFORM == U_PF_MINGW
212 #elif U_PLATFORM == U_PF_OS390
213 LIB_FILE_OS390BATCH_MAJOR
,
214 LIB_FILE_OS390BATCH_VERSION
,
218 static char libFileNames
[LIB_FILENAMES_SIZE
][256];
220 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
);
222 const char options_help
[][320]={
224 #ifdef U_MAKE_IS_NMAKE
225 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
227 "Specify options for the builder.",
229 "Specify the mode of building (see below; default: common)",
232 "Make the output verbose",
233 "Use the standard ICU copyright",
234 "Use a custom comment (instead of the copyright)",
235 "Specify the destination directory for files",
236 "Force rebuilding of all data",
237 "Specify temporary dir (default: output dir)",
238 "Install the data (specify target)",
239 "Specify a custom source directory",
240 "Specify a custom entrypoint name (default: short name)",
241 "Specify a version when packaging in dll or static mode",
242 "Add package to all file names if not present",
243 "Library name to build (if different than package name)",
244 "Quite mode. (e.g. Do not output a readme file for static libraries)",
245 "Build the data without assembly code",
246 "Build PDS dataset (zOS build only)"
249 const char *progname
= "PKGDATA";
252 main(int argc
, char* argv
[]) {
254 /* FileStream *out; */
257 UBool needsHelp
= FALSE
;
258 UErrorCode status
= U_ZERO_ERROR
;
259 /* char tmp[1024]; */
263 U_MAIN_INIT_ARGS(argc
, argv
);
267 options
[MODE
].value
= "common";
269 /* read command line options */
270 argc
=u_parseArgs(argc
, argv
, sizeof(options
)/sizeof(options
[0]), options
);
272 /* error handling, printing usage message */
273 /* I've decided to simply print an error and quit. This tool has too
274 many options to just display them all of the time. */
276 if(options
[HELP
].doesOccur
|| options
[HELP_QUESTION_MARK
].doesOccur
) {
280 if(!needsHelp
&& argc
<0) {
282 "%s: error in command line argument \"%s\"\n",
285 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
290 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
291 if(!options
[BLDOPT
].doesOccur
&& uprv_strcmp(options
[MODE
].value
, "common") != 0) {
292 if (pkg_getOptionsFromICUConfig(options
[VERBOSE
].doesOccur
, &options
[BLDOPT
]) != 0) {
293 fprintf(stderr
, " required parameter is missing: -O is required for static and shared builds.\n");
294 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
299 if(options
[BLDOPT
].doesOccur
) {
300 fprintf(stdout
, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
304 if(!options
[NAME
].doesOccur
) /* -O we already have - don't report it. */
306 fprintf(stderr
, " required parameter -p is missing \n");
307 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
313 "No input files specified.\n"
314 "Run '%s --help' for help.\n", progname
);
317 } /* end !needsHelp */
319 if(argc
<0 || needsHelp
) {
321 "usage: %s [-options] [-] [packageFile] \n"
322 "\tProduce packaged ICU data from the given list(s) of files.\n"
323 "\t'-' by itself means to read from stdin.\n"
324 "\tpackageFile is a text file containing the list of files to package.\n",
327 fprintf(stderr
, "\n options:\n");
328 for(i
=0;i
<(sizeof(options
)/sizeof(options
[0]));i
++) {
329 fprintf(stderr
, "%-5s -%c %s%-10s %s\n",
331 options
[i
].shortName
,
332 options
[i
].longName
? "or --" : " ",
333 options
[i
].longName
? options
[i
].longName
: "",
337 fprintf(stderr
, "modes: (-m option)\n");
338 for(i
=0;i
<(sizeof(modes
)/sizeof(modes
[0]));i
++) {
339 fprintf(stderr
, " %-9s ", modes
[i
].name
);
340 if (modes
[i
].alt_name
) {
341 fprintf(stderr
, "/ %-9s", modes
[i
].alt_name
);
343 fprintf(stderr
, " ");
345 fprintf(stderr
, " %s\n", modes
[i
].desc
);
350 /* OK, fill in the options struct */
351 uprv_memset(&o
, 0, sizeof(o
));
353 o
.mode
= options
[MODE
].value
;
354 o
.version
= options
[REVISION
].doesOccur
? options
[REVISION
].value
: 0;
356 o
.shortName
= options
[NAME
].value
;
358 int32_t len
= (int32_t)uprv_strlen(o
.shortName
);
362 cp
= csname
= (char *) uprv_malloc((len
+ 1 + 1) * sizeof(*o
.cShortName
));
363 if (*(sp
= o
.shortName
)) {
364 *cp
++ = isalpha(*sp
) ? * sp
: '_';
365 for (++sp
; *sp
; ++sp
) {
366 *cp
++ = isalnum(*sp
) ? *sp
: '_';
371 o
.cShortName
= csname
;
374 if(options
[LIBNAME
].doesOccur
) { /* get libname from shortname, or explicit -L parameter */
375 o
.libName
= options
[LIBNAME
].value
;
377 o
.libName
= o
.shortName
;
380 if(options
[QUIET
].doesOccur
) {
386 if(options
[PDS_BUILD
].doesOccur
) {
387 #if U_PLATFORM == U_PF_OS390
391 fprintf(stdout
, "Warning: You are using the -z option which only works on z/OS.\n");
398 o
.verbose
= options
[VERBOSE
].doesOccur
;
401 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
402 if (options
[BLDOPT
].doesOccur
) {
403 o
.options
= options
[BLDOPT
].value
;
408 if(options
[COPYRIGHT
].doesOccur
) {
409 o
.comment
= U_COPYRIGHT_STRING
;
410 } else if (options
[COMMENT
].doesOccur
) {
411 o
.comment
= options
[COMMENT
].value
;
414 if( options
[DESTDIR
].doesOccur
) {
415 o
.targetDir
= options
[DESTDIR
].value
;
417 o
.targetDir
= "."; /* cwd */
420 o
.rebuild
= options
[REBUILD
].doesOccur
;
422 if( options
[TEMPDIR
].doesOccur
) {
423 o
.tmpDir
= options
[TEMPDIR
].value
;
425 o
.tmpDir
= o
.targetDir
;
428 if( options
[INSTALL
].doesOccur
) {
429 o
.install
= options
[INSTALL
].value
;
434 if( options
[SOURCEDIR
].doesOccur
) {
435 o
.srcDir
= options
[SOURCEDIR
].value
;
440 if( options
[ENTRYPOINT
].doesOccur
) {
441 o
.entryName
= options
[ENTRYPOINT
].value
;
443 o
.entryName
= o
.cShortName
;
446 o
.withoutAssembly
= FALSE
;
447 if (options
[WITHOUT_ASSEMBLY
].doesOccur
) {
448 #ifndef BUILD_DATA_WITHOUT_ASSEMBLY
449 fprintf(stdout
, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n");
450 fprintf(stdout
, "Warning: This option will be ignored.\n");
452 o
.withoutAssembly
= TRUE
;
456 /* OK options are set up. Now the file lists. */
458 for( n
=1; n
<argc
; n
++) {
459 o
.fileListFiles
= pkg_appendToList(o
.fileListFiles
, &tail
, uprv_strdup(argv
[n
]));
463 loadLists(&o
, &status
);
464 if( U_FAILURE(status
) ) {
465 fprintf(stderr
, "error loading input file lists: %s\n", u_errorName(status
));
469 result
= pkg_executeOptions(&o
);
471 if (pkgDataFlags
!= NULL
) {
472 for (n
= 0; n
< PKGDATA_FLAGS_SIZE
; n
++) {
473 if (pkgDataFlags
[n
] != NULL
) {
474 uprv_free(pkgDataFlags
[n
]);
477 uprv_free(pkgDataFlags
);
480 if (o
.cShortName
!= NULL
) {
481 uprv_free((char *)o
.cShortName
);
483 if (o
.fileListFiles
!= NULL
) {
484 pkg_deleteList(o
.fileListFiles
);
486 if (o
.filePaths
!= NULL
) {
487 pkg_deleteList(o
.filePaths
);
489 if (o
.files
!= NULL
) {
490 pkg_deleteList(o
.files
);
496 static int runCommand(const char* command
, UBool specialHandling
) {
498 char cmdBuffer
[SMALL_BUFFER_MAX_SIZE
];
499 int32_t len
= strlen(command
);
505 if (!specialHandling
) {
506 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400
507 if ((len
+ BUFFER_PADDING_SIZE
) >= SMALL_BUFFER_MAX_SIZE
) {
508 cmd
= (char *)uprv_malloc(len
+ BUFFER_PADDING_SIZE
);
512 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
513 sprintf(cmd
, "bash -c \"%s\"", command
);
515 #elif U_PLATFORM == U_PF_OS400
516 sprintf(cmd
, "QSH CMD('%s')", command
);
519 goto normal_command_mode
;
522 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
525 cmd
= (char *)command
;
528 printf("pkgdata: %s\n", cmd
);
529 int result
= system(cmd
);
531 fprintf(stderr
, "-- return status = %d\n", result
);
534 if (cmd
!= cmdBuffer
&& cmd
!= command
) {
541 #define LN_CMD "ln -s"
542 #define RM_CMD "rm -f"
544 static int32_t pkg_executeOptions(UPKGOptions
*o
) {
547 const char mode
= o
->mode
[0];
548 char targetDir
[SMALL_BUFFER_MAX_SIZE
] = "";
549 char tmpDir
[SMALL_BUFFER_MAX_SIZE
] = "";
550 char datFileName
[SMALL_BUFFER_MAX_SIZE
] = "";
551 char datFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
552 char checkLibFile
[LARGE_BUFFER_MAX_SIZE
] = "";
554 initializePkgDataFlags(o
);
556 if (IN_FILES_MODE(mode
)) {
557 /* Copy the raw data to the installation directory. */
558 if (o
->install
!= NULL
) {
559 uprv_strcpy(targetDir
, o
->install
);
560 if (o
->shortName
!= NULL
) {
561 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
562 uprv_strcat(targetDir
, o
->shortName
);
566 fprintf(stdout
, "# Install: Files mode, copying files to %s..\n", targetDir
);
568 result
= pkg_installFileMode(targetDir
, o
->srcDir
, o
->fileListFiles
->str
);
571 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
572 UBool noVersion
= FALSE
;
574 uprv_strcpy(targetDir
, o
->targetDir
);
575 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
577 uprv_strcpy(tmpDir
, o
->tmpDir
);
578 uprv_strcat(tmpDir
, PKGDATA_FILE_SEP_STRING
);
580 uprv_strcpy(datFileNamePath
, tmpDir
);
582 uprv_strcpy(datFileName
, o
->shortName
);
583 uprv_strcat(datFileName
, UDATA_CMN_SUFFIX
);
585 uprv_strcat(datFileNamePath
, datFileName
);
588 fprintf(stdout
, "# Writing package file %s ..\n", datFileNamePath
);
590 result
= writePackageDatFile(datFileNamePath
, o
->comment
, o
->srcDir
, o
->fileListFiles
->str
, NULL
, U_CHARSET_FAMILY
? 'e' : U_IS_BIG_ENDIAN
? 'b' : 'l');
592 fprintf(stderr
,"Error writing package dat file.\n");
596 if (IN_COMMON_MODE(mode
)) {
597 char targetFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
599 uprv_strcpy(targetFileNamePath
, targetDir
);
600 uprv_strcat(targetFileNamePath
, datFileName
);
602 /* Move the dat file created to the target directory. */
603 if (uprv_strcmp(datFileNamePath
, targetFileNamePath
) != 0) {
604 if (T_FileStream_file_exists(targetFileNamePath
)) {
605 if ((result
= remove(targetFileNamePath
)) != 0) {
606 fprintf(stderr
, "Unable to remove old dat file: %s\n",
612 result
= rename(datFileNamePath
, targetFileNamePath
);
615 fprintf(stdout
, "# Moving package file to %s ..\n",
621 "Unable to move dat file (%s) to target location (%s).\n",
622 datFileNamePath
, targetFileNamePath
);
627 if (o
->install
!= NULL
) {
628 result
= pkg_installCommonMode(o
->install
, targetFileNamePath
);
632 } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ {
633 char gencFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
634 char version_major
[10] = "";
635 UBool reverseExt
= FALSE
;
637 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
638 /* Get the version major number. */
639 if (o
->version
!= NULL
) {
640 for (uint32_t i
= 0;i
< sizeof(version_major
);i
++) {
641 if (o
->version
[i
] == '.') {
642 version_major
[i
] = 0;
645 version_major
[i
] = o
->version
[i
];
649 if (IN_DLL_MODE(mode
)) {
650 fprintf(stdout
, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n");
654 #if U_PLATFORM != U_PF_OS400
655 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
656 * reverseExt is FALSE if the suffix should be the version number.
658 if (pkgDataFlags
[LIB_EXT_ORDER
][uprv_strlen(pkgDataFlags
[LIB_EXT_ORDER
])-1] == pkgDataFlags
[SO_EXT
][uprv_strlen(pkgDataFlags
[SO_EXT
])-1]) {
662 /* Using the base libName and version number, generate the library file names. */
663 createFileNames(o
, mode
, version_major
, o
->version
== NULL
? "" : o
->version
, o
->libName
, reverseExt
, noVersion
);
665 if ((o
->version
!=NULL
|| IN_STATIC_MODE(mode
)) && o
->rebuild
== FALSE
&& o
->pdsbuild
== FALSE
) {
666 /* Check to see if a previous built data library file exists and check if it is the latest. */
667 sprintf(checkLibFile
, "%s%s", targetDir
, libFileNames
[LIB_FILE_VERSION
]);
668 if (T_FileStream_file_exists(checkLibFile
)) {
669 if (isFileModTimeLater(checkLibFile
, o
->srcDir
, TRUE
) && isFileModTimeLater(checkLibFile
, o
->options
)) {
670 if (o
->install
!= NULL
) {
672 fprintf(stdout
, "# Installing already-built library into %s\n", o
->install
);
674 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
677 printf("# Not rebuilding %s - up to date.\n", checkLibFile
);
681 } else if (o
->verbose
&& (o
->install
!=NULL
)) {
682 fprintf(stdout
, "# Not installing up-to-date library %s into %s\n", checkLibFile
, o
->install
);
684 } else if(o
->verbose
&& (o
->install
!=NULL
)) {
685 fprintf(stdout
, "# Not installing missing %s into %s\n", checkLibFile
, o
->install
);
689 if (pkg_checkFlag(o
) == NULL
) {
690 /* Error occurred. */
695 if (!o
->withoutAssembly
&& pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
][0] != 0) {
696 const char* genccodeAssembly
= pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
];
699 fprintf(stdout
, "# Generating assembly code %s of type %s ..\n", gencFilePath
, genccodeAssembly
);
702 /* Offset genccodeAssembly by 3 because "-a " */
703 if (genccodeAssembly
&&
704 (uprv_strlen(genccodeAssembly
)>3) &&
705 checkAssemblyHeaderName(genccodeAssembly
+3)) {
706 writeAssemblyCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, NULL
, gencFilePath
);
708 result
= pkg_createWithAssemblyCode(targetDir
, mode
, gencFilePath
);
710 fprintf(stderr
, "Error generating assembly code for data.\n");
712 } else if (IN_STATIC_MODE(mode
)) {
713 if(o
->install
!= NULL
) {
715 fprintf(stdout
, "# Installing static library into %s\n", o
->install
);
717 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
722 fprintf(stderr
,"Assembly type \"%s\" is unknown.\n", genccodeAssembly
);
727 fprintf(stdout
, "# Writing object code to %s ..\n", gencFilePath
);
729 if (o
->withoutAssembly
) {
730 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
731 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
733 /* This error should not occur. */
734 fprintf(stderr
, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
737 #ifdef CAN_WRITE_OBJ_CODE
738 /* Try to detect the arch type, use NULL if unsuccessful */
739 char optMatchArch
[10] = { 0 };
740 pkg_createOptMatchArch(optMatchArch
);
741 writeObjectCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, (optMatchArch
[0] == 0 ? NULL
: optMatchArch
), NULL
, gencFilePath
);
742 pkg_destroyOptMatchArch(optMatchArch
);
743 #if U_PLATFORM_IS_LINUX_BASED
744 result
= pkg_generateLibraryFile(targetDir
, mode
, gencFilePath
);
745 #elif defined(WINDOWS_WITH_MSVC)
746 result
= pkg_createWindowsDLL(mode
, gencFilePath
, o
);
748 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
749 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
751 fprintf(stderr
, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
757 fprintf(stderr
, "Error generating package data.\n");
761 #if !U_PLATFORM_USES_ONLY_WIN32_API
762 if(!IN_STATIC_MODE(mode
)) {
763 /* Certain platforms uses archive library. (e.g. AIX) */
765 fprintf(stdout
, "# Creating data archive library file ..\n");
767 result
= pkg_archiveLibrary(targetDir
, o
->version
, reverseExt
);
769 fprintf(stderr
, "Error creating data archive library file.\n");
772 #if U_PLATFORM != U_PF_OS400
774 /* Create symbolic links for the final library file. */
775 #if U_PLATFORM == U_PF_OS390
776 result
= pkg_createSymLinks(targetDir
, o
->pdsbuild
);
778 result
= pkg_createSymLinks(targetDir
, noVersion
);
781 fprintf(stderr
, "Error creating symbolic links of the data library file.\n");
786 } /* !IN_STATIC_MODE */
789 #if !U_PLATFORM_USES_ONLY_WIN32_API
790 /* Install the libraries if option was set. */
791 if (o
->install
!= NULL
) {
793 fprintf(stdout
, "# Installing library file to %s ..\n", o
->install
);
795 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
797 fprintf(stderr
, "Error installing the data library.\n");
807 /* Initialize the pkgDataFlags with the option file given. */
808 static int32_t initializePkgDataFlags(UPKGOptions
*o
) {
809 UErrorCode status
= U_ZERO_ERROR
;
811 int32_t currentBufferSize
= SMALL_BUFFER_MAX_SIZE
;
812 int32_t tmpResult
= 0;
814 /* Initialize pkgdataFlags */
815 pkgDataFlags
= (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE
);
817 /* If we run out of space, allocate more */
818 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
821 if (pkgDataFlags
!= NULL
) {
822 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
823 pkgDataFlags
[i
] = (char*)uprv_malloc(sizeof(char) * currentBufferSize
);
824 if (pkgDataFlags
[i
] != NULL
) {
825 pkgDataFlags
[i
][0] = 0;
827 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
832 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
836 if (o
->options
== NULL
) {
840 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
841 /* Read in options file. */
843 fprintf(stdout
, "# Reading options file %s\n", o
->options
);
845 status
= U_ZERO_ERROR
;
846 tmpResult
= parseFlagsFile(o
->options
, pkgDataFlags
, currentBufferSize
, FLAG_NAMES
, (int32_t)PKGDATA_FLAGS_SIZE
, &status
);
847 if (status
== U_BUFFER_OVERFLOW_ERROR
) {
848 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
849 uprv_free(pkgDataFlags
[i
]);
851 currentBufferSize
= tmpResult
;
852 } else if (U_FAILURE(status
)) {
853 fprintf(stderr
,"Unable to open or read \"%s\" option file. status = %s\n", o
->options
, u_errorName(status
));
858 fprintf(stdout
, "# pkgDataFlags=\n");
859 for(int32_t i
=0;i
<PKGDATA_FLAGS_SIZE
;i
++) {
860 fprintf(stdout
, " [%d] %s: %s\n", i
, FLAG_NAMES
[i
], pkgDataFlags
[i
]);
862 fprintf(stdout
, "\n");
864 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
865 } while (status
== U_BUFFER_OVERFLOW_ERROR
);
873 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
874 * Depending on the configuration, the library name may either end with version number or shared object suffix.
876 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, UBool reverseExt
, UBool noVersion
) {
877 const char* FILE_EXTENSION_SEP
= uprv_strlen(pkgDataFlags
[SO_EXT
]) == 0 ? "" : ".";
878 const char* FILE_SUFFIX
= pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "";
880 #if U_PLATFORM == U_PF_MINGW
881 /* MinGW does not need the library prefix when building in dll mode. */
882 if (IN_DLL_MODE(mode
)) {
883 sprintf(libFileNames
[LIB_FILE
], "%s", libName
);
885 sprintf(libFileNames
[LIB_FILE
], "%s%s",
886 pkgDataFlags
[LIBPREFIX
],
890 sprintf(libFileNames
[LIB_FILE
], "%s%s",
891 pkgDataFlags
[LIBPREFIX
],
896 fprintf(stdout
, "# libFileName[LIB_FILE] = %s\n", libFileNames
[LIB_FILE
]);
899 #if U_PLATFORM == U_PF_MINGW
900 // Name the import library lib*.dll.a
901 sprintf(libFileNames
[LIB_FILE_MINGW
], "lib%s.dll.a", libName
);
902 #elif U_PLATFORM == U_PF_CYGWIN
903 sprintf(libFileNames
[LIB_FILE_CYGWIN
], "cyg%s%s%s",
906 pkgDataFlags
[SO_EXT
]);
907 sprintf(libFileNames
[LIB_FILE_CYGWIN_VERSION
], "cyg%s%s%s%s",
911 pkgDataFlags
[SO_EXT
]);
913 uprv_strcat(pkgDataFlags
[SO_EXT
], ".");
914 uprv_strcat(pkgDataFlags
[SO_EXT
], pkgDataFlags
[A_EXT
]);
915 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
916 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s",
917 libFileNames
[LIB_FILE
],
919 pkgDataFlags
[SOBJ_EXT
]);
920 #elif U_PLATFORM == U_PF_OS390
921 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s%s%s",
922 libFileNames
[LIB_FILE
],
923 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
924 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
926 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
928 sprintf(libFileNames
[LIB_FILE_OS390BATCH_VERSION
], "%s%s.x",
929 libFileNames
[LIB_FILE
],
931 sprintf(libFileNames
[LIB_FILE_OS390BATCH_MAJOR
], "%s%s.x",
932 libFileNames
[LIB_FILE
],
935 if (noVersion
&& !reverseExt
) {
936 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s",
937 libFileNames
[LIB_FILE
],
939 pkgDataFlags
[SOBJ_EXT
]);
941 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s%s%s",
942 libFileNames
[LIB_FILE
],
944 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
946 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
949 if (noVersion
&& !reverseExt
) {
950 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s",
951 libFileNames
[LIB_FILE
],
953 pkgDataFlags
[SO_EXT
]);
955 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s",
956 libFileNames
[LIB_FILE
],
958 pkgDataFlags
[SO_EXT
]);
960 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s%s%s",
961 libFileNames
[LIB_FILE
],
963 reverseExt
? version_major
: pkgDataFlags
[SO_EXT
],
965 reverseExt
? pkgDataFlags
[SO_EXT
] : version_major
);
967 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s%s%s",
968 libFileNames
[LIB_FILE
],
970 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
972 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
976 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames
[LIB_FILE_VERSION
]);
979 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
980 /* Cygwin and MinGW only deals with the version major number. */
981 uprv_strcpy(libFileNames
[LIB_FILE_VERSION_TMP
], libFileNames
[LIB_FILE_VERSION_MAJOR
]);
984 if(IN_STATIC_MODE(mode
)) {
985 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s.%s", libFileNames
[LIB_FILE
], pkgDataFlags
[A_EXT
]);
986 libFileNames
[LIB_FILE_VERSION_MAJOR
][0]=0;
988 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames
[LIB_FILE_VERSION
]);
993 /* Create the symbolic links for the final library file. */
994 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
) {
996 char cmd
[LARGE_BUFFER_MAX_SIZE
];
997 char name1
[SMALL_BUFFER_MAX_SIZE
]; /* symlink file name */
998 char name2
[SMALL_BUFFER_MAX_SIZE
]; /* file name to symlink */
999 const char* FILE_EXTENSION_SEP
= uprv_strlen(pkgDataFlags
[SO_EXT
]) == 0 ? "" : ".";
1001 #if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW
1002 /* No symbolic link to make. */
1003 if (uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) == 0 || uprv_strlen(libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0 ||
1004 uprv_strcmp(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0) {
1008 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1011 libFileNames
[LIB_FILE_VERSION_MAJOR
],
1013 libFileNames
[LIB_FILE_VERSION
],
1014 libFileNames
[LIB_FILE_VERSION_MAJOR
]);
1015 result
= runCommand(cmd
);
1017 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1022 if (specialHandling
) {
1023 #if U_PLATFORM == U_PF_CYGWIN
1024 sprintf(name1
, "%s", libFileNames
[LIB_FILE_CYGWIN
]);
1025 sprintf(name2
, "%s", libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
1026 #elif U_PLATFORM == U_PF_OS390
1027 /* Create the symbolic links for the import data */
1028 /* Use the cmd buffer to store path to import data file to check its existence */
1029 sprintf(cmd
, "%s/%s", targetDir
, libFileNames
[LIB_FILE_OS390BATCH_VERSION
]);
1030 if (T_FileStream_file_exists(cmd
)) {
1031 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1034 libFileNames
[LIB_FILE_OS390BATCH_MAJOR
],
1036 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1037 libFileNames
[LIB_FILE_OS390BATCH_MAJOR
]);
1038 result
= runCommand(cmd
);
1040 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1044 sprintf(cmd
, "cd %s && %s %s.x && %s %s %s.x",
1047 libFileNames
[LIB_FILE
],
1049 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1050 libFileNames
[LIB_FILE
]);
1051 result
= runCommand(cmd
);
1053 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1058 /* Needs to be set here because special handling skips it */
1059 sprintf(name1
, "%s%s%s", libFileNames
[LIB_FILE
], FILE_EXTENSION_SEP
, pkgDataFlags
[SO_EXT
]);
1060 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
1062 goto normal_symlink_mode
;
1065 #if U_PLATFORM != U_PF_CYGWIN
1066 normal_symlink_mode
:
1068 sprintf(name1
, "%s%s%s", libFileNames
[LIB_FILE
], FILE_EXTENSION_SEP
, pkgDataFlags
[SO_EXT
]);
1069 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
1072 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1080 result
= runCommand(cmd
);
1085 static int32_t pkg_installLibrary(const char *installDir
, const char *targetDir
, UBool noVersion
) {
1087 char cmd
[SMALL_BUFFER_MAX_SIZE
];
1089 sprintf(cmd
, "cd %s && %s %s %s%s%s",
1091 pkgDataFlags
[INSTALL_CMD
],
1092 libFileNames
[LIB_FILE_VERSION
],
1093 installDir
, PKGDATA_FILE_SEP_STRING
, libFileNames
[LIB_FILE_VERSION
]
1096 result
= runCommand(cmd
);
1099 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1104 sprintf(cmd
, "cd %s && %s %s.lib %s",
1106 pkgDataFlags
[INSTALL_CMD
],
1107 libFileNames
[LIB_FILE
],
1110 result
= runCommand(cmd
);
1113 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1116 #elif U_PLATFORM == U_PF_CYGWIN
1117 sprintf(cmd
, "cd %s && %s %s %s",
1119 pkgDataFlags
[INSTALL_CMD
],
1120 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1123 result
= runCommand(cmd
);
1126 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1130 #elif U_PLATFORM == U_PF_OS390
1131 if (T_FileStream_file_exists(libFileNames
[LIB_FILE_OS390BATCH_VERSION
])) {
1132 sprintf(cmd
, "%s %s %s",
1133 pkgDataFlags
[INSTALL_CMD
],
1134 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1137 result
= runCommand(cmd
);
1140 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1149 return pkg_createSymLinks(installDir
, TRUE
);
1153 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
) {
1155 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1157 if (!T_FileStream_file_exists(installDir
)) {
1158 UErrorCode status
= U_ZERO_ERROR
;
1160 uprv_mkdir(installDir
, &status
);
1161 if (U_FAILURE(status
)) {
1162 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1166 #ifndef U_WINDOWS_WITH_MSVC
1167 sprintf(cmd
, "%s %s %s", pkgDataFlags
[INSTALL_CMD
], fileName
, installDir
);
1169 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, fileName
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1172 result
= runCommand(cmd
);
1174 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1180 #ifdef U_WINDOWS_MSVC
1181 /* Copy commands for installing the raw data files on Windows. */
1182 #define WIN_INSTALL_CMD "xcopy"
1183 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
1185 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
) {
1187 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1189 if (!T_FileStream_file_exists(installDir
)) {
1190 UErrorCode status
= U_ZERO_ERROR
;
1192 uprv_mkdir(installDir
, &status
);
1193 if (U_FAILURE(status
)) {
1194 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1198 #ifndef U_WINDOWS_WITH_MSVC
1199 char buffer
[SMALL_BUFFER_MAX_SIZE
] = "";
1200 int32_t bufferLength
= 0;
1202 FileStream
*f
= T_FileStream_open(fileListName
, "r");
1205 if (T_FileStream_readLine(f
, buffer
, SMALL_BUFFER_MAX_SIZE
) != NULL
) {
1206 bufferLength
= uprv_strlen(buffer
);
1207 /* Remove new line character. */
1208 if (bufferLength
> 0) {
1209 buffer
[bufferLength
-1] = 0;
1212 sprintf(cmd
, "%s %s%s%s %s%s%s",
1213 pkgDataFlags
[INSTALL_CMD
],
1214 srcDir
, PKGDATA_FILE_SEP_STRING
, buffer
,
1215 installDir
, PKGDATA_FILE_SEP_STRING
, buffer
);
1217 result
= runCommand(cmd
);
1219 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1223 if (!T_FileStream_eof(f
)) {
1224 fprintf(stderr
, "Failed to read line from file: %s\n", fileListName
);
1230 T_FileStream_close(f
);
1233 fprintf(stderr
, "Unable to open list file: %s\n", fileListName
);
1236 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, srcDir
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1237 result
= runCommand(cmd
);
1239 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1246 /* Archiving of the library file may be needed depending on the platform and options given.
1247 * If archiving is not needed, copy over the library file name.
1249 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
) {
1251 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1253 /* If the shared object suffix and the final object suffix is different and the final object suffix and the
1254 * archive file suffix is the same, then the final library needs to be archived.
1256 if (uprv_strcmp(pkgDataFlags
[SOBJ_EXT
], pkgDataFlags
[SO_EXT
]) != 0 && uprv_strcmp(pkgDataFlags
[A_EXT
], pkgDataFlags
[SO_EXT
]) == 0) {
1257 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s.%s",
1258 libFileNames
[LIB_FILE
],
1259 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
1260 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
1261 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
1263 sprintf(cmd
, "%s %s %s%s %s%s",
1265 pkgDataFlags
[ARFLAGS
],
1267 libFileNames
[LIB_FILE_VERSION
],
1269 libFileNames
[LIB_FILE_VERSION_TMP
]);
1271 result
= runCommand(cmd
);
1273 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1277 sprintf(cmd
, "%s %s%s",
1278 pkgDataFlags
[RANLIB
],
1280 libFileNames
[LIB_FILE_VERSION
]);
1282 result
= runCommand(cmd
);
1284 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1288 /* Remove unneeded library file. */
1289 sprintf(cmd
, "%s %s%s",
1292 libFileNames
[LIB_FILE_VERSION_TMP
]);
1294 result
= runCommand(cmd
);
1296 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1301 uprv_strcpy(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_TMP
]);
1308 * Using the compiler information from the configuration file set by -O option, generate the library file.
1309 * command may be given to allow for a larger buffer for cmd.
1311 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
, UBool specialHandling
) {
1314 UBool freeCmd
= FALSE
;
1317 (void)specialHandling
; // Suppress unused variable compiler warnings on platforms where all usage
1318 // of this parameter is #ifdefed out.
1320 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
1321 * containing many object files and so the calling function should supply a command buffer that is large
1322 * enough to handle this. Otherwise, use the default size.
1324 if (command
!= NULL
) {
1328 if (IN_STATIC_MODE(mode
)) {
1330 length
= uprv_strlen(pkgDataFlags
[AR
]) + uprv_strlen(pkgDataFlags
[ARFLAGS
]) + uprv_strlen(targetDir
) +
1331 uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) + uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[RANLIB
]) + BUFFER_PADDING_SIZE
;
1332 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1333 fprintf(stderr
, "Unable to allocate memory for command.\n");
1338 sprintf(cmd
, "%s %s %s%s %s",
1340 pkgDataFlags
[ARFLAGS
],
1342 libFileNames
[LIB_FILE_VERSION
],
1345 result
= runCommand(cmd
);
1347 sprintf(cmd
, "%s %s%s",
1348 pkgDataFlags
[RANLIB
],
1350 libFileNames
[LIB_FILE_VERSION
]);
1352 result
= runCommand(cmd
);
1354 } else /* if (IN_DLL_MODE(mode)) */ {
1356 length
= uprv_strlen(pkgDataFlags
[GENLIB
]) + uprv_strlen(pkgDataFlags
[LDICUDTFLAGS
]) +
1357 ((uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_VERSION_TMP
])) * 2) +
1358 uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[LD_SONAME
]) +
1359 uprv_strlen(pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
]) +
1360 uprv_strlen(pkgDataFlags
[RPATH_FLAGS
]) + uprv_strlen(pkgDataFlags
[BIR_FLAGS
]) + BUFFER_PADDING_SIZE
;
1361 #if U_PLATFORM == U_PF_CYGWIN
1362 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
1363 #elif U_PLATFORM == U_PF_MINGW
1364 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_MINGW
]);
1366 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1367 fprintf(stderr
, "Unable to allocate memory for command.\n");
1372 #if U_PLATFORM == U_PF_MINGW
1373 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1374 pkgDataFlags
[GENLIB
],
1376 libFileNames
[LIB_FILE_MINGW
],
1377 pkgDataFlags
[LDICUDTFLAGS
],
1379 libFileNames
[LIB_FILE_VERSION_TMP
],
1380 #elif U_PLATFORM == U_PF_CYGWIN
1381 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1382 pkgDataFlags
[GENLIB
],
1384 libFileNames
[LIB_FILE_VERSION_TMP
],
1385 pkgDataFlags
[LDICUDTFLAGS
],
1387 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1388 #elif U_PLATFORM == U_PF_AIX
1389 sprintf(cmd
, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
1392 libFileNames
[LIB_FILE_VERSION_TMP
],
1393 pkgDataFlags
[GENLIB
],
1394 pkgDataFlags
[LDICUDTFLAGS
],
1396 libFileNames
[LIB_FILE_VERSION_TMP
],
1398 sprintf(cmd
, "%s %s -o %s%s %s %s%s %s %s",
1399 pkgDataFlags
[GENLIB
],
1400 pkgDataFlags
[LDICUDTFLAGS
],
1402 libFileNames
[LIB_FILE_VERSION_TMP
],
1405 pkgDataFlags
[LD_SONAME
],
1406 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1407 pkgDataFlags
[RPATH_FLAGS
],
1408 pkgDataFlags
[BIR_FLAGS
]);
1410 /* Generate the library file. */
1411 result
= runCommand(cmd
);
1413 #if U_PLATFORM == U_PF_OS390
1415 char PDS_LibName
[512];
1420 if (specialHandling
&& uprv_strcmp(libFileNames
[LIB_FILE
],"libicudata") == 0) {
1421 if (env_tmp
= getenv("ICU_PDS_NAME")) {
1422 sprintf(PDS_Name
, "%s%s",
1425 strcat(PDS_Name
, getenv("ICU_PDS_NAME_SUFFIX"));
1426 } else if (env_tmp
= getenv("PDS_NAME_PREFIX")) {
1427 sprintf(PDS_Name
, "%s%s",
1429 U_ICU_VERSION_SHORT
"DA");
1431 sprintf(PDS_Name
, "%s%s",
1433 U_ICU_VERSION_SHORT
"DA");
1435 } else if (!specialHandling
&& uprv_strcmp(libFileNames
[LIB_FILE
],"libicudata_stub") == 0) {
1436 if (env_tmp
= getenv("ICU_PDS_NAME")) {
1437 sprintf(PDS_Name
, "%s%s",
1440 strcat(PDS_Name
, getenv("ICU_PDS_NAME_SUFFIX"));
1441 } else if (env_tmp
= getenv("PDS_NAME_PREFIX")) {
1442 sprintf(PDS_Name
, "%s%s",
1444 U_ICU_VERSION_SHORT
"D1");
1446 sprintf(PDS_Name
, "%s%s",
1448 U_ICU_VERSION_SHORT
"D1");
1453 sprintf(PDS_LibName
,"%s%s%s%s%s",
1459 sprintf(cmd
, "%s %s -o %s %s %s%s %s %s",
1460 pkgDataFlags
[GENLIB
],
1461 pkgDataFlags
[LDICUDTFLAGS
],
1464 pkgDataFlags
[LD_SONAME
],
1465 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1466 pkgDataFlags
[RPATH_FLAGS
],
1467 pkgDataFlags
[BIR_FLAGS
]);
1469 result
= runCommand(cmd
);
1475 fprintf(stderr
, "Error generating library file. Failed command: %s\n", cmd
);
1485 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
) {
1486 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1492 /* Remove the ending .s and replace it with .o for the new object file. */
1493 uprv_strcpy(tempObjectFile
, gencFilePath
);
1494 tempObjectFile
[uprv_strlen(tempObjectFile
)-1] = 'o';
1496 length
= uprv_strlen(pkgDataFlags
[COMPILER
]) + uprv_strlen(pkgDataFlags
[LIBFLAGS
])
1497 + uprv_strlen(tempObjectFile
) + uprv_strlen(gencFilePath
) + BUFFER_PADDING_SIZE
;
1499 cmd
= (char *)uprv_malloc(sizeof(char) * length
);
1504 /* Generate the object file. */
1505 sprintf(cmd
, "%s %s -o %s %s",
1506 pkgDataFlags
[COMPILER
],
1507 pkgDataFlags
[LIBFLAGS
],
1511 result
= runCommand(cmd
);
1514 fprintf(stderr
, "Error creating with assembly code. Failed command: %s\n", cmd
);
1518 return pkg_generateLibraryFile(targetDir
, mode
, tempObjectFile
);
1521 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
1523 * Generation of the data library without assembly code needs to compile each data file
1524 * individually and then link it all together.
1525 * Note: Any update to the directory structure of the data needs to be reflected here.
1534 DATA_PREFIX_TRANSLIT
,
1540 const static char DATA_PREFIX
[DATA_PREFIX_LENGTH
][10] = {
1552 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
) {
1554 CharList
*list
= o
->filePaths
;
1555 CharList
*listNames
= o
->files
;
1556 int32_t listSize
= pkg_countCharList(list
);
1559 char gencmnFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1560 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1561 #ifdef USE_SINGLE_CCODE_FILE
1562 char icudtAll
[SMALL_BUFFER_MAX_SIZE
] = "";
1563 FileStream
*icudtAllFile
= NULL
;
1565 sprintf(icudtAll
, "%s%s%sall.c",
1567 PKGDATA_FILE_SEP_STRING
,
1568 libFileNames
[LIB_FILE
]);
1569 /* Remove previous icudtall.c file. */
1570 if (T_FileStream_file_exists(icudtAll
) && (result
= remove(icudtAll
)) != 0) {
1571 fprintf(stderr
, "Unable to remove old icudtall file: %s\n", icudtAll
);
1575 if((icudtAllFile
= T_FileStream_open(icudtAll
, "w"))==NULL
) {
1576 fprintf(stderr
, "Unable to write to icudtall file: %s\n", icudtAll
);
1581 if (list
== NULL
|| listNames
== NULL
) {
1582 /* list and listNames should never be NULL since we are looping through the CharList with
1588 if ((cmd
= (char *)uprv_malloc((listSize
+ 2) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1589 fprintf(stderr
, "Unable to allocate memory for cmd.\n");
1591 } else if ((buffer
= (char *)uprv_malloc((listSize
+ 1) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1592 fprintf(stderr
, "Unable to allocate memory for buffer.\n");
1597 for (int32_t i
= 0; i
< (listSize
+ 1); i
++) {
1602 /* The first iteration calls the gencmn function and initailizes the buffer. */
1603 createCommonDataFile(o
->tmpDir
, o
->shortName
, o
->entryName
, NULL
, o
->srcDir
, o
->comment
, o
->fileListFiles
->str
, 0, TRUE
, o
->verbose
, gencmnFile
);
1605 #ifdef USE_SINGLE_CCODE_FILE
1606 uprv_strcpy(tempObjectFile
, gencmnFile
);
1607 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1609 sprintf(cmd
, "%s %s -o %s %s",
1610 pkgDataFlags
[COMPILER
],
1611 pkgDataFlags
[LIBFLAGS
],
1615 result
= runCommand(cmd
);
1620 sprintf(buffer
, "%s",tempObjectFile
);
1623 char newName
[SMALL_BUFFER_MAX_SIZE
];
1624 char dataName
[SMALL_BUFFER_MAX_SIZE
];
1625 char dataDirName
[SMALL_BUFFER_MAX_SIZE
];
1626 const char *pSubstring
;
1628 name
= listNames
->str
;
1630 newName
[0] = dataName
[0] = 0;
1631 for (int32_t n
= 0; n
< DATA_PREFIX_LENGTH
; n
++) {
1633 sprintf(dataDirName
, "%s%s", DATA_PREFIX
[n
], PKGDATA_FILE_SEP_STRING
);
1634 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
1635 pSubstring
= uprv_strstr(name
, dataDirName
);
1636 if (pSubstring
!= NULL
) {
1637 char newNameTmp
[SMALL_BUFFER_MAX_SIZE
] = "";
1638 const char *p
= name
+ uprv_strlen(dataDirName
);
1639 for (int32_t i
= 0;;i
++) {
1641 newNameTmp
[i
] = '_';
1644 newNameTmp
[i
] = p
[i
];
1649 sprintf(newName
, "%s_%s",
1652 sprintf(dataName
, "%s_%s",
1656 if (newName
[0] != 0) {
1662 printf("# Generating %s \n", gencmnFile
);
1665 writeCCode(file
, o
->tmpDir
, dataName
[0] != 0 ? dataName
: o
->shortName
, newName
[0] != 0 ? newName
: NULL
, gencmnFile
);
1667 #ifdef USE_SINGLE_CCODE_FILE
1668 sprintf(cmd
, "#include \"%s\"\n", gencmnFile
);
1669 T_FileStream_writeLine(icudtAllFile
, cmd
);
1670 /* don't delete the file */
1674 #ifndef USE_SINGLE_CCODE_FILE
1675 uprv_strcpy(tempObjectFile
, gencmnFile
);
1676 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1678 sprintf(cmd
, "%s %s -o %s %s",
1679 pkgDataFlags
[COMPILER
],
1680 pkgDataFlags
[LIBFLAGS
],
1683 result
= runCommand(cmd
);
1685 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1689 uprv_strcat(buffer
, " ");
1690 uprv_strcat(buffer
, tempObjectFile
);
1696 listNames
= listNames
->next
;
1700 #ifdef USE_SINGLE_CCODE_FILE
1701 T_FileStream_close(icudtAllFile
);
1702 uprv_strcpy(tempObjectFile
, icudtAll
);
1703 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1705 sprintf(cmd
, "%s %s -I. -o %s %s",
1706 pkgDataFlags
[COMPILER
],
1707 pkgDataFlags
[LIBFLAGS
],
1711 result
= runCommand(cmd
);
1713 uprv_strcat(buffer
, " ");
1714 uprv_strcat(buffer
, tempObjectFile
);
1716 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1721 /* Generate the library file. */
1722 #if U_PLATFORM == U_PF_OS390
1723 result
= pkg_generateLibraryFile(targetDir
, mode
, buffer
, cmd
, (o
->pdsbuild
&& IN_DLL_MODE(mode
)));
1725 result
= pkg_generateLibraryFile(targetDir
,mode
, buffer
, cmd
);
1736 #ifdef WINDOWS_WITH_MSVC
1737 #define LINK_CMD "link.exe /nologo /release /out:"
1738 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:"
1739 #define LIB_CMD "LIB.exe /nologo /out:"
1740 #define LIB_FILE "icudt.lib"
1741 #define LIB_EXT UDATA_LIB_SUFFIX
1742 #define DLL_EXT UDATA_SO_SUFFIX
1744 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
) {
1746 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1747 if (IN_STATIC_MODE(mode
)) {
1748 char staticLibFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1751 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1753 PKGDATA_FILE_SEP_STRING
,
1754 pkgDataFlags
[LIBPREFIX
],
1758 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1760 PKGDATA_FILE_SEP_STRING
,
1761 (strstr(o
->libName
, "icudt") ? "s" : ""),
1766 sprintf(cmd
, "%s\"%s\" \"%s\"",
1770 } else if (IN_DLL_MODE(mode
)) {
1771 char dllFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1772 char libFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1773 char resFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1774 char tmpResFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1777 uprv_strcpy(dllFilePath
, o
->targetDir
);
1779 uprv_strcpy(dllFilePath
, o
->srcDir
);
1781 uprv_strcat(dllFilePath
, PKGDATA_FILE_SEP_STRING
);
1782 uprv_strcpy(libFilePath
, dllFilePath
);
1785 uprv_strcat(libFilePath
, o
->libName
);
1786 uprv_strcat(libFilePath
, ".lib");
1788 uprv_strcat(dllFilePath
, o
->libName
);
1789 uprv_strcat(dllFilePath
, o
->version
);
1791 if (strstr(o
->libName
, "icudt")) {
1792 uprv_strcat(libFilePath
, LIB_FILE
);
1794 uprv_strcat(libFilePath
, o
->libName
);
1795 uprv_strcat(libFilePath
, ".lib");
1797 uprv_strcat(dllFilePath
, o
->entryName
);
1799 uprv_strcat(dllFilePath
, DLL_EXT
);
1801 uprv_strcpy(tmpResFilePath
, o
->tmpDir
);
1802 uprv_strcat(tmpResFilePath
, PKGDATA_FILE_SEP_STRING
);
1803 uprv_strcat(tmpResFilePath
, ICUDATA_RES_FILE
);
1805 if (T_FileStream_file_exists(tmpResFilePath
)) {
1806 sprintf(resFilePath
, "\"%s\"", tmpResFilePath
);
1809 /* Check if dll file and lib file exists and that it is not newer than genc file. */
1810 if (!o
->rebuild
&& (T_FileStream_file_exists(dllFilePath
) && isFileModTimeLater(dllFilePath
, gencFilePath
)) &&
1811 (T_FileStream_file_exists(libFilePath
) && isFileModTimeLater(libFilePath
, gencFilePath
))) {
1813 printf("# Not rebuilding %s - up to date.\n", gencFilePath
);
1818 sprintf(cmd
, "%s\"%s\" %s\"%s\" \"%s\" %s",
1828 result
= runCommand(cmd
, TRUE
);
1830 fprintf(stderr
, "Error creating Windows DLL library. Failed command: %s\n", cmd
);
1837 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
) {
1838 #if U_PLATFORM == U_PF_AIX
1839 /* AIX needs a map file. */
1842 char tmpbuffer
[SMALL_BUFFER_MAX_SIZE
];
1843 const char MAP_FILE_EXT
[] = ".map";
1844 FileStream
*f
= NULL
;
1845 char mapFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1848 const char rm_cmd
[] = "rm -f all ;";
1850 flag
= pkgDataFlags
[GENLIB
];
1852 /* This portion of the code removes 'rm -f all' in the GENLIB.
1853 * Only occurs in AIX.
1855 if (uprv_strstr(flag
, rm_cmd
) != NULL
) {
1856 char *tmpGenlibFlagBuffer
= NULL
;
1859 length
= uprv_strlen(flag
) + 1;
1860 tmpGenlibFlagBuffer
= (char *)uprv_malloc(length
);
1861 if (tmpGenlibFlagBuffer
== NULL
) {
1862 /* Memory allocation error */
1863 fprintf(stderr
,"Unable to allocate buffer of size: %d.\n", length
);
1867 uprv_strcpy(tmpGenlibFlagBuffer
, flag
);
1869 offset
= uprv_strlen(rm_cmd
);
1871 for (i
= 0; i
< (length
- offset
); i
++) {
1872 flag
[i
] = tmpGenlibFlagBuffer
[offset
+ i
];
1875 /* Zero terminate the string */
1878 uprv_free(tmpGenlibFlagBuffer
);
1881 flag
= pkgDataFlags
[BIR_FLAGS
];
1882 length
= uprv_strlen(pkgDataFlags
[BIR_FLAGS
]);
1884 for (int32_t i
= 0; i
< length
; i
++) {
1885 if (flag
[i
] == MAP_FILE_EXT
[count
]) {
1894 if (count
== uprv_strlen(MAP_FILE_EXT
)) {
1901 for (int32_t i
= 0;;i
++) {
1903 for (int32_t n
= 0;;n
++) {
1904 if (o
->shortName
[n
] == 0) {
1907 tmpbuffer
[index
++] = o
->shortName
[n
];
1911 tmpbuffer
[index
++] = flag
[i
];
1918 uprv_memset(flag
, 0, length
);
1919 uprv_strcpy(flag
, tmpbuffer
);
1921 uprv_strcpy(mapFile
, o
->shortName
);
1922 uprv_strcat(mapFile
, MAP_FILE_EXT
);
1924 f
= T_FileStream_open(mapFile
, "w");
1926 fprintf(stderr
,"Unable to create map file: %s.\n", mapFile
);
1929 sprintf(tmpbuffer
, "%s%s ", o
->entryName
, UDATA_CMN_INTERMEDIATE_SUFFIX
);
1931 T_FileStream_writeLine(f
, tmpbuffer
);
1933 T_FileStream_close(f
);
1936 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
1937 /* Cygwin needs to change flag options. */
1941 flag
= pkgDataFlags
[GENLIB
];
1942 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1944 int32_t position
= length
- 1;
1946 for(;position
>= 0;position
--) {
1947 if (flag
[position
] == '=') {
1953 uprv_memset(flag
+ position
, 0, length
- position
);
1954 #elif U_PLATFORM == U_PF_OS400
1955 /* OS/400 needs to fix the ld options (swap single quote with double quote) */
1959 flag
= pkgDataFlags
[GENLIB
];
1960 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1962 int32_t position
= length
- 1;
1964 for(int32_t i
= 0; i
< length
; i
++) {
1965 if (flag
[i
] == '\'') {
1970 // Don't really need a return value, just need to stop compiler warnings about
1971 // the unused parameter 'o' on platforms where it is not otherwise used.
1975 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
)
1977 CharList
*l
, *tail
= NULL
, *tail2
= NULL
;
1980 char *linePtr
, *lineNext
;
1981 const uint32_t lineMax
= 16300;
1983 int32_t tmpLength
= 0;
1985 int32_t ln
=0; /* line number */
1987 for(l
= o
->fileListFiles
; l
; l
= l
->next
) {
1989 fprintf(stdout
, "# pkgdata: Reading %s..\n", l
->str
);
1992 in
= T_FileStream_open(l
->str
, "r"); /* open files list */
1995 fprintf(stderr
, "Error opening <%s>.\n", l
->str
);
1996 *status
= U_FILE_ACCESS_ERROR
;
2000 while(T_FileStream_readLine(in
, line
, sizeof(line
))!=NULL
) { /* for each line */
2002 if(uprv_strlen(line
)>lineMax
) {
2003 fprintf(stderr
, "%s:%d - line too long (over %d chars)\n", l
->str
, (int)ln
, (int)lineMax
);
2006 /* remove spaces at the beginning */
2008 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */
2009 #if U_PLATFORM != U_PF_OS390
2010 while(isspace(*linePtr
)) {
2015 /* remove trailing newline characters */
2017 if(*s
=='\r' || *s
=='\n') {
2023 if((*linePtr
== 0) || (*linePtr
== '#')) {
2024 continue; /* comment or empty line */
2027 /* Now, process the line */
2030 while(linePtr
&& *linePtr
) { /* process space-separated items */
2031 while(*linePtr
== ' ') {
2034 /* Find the next quote */
2035 if(linePtr
[0] == '"')
2037 lineNext
= uprv_strchr(linePtr
+1, '"');
2038 if(lineNext
== NULL
) {
2039 fprintf(stderr
, "%s:%d - missing trailing double quote (\")\n",
2045 if(*lineNext
!= ' ') {
2046 fprintf(stderr
, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
2047 l
->str
, (int)ln
, (int)(lineNext
-line
), (*lineNext
)?*lineNext
:'0');
2055 lineNext
= uprv_strchr(linePtr
, ' ');
2057 *lineNext
= 0; /* terminate at space */
2063 s
= (char*)getLongPathname(linePtr
);
2065 /* normal mode.. o->files is just the bare list without package names */
2066 o
->files
= pkg_appendToList(o
->files
, &tail
, uprv_strdup(linePtr
));
2067 if(uprv_pathIsAbsolute(s
) || s
[0] == '.') {
2068 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
);
2069 exit(U_ILLEGAL_ARGUMENT_ERROR
);
2071 tmpLength
= uprv_strlen(o
->srcDir
) +
2072 uprv_strlen(s
) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
2073 if((tmp
= (char *)uprv_malloc(tmpLength
)) == NULL
) {
2074 fprintf(stderr
, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength
);
2075 exit(U_MEMORY_ALLOCATION_ERROR
);
2077 uprv_strcpy(tmp
, o
->srcDir
);
2078 uprv_strcat(tmp
, o
->srcDir
[uprv_strlen(o
->srcDir
)-1] == U_FILE_SEP_CHAR
? "" : PKGDATA_FILE_SEP_STRING
);
2079 uprv_strcat(tmp
, s
);
2080 o
->filePaths
= pkg_appendToList(o
->filePaths
, &tail2
, tmp
);
2082 } /* for each entry on line */
2083 } /* for each line */
2084 T_FileStream_close(in
);
2085 } /* for each file list file */
2088 /* Try calling icu-config directly to get the option file. */
2089 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
) {
2093 static char buf
[512] = "";
2094 icu::CharString cmdBuf
;
2095 UErrorCode status
= U_ZERO_ERROR
;
2096 const char cmd
[] = "icu-config --incpkgdatafile";
2097 char dirBuf
[1024] = "";
2098 /* #1 try the same path where pkgdata was called from. */
2099 findDirname(progname
, dirBuf
, UPRV_LENGTHOF(dirBuf
), &status
);
2100 if(U_SUCCESS(status
)) {
2101 cmdBuf
.append(dirBuf
, status
);
2102 if (cmdBuf
[0] != 0) {
2103 cmdBuf
.append( U_FILE_SEP_STRING
, status
);
2105 cmdBuf
.append( cmd
, status
);
2108 fprintf(stdout
, "# Calling icu-config: %s\n", cmdBuf
.data());
2110 p
= popen(cmdBuf
.data(), "r");
2113 if(p
== NULL
|| (n
= fread(buf
, 1, UPRV_LENGTHOF(buf
)-1, p
)) <= 0) {
2115 fprintf(stdout
, "# Calling icu-config: %s\n", cmd
);
2119 p
= popen(cmd
, "r");
2120 if(p
== NULL
|| (n
= fread(buf
, 1, UPRV_LENGTHOF(buf
)-1, p
)) <= 0) {
2121 fprintf(stderr
, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname
);
2128 for (int32_t length
= strlen(buf
) - 1; length
>= 0; length
--) {
2129 if (buf
[length
] == '\n' || buf
[length
] == ' ') {
2136 if(buf
[strlen(buf
)-1]=='\n')
2138 buf
[strlen(buf
)-1]=0;
2143 fprintf(stderr
, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname
);
2148 fprintf(stdout
, "# icu-config said: %s\n", buf
);
2151 option
->value
= buf
;
2152 option
->doesOccur
= TRUE
;
2160 #ifdef CAN_WRITE_OBJ_CODE
2161 /* Create optMatchArch for genccode architecture detection */
2162 static void pkg_createOptMatchArch(char *optMatchArch
) {
2163 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
2164 const char* code
= "void oma(){}";
2165 const char* source
= "oma.c";
2166 const char* obj
= "oma.obj";
2167 FileStream
* stream
= NULL
;
2169 stream
= T_FileStream_open(source
,"w");
2170 if (stream
!= NULL
) {
2171 T_FileStream_writeLine(stream
, code
);
2172 T_FileStream_close(stream
);
2174 char cmd
[SMALL_BUFFER_MAX_SIZE
];
2175 sprintf(cmd
, "%s %s -o %s",
2176 pkgDataFlags
[COMPILER
],
2180 if (runCommand(cmd
) == 0){
2181 sprintf(optMatchArch
, "%s", obj
);
2184 fprintf(stderr
, "Failed to compile %s\n", source
);
2186 if(!T_FileStream_remove(source
)){
2187 fprintf(stderr
, "T_FileStream_remove failed to delete %s\n", source
);
2191 fprintf(stderr
, "T_FileStream_open failed to open %s for writing\n", source
);
2195 static void pkg_destroyOptMatchArch(char *optMatchArch
) {
2196 if(T_FileStream_file_exists(optMatchArch
) && !T_FileStream_remove(optMatchArch
)){
2197 fprintf(stderr
, "T_FileStream_remove failed to delete %s\n", optMatchArch
);