1 /******************************************************************************
2 * Copyright (C) 2000-2016, 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"
61 using icu::LocalPointerBase
;
63 U_DEFINE_LOCAL_OPEN_POINTER(LocalPipeFilePointer
, FILE, pclose
);
67 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
);
69 static int32_t pkg_executeOptions(UPKGOptions
*o
);
71 #ifdef WINDOWS_WITH_MSVC
72 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
);
74 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
=FALSE
);
75 static int32_t pkg_installLibrary(const char *installDir
, const char *dir
, UBool noVersion
);
76 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
);
77 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
);
79 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
80 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
);
83 #ifdef CAN_WRITE_OBJ_CODE
84 static void pkg_createOptMatchArch(char *optMatchArch
);
85 static void pkg_destroyOptMatchArch(char *optMatchArch
);
88 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
);
89 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
= NULL
, UBool specialHandling
=FALSE
);
90 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
);
91 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, const UBool reverseExt
, UBool noVersion
);
92 static int32_t initializePkgDataFlags(UPKGOptions
*o
);
94 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
);
95 static int runCommand(const char* command
, UBool specialHandling
=FALSE
);
97 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
98 #define IN_DLL_MODE(mode) (mode == 'd' || mode == 'l')
99 #define IN_STATIC_MODE(mode) (mode == 's')
100 #define IN_FILES_MODE(mode) (mode == 'f')
125 /* This sets the modes that are available */
127 const char *name
, *alt_name
;
130 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
131 #if U_PLATFORM_HAS_WIN32_API
132 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
133 { "common", "archive", "Generates just the common file, <package>.dat"},
134 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
136 #ifdef UDATA_SO_SUFFIX
137 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX
},
139 { "common", "archive", "Generates one common data file, <package>.dat" },
140 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
144 static UOption options
[]={
145 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG
),
146 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG
), /* on Win32 it is release or debug */
147 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG
),
148 /*03*/ UOPTION_HELP_H
, /* -h */
149 /*04*/ UOPTION_HELP_QUESTION_MARK
, /* -? */
150 /*05*/ UOPTION_VERBOSE
, /* -v */
151 /*06*/ UOPTION_COPYRIGHT
, /* -c */
152 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG
),
153 /*08*/ UOPTION_DESTDIR
, /* -d */
154 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG
),
155 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG
),
156 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG
),
157 /*14*/ UOPTION_SOURCEDIR
,
158 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG
),
159 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG
),
160 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG
),
161 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG
),
162 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG
),
163 /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG
),
164 /*21*/ UOPTION_DEF( "zos-pds-build", 'z', UOPT_NO_ARG
)
167 /* This enum and the following char array should be kept in sync. */
169 GENCCODE_ASSEMBLY_TYPE
,
188 static const char* FLAG_NAMES
[PKGDATA_FLAGS_SIZE
] = {
189 "GENCCODE_ASSEMBLY_TYPE",
207 static char **pkgDataFlags
= NULL
;
211 LIB_FILE_VERSION_MAJOR
,
213 LIB_FILE_VERSION_TMP
,
214 #if U_PLATFORM == U_PF_CYGWIN
216 LIB_FILE_CYGWIN_VERSION
,
217 #elif U_PLATFORM == U_PF_MINGW
219 #elif U_PLATFORM == U_PF_OS390
220 LIB_FILE_OS390BATCH_MAJOR
,
221 LIB_FILE_OS390BATCH_VERSION
,
225 static char libFileNames
[LIB_FILENAMES_SIZE
][256];
227 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
);
229 const char options_help
[][320]={
231 #ifdef U_MAKE_IS_NMAKE
232 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
234 "Specify options for the builder.",
236 "Specify the mode of building (see below; default: common)",
239 "Make the output verbose",
240 "Use the standard ICU copyright",
241 "Use a custom comment (instead of the copyright)",
242 "Specify the destination directory for files",
243 "Force rebuilding of all data",
244 "Specify temporary dir (default: output dir)",
245 "Install the data (specify target)",
246 "Specify a custom source directory",
247 "Specify a custom entrypoint name (default: short name)",
248 "Specify a version when packaging in dll or static mode",
249 "Add package to all file names if not present",
250 "Library name to build (if different than package name)",
251 "Quite mode. (e.g. Do not output a readme file for static libraries)",
252 "Build the data without assembly code",
253 "Build PDS dataset (zOS build only)"
256 const char *progname
= "PKGDATA";
259 main(int argc
, char* argv
[]) {
261 /* FileStream *out; */
264 UBool needsHelp
= FALSE
;
265 UErrorCode status
= U_ZERO_ERROR
;
266 /* char tmp[1024]; */
270 U_MAIN_INIT_ARGS(argc
, argv
);
274 options
[MODE
].value
= "common";
276 /* read command line options */
277 argc
=u_parseArgs(argc
, argv
, UPRV_LENGTHOF(options
), options
);
279 /* error handling, printing usage message */
280 /* I've decided to simply print an error and quit. This tool has too
281 many options to just display them all of the time. */
283 if(options
[HELP
].doesOccur
|| options
[HELP_QUESTION_MARK
].doesOccur
) {
287 if(!needsHelp
&& argc
<0) {
289 "%s: error in command line argument \"%s\"\n",
292 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
297 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
298 if(!options
[BLDOPT
].doesOccur
&& uprv_strcmp(options
[MODE
].value
, "common") != 0) {
299 if (pkg_getOptionsFromICUConfig(options
[VERBOSE
].doesOccur
, &options
[BLDOPT
]) != 0) {
300 fprintf(stderr
, " required parameter is missing: -O is required for static and shared builds.\n");
301 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
306 if(options
[BLDOPT
].doesOccur
) {
307 fprintf(stdout
, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
311 if(!options
[NAME
].doesOccur
) /* -O we already have - don't report it. */
313 fprintf(stderr
, " required parameter -p is missing \n");
314 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
320 "No input files specified.\n"
321 "Run '%s --help' for help.\n", progname
);
324 } /* end !needsHelp */
326 if(argc
<0 || needsHelp
) {
328 "usage: %s [-options] [-] [packageFile] \n"
329 "\tProduce packaged ICU data from the given list(s) of files.\n"
330 "\t'-' by itself means to read from stdin.\n"
331 "\tpackageFile is a text file containing the list of files to package.\n",
334 fprintf(stderr
, "\n options:\n");
335 for(i
=0;i
<UPRV_LENGTHOF(options
);i
++) {
336 fprintf(stderr
, "%-5s -%c %s%-10s %s\n",
338 options
[i
].shortName
,
339 options
[i
].longName
? "or --" : " ",
340 options
[i
].longName
? options
[i
].longName
: "",
344 fprintf(stderr
, "modes: (-m option)\n");
345 for(i
=0;i
<UPRV_LENGTHOF(modes
);i
++) {
346 fprintf(stderr
, " %-9s ", modes
[i
].name
);
347 if (modes
[i
].alt_name
) {
348 fprintf(stderr
, "/ %-9s", modes
[i
].alt_name
);
350 fprintf(stderr
, " ");
352 fprintf(stderr
, " %s\n", modes
[i
].desc
);
357 /* OK, fill in the options struct */
358 uprv_memset(&o
, 0, sizeof(o
));
360 o
.mode
= options
[MODE
].value
;
361 o
.version
= options
[REVISION
].doesOccur
? options
[REVISION
].value
: 0;
363 o
.shortName
= options
[NAME
].value
;
365 int32_t len
= (int32_t)uprv_strlen(o
.shortName
);
369 cp
= csname
= (char *) uprv_malloc((len
+ 1 + 1) * sizeof(*o
.cShortName
));
370 if (*(sp
= o
.shortName
)) {
371 *cp
++ = isalpha(*sp
) ? * sp
: '_';
372 for (++sp
; *sp
; ++sp
) {
373 *cp
++ = isalnum(*sp
) ? *sp
: '_';
378 o
.cShortName
= csname
;
381 if(options
[LIBNAME
].doesOccur
) { /* get libname from shortname, or explicit -L parameter */
382 o
.libName
= options
[LIBNAME
].value
;
384 o
.libName
= o
.shortName
;
387 if(options
[QUIET
].doesOccur
) {
393 if(options
[PDS_BUILD
].doesOccur
) {
394 #if U_PLATFORM == U_PF_OS390
398 fprintf(stdout
, "Warning: You are using the -z option which only works on z/OS.\n");
405 o
.verbose
= options
[VERBOSE
].doesOccur
;
408 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
409 if (options
[BLDOPT
].doesOccur
) {
410 o
.options
= options
[BLDOPT
].value
;
415 if(options
[COPYRIGHT
].doesOccur
) {
416 o
.comment
= U_COPYRIGHT_STRING
;
417 } else if (options
[COMMENT
].doesOccur
) {
418 o
.comment
= options
[COMMENT
].value
;
421 if( options
[DESTDIR
].doesOccur
) {
422 o
.targetDir
= options
[DESTDIR
].value
;
424 o
.targetDir
= "."; /* cwd */
427 o
.rebuild
= options
[REBUILD
].doesOccur
;
429 if( options
[TEMPDIR
].doesOccur
) {
430 o
.tmpDir
= options
[TEMPDIR
].value
;
432 o
.tmpDir
= o
.targetDir
;
435 if( options
[INSTALL
].doesOccur
) {
436 o
.install
= options
[INSTALL
].value
;
441 if( options
[SOURCEDIR
].doesOccur
) {
442 o
.srcDir
= options
[SOURCEDIR
].value
;
447 if( options
[ENTRYPOINT
].doesOccur
) {
448 o
.entryName
= options
[ENTRYPOINT
].value
;
450 o
.entryName
= o
.cShortName
;
453 o
.withoutAssembly
= FALSE
;
454 if (options
[WITHOUT_ASSEMBLY
].doesOccur
) {
455 #ifndef BUILD_DATA_WITHOUT_ASSEMBLY
456 fprintf(stdout
, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n");
457 fprintf(stdout
, "Warning: This option will be ignored.\n");
459 o
.withoutAssembly
= TRUE
;
463 /* OK options are set up. Now the file lists. */
465 for( n
=1; n
<argc
; n
++) {
466 o
.fileListFiles
= pkg_appendToList(o
.fileListFiles
, &tail
, uprv_strdup(argv
[n
]));
470 loadLists(&o
, &status
);
471 if( U_FAILURE(status
) ) {
472 fprintf(stderr
, "error loading input file lists: %s\n", u_errorName(status
));
476 result
= pkg_executeOptions(&o
);
478 if (pkgDataFlags
!= NULL
) {
479 for (n
= 0; n
< PKGDATA_FLAGS_SIZE
; n
++) {
480 if (pkgDataFlags
[n
] != NULL
) {
481 uprv_free(pkgDataFlags
[n
]);
484 uprv_free(pkgDataFlags
);
487 if (o
.cShortName
!= NULL
) {
488 uprv_free((char *)o
.cShortName
);
490 if (o
.fileListFiles
!= NULL
) {
491 pkg_deleteList(o
.fileListFiles
);
493 if (o
.filePaths
!= NULL
) {
494 pkg_deleteList(o
.filePaths
);
496 if (o
.files
!= NULL
) {
497 pkg_deleteList(o
.files
);
503 static int runCommand(const char* command
, UBool specialHandling
) {
505 char cmdBuffer
[SMALL_BUFFER_MAX_SIZE
];
506 int32_t len
= strlen(command
);
512 if (!specialHandling
) {
513 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400
514 if ((len
+ BUFFER_PADDING_SIZE
) >= SMALL_BUFFER_MAX_SIZE
) {
515 cmd
= (char *)uprv_malloc(len
+ BUFFER_PADDING_SIZE
);
519 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
520 sprintf(cmd
, "bash -c \"%s\"", command
);
522 #elif U_PLATFORM == U_PF_OS400
523 sprintf(cmd
, "QSH CMD('%s')", command
);
526 goto normal_command_mode
;
529 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
532 cmd
= (char *)command
;
535 printf("pkgdata: %s\n", cmd
);
536 int result
= system(cmd
);
538 fprintf(stderr
, "-- return status = %d\n", result
);
541 if (cmd
!= cmdBuffer
&& cmd
!= command
) {
548 #define LN_CMD "ln -s"
549 #define RM_CMD "rm -f"
551 static int32_t pkg_executeOptions(UPKGOptions
*o
) {
554 const char mode
= o
->mode
[0];
555 char targetDir
[SMALL_BUFFER_MAX_SIZE
] = "";
556 char tmpDir
[SMALL_BUFFER_MAX_SIZE
] = "";
557 char datFileName
[SMALL_BUFFER_MAX_SIZE
] = "";
558 char datFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
559 char checkLibFile
[LARGE_BUFFER_MAX_SIZE
] = "";
561 initializePkgDataFlags(o
);
563 if (IN_FILES_MODE(mode
)) {
564 /* Copy the raw data to the installation directory. */
565 if (o
->install
!= NULL
) {
566 uprv_strcpy(targetDir
, o
->install
);
567 if (o
->shortName
!= NULL
) {
568 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
569 uprv_strcat(targetDir
, o
->shortName
);
573 fprintf(stdout
, "# Install: Files mode, copying files to %s..\n", targetDir
);
575 result
= pkg_installFileMode(targetDir
, o
->srcDir
, o
->fileListFiles
->str
);
578 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
579 UBool noVersion
= FALSE
;
581 uprv_strcpy(targetDir
, o
->targetDir
);
582 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
584 uprv_strcpy(tmpDir
, o
->tmpDir
);
585 uprv_strcat(tmpDir
, PKGDATA_FILE_SEP_STRING
);
587 uprv_strcpy(datFileNamePath
, tmpDir
);
589 uprv_strcpy(datFileName
, o
->shortName
);
590 uprv_strcat(datFileName
, UDATA_CMN_SUFFIX
);
592 uprv_strcat(datFileNamePath
, datFileName
);
595 fprintf(stdout
, "# Writing package file %s ..\n", datFileNamePath
);
597 result
= writePackageDatFile(datFileNamePath
, o
->comment
, o
->srcDir
, o
->fileListFiles
->str
, NULL
, U_CHARSET_FAMILY
? 'e' : U_IS_BIG_ENDIAN
? 'b' : 'l');
599 fprintf(stderr
,"Error writing package dat file.\n");
603 if (IN_COMMON_MODE(mode
)) {
604 char targetFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
606 uprv_strcpy(targetFileNamePath
, targetDir
);
607 uprv_strcat(targetFileNamePath
, datFileName
);
609 /* Move the dat file created to the target directory. */
610 if (uprv_strcmp(datFileNamePath
, targetFileNamePath
) != 0) {
611 if (T_FileStream_file_exists(targetFileNamePath
)) {
612 if ((result
= remove(targetFileNamePath
)) != 0) {
613 fprintf(stderr
, "Unable to remove old dat file: %s\n",
619 result
= rename(datFileNamePath
, targetFileNamePath
);
622 fprintf(stdout
, "# Moving package file to %s ..\n",
628 "Unable to move dat file (%s) to target location (%s).\n",
629 datFileNamePath
, targetFileNamePath
);
634 if (o
->install
!= NULL
) {
635 result
= pkg_installCommonMode(o
->install
, targetFileNamePath
);
639 } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ {
640 char gencFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
641 char version_major
[10] = "";
642 UBool reverseExt
= FALSE
;
644 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
645 /* Get the version major number. */
646 if (o
->version
!= NULL
) {
647 for (uint32_t i
= 0;i
< sizeof(version_major
);i
++) {
648 if (o
->version
[i
] == '.') {
649 version_major
[i
] = 0;
652 version_major
[i
] = o
->version
[i
];
656 if (IN_DLL_MODE(mode
)) {
657 fprintf(stdout
, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n");
661 #if U_PLATFORM != U_PF_OS400
662 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
663 * reverseExt is FALSE if the suffix should be the version number.
665 if (pkgDataFlags
[LIB_EXT_ORDER
][uprv_strlen(pkgDataFlags
[LIB_EXT_ORDER
])-1] == pkgDataFlags
[SO_EXT
][uprv_strlen(pkgDataFlags
[SO_EXT
])-1]) {
669 /* Using the base libName and version number, generate the library file names. */
670 createFileNames(o
, mode
, version_major
, o
->version
== NULL
? "" : o
->version
, o
->libName
, reverseExt
, noVersion
);
672 if ((o
->version
!=NULL
|| IN_STATIC_MODE(mode
)) && o
->rebuild
== FALSE
&& o
->pdsbuild
== FALSE
) {
673 /* Check to see if a previous built data library file exists and check if it is the latest. */
674 sprintf(checkLibFile
, "%s%s", targetDir
, libFileNames
[LIB_FILE_VERSION
]);
675 if (T_FileStream_file_exists(checkLibFile
)) {
676 if (isFileModTimeLater(checkLibFile
, o
->srcDir
, TRUE
) && isFileModTimeLater(checkLibFile
, o
->options
)) {
677 if (o
->install
!= NULL
) {
679 fprintf(stdout
, "# Installing already-built library into %s\n", o
->install
);
681 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
684 printf("# Not rebuilding %s - up to date.\n", checkLibFile
);
688 } else if (o
->verbose
&& (o
->install
!=NULL
)) {
689 fprintf(stdout
, "# Not installing up-to-date library %s into %s\n", checkLibFile
, o
->install
);
691 } else if(o
->verbose
&& (o
->install
!=NULL
)) {
692 fprintf(stdout
, "# Not installing missing %s into %s\n", checkLibFile
, o
->install
);
696 if (pkg_checkFlag(o
) == NULL
) {
697 /* Error occurred. */
702 if (!o
->withoutAssembly
&& pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
][0] != 0) {
703 const char* genccodeAssembly
= pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
];
706 fprintf(stdout
, "# Generating assembly code %s of type %s ..\n", gencFilePath
, genccodeAssembly
);
709 /* Offset genccodeAssembly by 3 because "-a " */
710 if (genccodeAssembly
&&
711 (uprv_strlen(genccodeAssembly
)>3) &&
712 checkAssemblyHeaderName(genccodeAssembly
+3)) {
713 writeAssemblyCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, NULL
, gencFilePath
);
715 result
= pkg_createWithAssemblyCode(targetDir
, mode
, gencFilePath
);
717 fprintf(stderr
, "Error generating assembly code for data.\n");
719 } else if (IN_STATIC_MODE(mode
)) {
720 if(o
->install
!= NULL
) {
722 fprintf(stdout
, "# Installing static library into %s\n", o
->install
);
724 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
729 fprintf(stderr
,"Assembly type \"%s\" is unknown.\n", genccodeAssembly
);
734 fprintf(stdout
, "# Writing object code to %s ..\n", gencFilePath
);
736 if (o
->withoutAssembly
) {
737 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
738 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
740 /* This error should not occur. */
741 fprintf(stderr
, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
744 #ifdef CAN_WRITE_OBJ_CODE
745 /* Try to detect the arch type, use NULL if unsuccessful */
746 char optMatchArch
[10] = { 0 };
747 pkg_createOptMatchArch(optMatchArch
);
748 writeObjectCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, (optMatchArch
[0] == 0 ? NULL
: optMatchArch
), NULL
, gencFilePath
);
749 pkg_destroyOptMatchArch(optMatchArch
);
750 #if U_PLATFORM_IS_LINUX_BASED
751 result
= pkg_generateLibraryFile(targetDir
, mode
, gencFilePath
);
752 #elif defined(WINDOWS_WITH_MSVC)
753 result
= pkg_createWindowsDLL(mode
, gencFilePath
, o
);
755 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
756 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
758 fprintf(stderr
, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
764 fprintf(stderr
, "Error generating package data.\n");
768 #if !U_PLATFORM_USES_ONLY_WIN32_API
769 if(!IN_STATIC_MODE(mode
)) {
770 /* Certain platforms uses archive library. (e.g. AIX) */
772 fprintf(stdout
, "# Creating data archive library file ..\n");
774 result
= pkg_archiveLibrary(targetDir
, o
->version
, reverseExt
);
776 fprintf(stderr
, "Error creating data archive library file.\n");
779 #if U_PLATFORM != U_PF_OS400
781 /* Create symbolic links for the final library file. */
782 #if U_PLATFORM == U_PF_OS390
783 result
= pkg_createSymLinks(targetDir
, o
->pdsbuild
);
785 result
= pkg_createSymLinks(targetDir
, noVersion
);
788 fprintf(stderr
, "Error creating symbolic links of the data library file.\n");
793 } /* !IN_STATIC_MODE */
796 #if !U_PLATFORM_USES_ONLY_WIN32_API
797 /* Install the libraries if option was set. */
798 if (o
->install
!= NULL
) {
800 fprintf(stdout
, "# Installing library file to %s ..\n", o
->install
);
802 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
804 fprintf(stderr
, "Error installing the data library.\n");
814 /* Initialize the pkgDataFlags with the option file given. */
815 static int32_t initializePkgDataFlags(UPKGOptions
*o
) {
816 UErrorCode status
= U_ZERO_ERROR
;
818 int32_t currentBufferSize
= SMALL_BUFFER_MAX_SIZE
;
819 int32_t tmpResult
= 0;
821 /* Initialize pkgdataFlags */
822 pkgDataFlags
= (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE
);
824 /* If we run out of space, allocate more */
825 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
828 if (pkgDataFlags
!= NULL
) {
829 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
830 pkgDataFlags
[i
] = (char*)uprv_malloc(sizeof(char) * currentBufferSize
);
831 if (pkgDataFlags
[i
] != NULL
) {
832 pkgDataFlags
[i
][0] = 0;
834 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
835 /* If an error occurs, ensure that the rest of the array is NULL */
836 for (int32_t n
= i
+ 1; n
< PKGDATA_FLAGS_SIZE
; n
++) {
837 pkgDataFlags
[n
] = NULL
;
843 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
847 if (o
->options
== NULL
) {
851 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
852 /* Read in options file. */
854 fprintf(stdout
, "# Reading options file %s\n", o
->options
);
856 status
= U_ZERO_ERROR
;
857 tmpResult
= parseFlagsFile(o
->options
, pkgDataFlags
, currentBufferSize
, FLAG_NAMES
, (int32_t)PKGDATA_FLAGS_SIZE
, &status
);
858 if (status
== U_BUFFER_OVERFLOW_ERROR
) {
859 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
860 if (pkgDataFlags
[i
]) {
861 uprv_free(pkgDataFlags
[i
]);
862 pkgDataFlags
[i
] = NULL
;
865 currentBufferSize
= tmpResult
;
866 } else if (U_FAILURE(status
)) {
867 fprintf(stderr
,"Unable to open or read \"%s\" option file. status = %s\n", o
->options
, u_errorName(status
));
872 fprintf(stdout
, "# pkgDataFlags=\n");
873 for(int32_t i
=0;i
<PKGDATA_FLAGS_SIZE
;i
++) {
874 fprintf(stdout
, " [%d] %s: %s\n", i
, FLAG_NAMES
[i
], pkgDataFlags
[i
]);
876 fprintf(stdout
, "\n");
878 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
879 } while (status
== U_BUFFER_OVERFLOW_ERROR
);
887 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
888 * Depending on the configuration, the library name may either end with version number or shared object suffix.
890 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, UBool reverseExt
, UBool noVersion
) {
891 const char* FILE_EXTENSION_SEP
= uprv_strlen(pkgDataFlags
[SO_EXT
]) == 0 ? "" : ".";
892 const char* FILE_SUFFIX
= pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "";
894 #if U_PLATFORM == U_PF_MINGW
895 /* MinGW does not need the library prefix when building in dll mode. */
896 if (IN_DLL_MODE(mode
)) {
897 sprintf(libFileNames
[LIB_FILE
], "%s", libName
);
899 sprintf(libFileNames
[LIB_FILE
], "%s%s",
900 pkgDataFlags
[LIBPREFIX
],
904 sprintf(libFileNames
[LIB_FILE
], "%s%s",
905 pkgDataFlags
[LIBPREFIX
],
910 fprintf(stdout
, "# libFileName[LIB_FILE] = %s\n", libFileNames
[LIB_FILE
]);
913 #if U_PLATFORM == U_PF_MINGW
914 // Name the import library lib*.dll.a
915 sprintf(libFileNames
[LIB_FILE_MINGW
], "lib%s.dll.a", libName
);
916 #elif U_PLATFORM == U_PF_CYGWIN
917 sprintf(libFileNames
[LIB_FILE_CYGWIN
], "cyg%s%s%s",
920 pkgDataFlags
[SO_EXT
]);
921 sprintf(libFileNames
[LIB_FILE_CYGWIN_VERSION
], "cyg%s%s%s%s",
925 pkgDataFlags
[SO_EXT
]);
927 uprv_strcat(pkgDataFlags
[SO_EXT
], ".");
928 uprv_strcat(pkgDataFlags
[SO_EXT
], pkgDataFlags
[A_EXT
]);
929 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
930 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s",
931 libFileNames
[LIB_FILE
],
933 pkgDataFlags
[SOBJ_EXT
]);
934 #elif U_PLATFORM == U_PF_OS390
935 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s%s%s",
936 libFileNames
[LIB_FILE
],
937 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
938 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
940 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
942 sprintf(libFileNames
[LIB_FILE_OS390BATCH_VERSION
], "%s%s.x",
943 libFileNames
[LIB_FILE
],
945 sprintf(libFileNames
[LIB_FILE_OS390BATCH_MAJOR
], "%s%s.x",
946 libFileNames
[LIB_FILE
],
949 if (noVersion
&& !reverseExt
) {
950 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s",
951 libFileNames
[LIB_FILE
],
953 pkgDataFlags
[SOBJ_EXT
]);
955 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s%s%s",
956 libFileNames
[LIB_FILE
],
958 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
960 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
963 if (noVersion
&& !reverseExt
) {
964 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s",
965 libFileNames
[LIB_FILE
],
967 pkgDataFlags
[SO_EXT
]);
969 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s",
970 libFileNames
[LIB_FILE
],
972 pkgDataFlags
[SO_EXT
]);
974 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s%s%s",
975 libFileNames
[LIB_FILE
],
977 reverseExt
? version_major
: pkgDataFlags
[SO_EXT
],
979 reverseExt
? pkgDataFlags
[SO_EXT
] : version_major
);
981 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s%s%s",
982 libFileNames
[LIB_FILE
],
984 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
986 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
990 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames
[LIB_FILE_VERSION
]);
993 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
994 /* Cygwin and MinGW only deals with the version major number. */
995 uprv_strcpy(libFileNames
[LIB_FILE_VERSION_TMP
], libFileNames
[LIB_FILE_VERSION_MAJOR
]);
998 if(IN_STATIC_MODE(mode
)) {
999 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s.%s", libFileNames
[LIB_FILE
], pkgDataFlags
[A_EXT
]);
1000 libFileNames
[LIB_FILE_VERSION_MAJOR
][0]=0;
1002 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames
[LIB_FILE_VERSION
]);
1007 /* Create the symbolic links for the final library file. */
1008 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
) {
1010 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1011 char name1
[SMALL_BUFFER_MAX_SIZE
]; /* symlink file name */
1012 char name2
[SMALL_BUFFER_MAX_SIZE
]; /* file name to symlink */
1013 const char* FILE_EXTENSION_SEP
= uprv_strlen(pkgDataFlags
[SO_EXT
]) == 0 ? "" : ".";
1015 #if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW
1016 /* No symbolic link to make. */
1017 if (uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) == 0 || uprv_strlen(libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0 ||
1018 uprv_strcmp(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0) {
1022 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1025 libFileNames
[LIB_FILE_VERSION_MAJOR
],
1027 libFileNames
[LIB_FILE_VERSION
],
1028 libFileNames
[LIB_FILE_VERSION_MAJOR
]);
1029 result
= runCommand(cmd
);
1031 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1036 if (specialHandling
) {
1037 #if U_PLATFORM == U_PF_CYGWIN
1038 sprintf(name1
, "%s", libFileNames
[LIB_FILE_CYGWIN
]);
1039 sprintf(name2
, "%s", libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
1040 #elif U_PLATFORM == U_PF_OS390
1041 /* Create the symbolic links for the import data */
1042 /* Use the cmd buffer to store path to import data file to check its existence */
1043 sprintf(cmd
, "%s/%s", targetDir
, libFileNames
[LIB_FILE_OS390BATCH_VERSION
]);
1044 if (T_FileStream_file_exists(cmd
)) {
1045 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1048 libFileNames
[LIB_FILE_OS390BATCH_MAJOR
],
1050 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1051 libFileNames
[LIB_FILE_OS390BATCH_MAJOR
]);
1052 result
= runCommand(cmd
);
1054 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1058 sprintf(cmd
, "cd %s && %s %s.x && %s %s %s.x",
1061 libFileNames
[LIB_FILE
],
1063 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1064 libFileNames
[LIB_FILE
]);
1065 result
= runCommand(cmd
);
1067 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
1072 /* Needs to be set here because special handling skips it */
1073 sprintf(name1
, "%s%s%s", libFileNames
[LIB_FILE
], FILE_EXTENSION_SEP
, pkgDataFlags
[SO_EXT
]);
1074 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
1076 goto normal_symlink_mode
;
1079 #if U_PLATFORM != U_PF_CYGWIN
1080 normal_symlink_mode
:
1082 sprintf(name1
, "%s%s%s", libFileNames
[LIB_FILE
], FILE_EXTENSION_SEP
, pkgDataFlags
[SO_EXT
]);
1083 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
1086 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1094 result
= runCommand(cmd
);
1099 static int32_t pkg_installLibrary(const char *installDir
, const char *targetDir
, UBool noVersion
) {
1101 char cmd
[SMALL_BUFFER_MAX_SIZE
];
1103 sprintf(cmd
, "cd %s && %s %s %s%s%s",
1105 pkgDataFlags
[INSTALL_CMD
],
1106 libFileNames
[LIB_FILE_VERSION
],
1107 installDir
, PKGDATA_FILE_SEP_STRING
, libFileNames
[LIB_FILE_VERSION
]
1110 result
= runCommand(cmd
);
1113 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1118 sprintf(cmd
, "cd %s && %s %s.lib %s",
1120 pkgDataFlags
[INSTALL_CMD
],
1121 libFileNames
[LIB_FILE
],
1124 result
= runCommand(cmd
);
1127 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1130 #elif U_PLATFORM == U_PF_CYGWIN
1131 sprintf(cmd
, "cd %s && %s %s %s",
1133 pkgDataFlags
[INSTALL_CMD
],
1134 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1137 result
= runCommand(cmd
);
1140 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1144 #elif U_PLATFORM == U_PF_OS390
1145 if (T_FileStream_file_exists(libFileNames
[LIB_FILE_OS390BATCH_VERSION
])) {
1146 sprintf(cmd
, "%s %s %s",
1147 pkgDataFlags
[INSTALL_CMD
],
1148 libFileNames
[LIB_FILE_OS390BATCH_VERSION
],
1151 result
= runCommand(cmd
);
1154 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1163 return pkg_createSymLinks(installDir
, TRUE
);
1167 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
) {
1169 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1171 if (!T_FileStream_file_exists(installDir
)) {
1172 UErrorCode status
= U_ZERO_ERROR
;
1174 uprv_mkdir(installDir
, &status
);
1175 if (U_FAILURE(status
)) {
1176 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1180 #ifndef U_WINDOWS_WITH_MSVC
1181 sprintf(cmd
, "%s %s %s", pkgDataFlags
[INSTALL_CMD
], fileName
, installDir
);
1183 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, fileName
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1186 result
= runCommand(cmd
);
1188 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1194 #ifdef U_WINDOWS_MSVC
1195 /* Copy commands for installing the raw data files on Windows. */
1196 #define WIN_INSTALL_CMD "xcopy"
1197 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
1199 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
) {
1201 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1203 if (!T_FileStream_file_exists(installDir
)) {
1204 UErrorCode status
= U_ZERO_ERROR
;
1206 uprv_mkdir(installDir
, &status
);
1207 if (U_FAILURE(status
)) {
1208 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1212 #ifndef U_WINDOWS_WITH_MSVC
1213 char buffer
[SMALL_BUFFER_MAX_SIZE
] = "";
1214 int32_t bufferLength
= 0;
1216 FileStream
*f
= T_FileStream_open(fileListName
, "r");
1219 if (T_FileStream_readLine(f
, buffer
, SMALL_BUFFER_MAX_SIZE
) != NULL
) {
1220 bufferLength
= uprv_strlen(buffer
);
1221 /* Remove new line character. */
1222 if (bufferLength
> 0) {
1223 buffer
[bufferLength
-1] = 0;
1226 sprintf(cmd
, "%s %s%s%s %s%s%s",
1227 pkgDataFlags
[INSTALL_CMD
],
1228 srcDir
, PKGDATA_FILE_SEP_STRING
, buffer
,
1229 installDir
, PKGDATA_FILE_SEP_STRING
, buffer
);
1231 result
= runCommand(cmd
);
1233 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1237 if (!T_FileStream_eof(f
)) {
1238 fprintf(stderr
, "Failed to read line from file: %s\n", fileListName
);
1244 T_FileStream_close(f
);
1247 fprintf(stderr
, "Unable to open list file: %s\n", fileListName
);
1250 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, srcDir
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1251 result
= runCommand(cmd
);
1253 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1260 /* Archiving of the library file may be needed depending on the platform and options given.
1261 * If archiving is not needed, copy over the library file name.
1263 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
) {
1265 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1267 /* If the shared object suffix and the final object suffix is different and the final object suffix and the
1268 * archive file suffix is the same, then the final library needs to be archived.
1270 if (uprv_strcmp(pkgDataFlags
[SOBJ_EXT
], pkgDataFlags
[SO_EXT
]) != 0 && uprv_strcmp(pkgDataFlags
[A_EXT
], pkgDataFlags
[SO_EXT
]) == 0) {
1271 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s.%s",
1272 libFileNames
[LIB_FILE
],
1273 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
1274 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
1275 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
1277 sprintf(cmd
, "%s %s %s%s %s%s",
1279 pkgDataFlags
[ARFLAGS
],
1281 libFileNames
[LIB_FILE_VERSION
],
1283 libFileNames
[LIB_FILE_VERSION_TMP
]);
1285 result
= runCommand(cmd
);
1287 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1291 sprintf(cmd
, "%s %s%s",
1292 pkgDataFlags
[RANLIB
],
1294 libFileNames
[LIB_FILE_VERSION
]);
1296 result
= runCommand(cmd
);
1298 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1302 /* Remove unneeded library file. */
1303 sprintf(cmd
, "%s %s%s",
1306 libFileNames
[LIB_FILE_VERSION_TMP
]);
1308 result
= runCommand(cmd
);
1310 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1315 uprv_strcpy(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_TMP
]);
1322 * Using the compiler information from the configuration file set by -O option, generate the library file.
1323 * command may be given to allow for a larger buffer for cmd.
1325 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
, UBool specialHandling
) {
1328 UBool freeCmd
= FALSE
;
1331 (void)specialHandling
; // Suppress unused variable compiler warnings on platforms where all usage
1332 // of this parameter is #ifdefed out.
1334 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
1335 * containing many object files and so the calling function should supply a command buffer that is large
1336 * enough to handle this. Otherwise, use the default size.
1338 if (command
!= NULL
) {
1342 if (IN_STATIC_MODE(mode
)) {
1344 length
= uprv_strlen(pkgDataFlags
[AR
]) + uprv_strlen(pkgDataFlags
[ARFLAGS
]) + uprv_strlen(targetDir
) +
1345 uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) + uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[RANLIB
]) + BUFFER_PADDING_SIZE
;
1346 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1347 fprintf(stderr
, "Unable to allocate memory for command.\n");
1352 sprintf(cmd
, "%s %s %s%s %s",
1354 pkgDataFlags
[ARFLAGS
],
1356 libFileNames
[LIB_FILE_VERSION
],
1359 result
= runCommand(cmd
);
1361 sprintf(cmd
, "%s %s%s",
1362 pkgDataFlags
[RANLIB
],
1364 libFileNames
[LIB_FILE_VERSION
]);
1366 result
= runCommand(cmd
);
1368 } else /* if (IN_DLL_MODE(mode)) */ {
1370 length
= uprv_strlen(pkgDataFlags
[GENLIB
]) + uprv_strlen(pkgDataFlags
[LDICUDTFLAGS
]) +
1371 ((uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_VERSION_TMP
])) * 2) +
1372 uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[LD_SONAME
]) +
1373 uprv_strlen(pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
]) +
1374 uprv_strlen(pkgDataFlags
[RPATH_FLAGS
]) + uprv_strlen(pkgDataFlags
[BIR_FLAGS
]) + BUFFER_PADDING_SIZE
;
1375 #if U_PLATFORM == U_PF_CYGWIN
1376 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
1377 #elif U_PLATFORM == U_PF_MINGW
1378 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_MINGW
]);
1380 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1381 fprintf(stderr
, "Unable to allocate memory for command.\n");
1386 #if U_PLATFORM == U_PF_MINGW
1387 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1388 pkgDataFlags
[GENLIB
],
1390 libFileNames
[LIB_FILE_MINGW
],
1391 pkgDataFlags
[LDICUDTFLAGS
],
1393 libFileNames
[LIB_FILE_VERSION_TMP
],
1394 #elif U_PLATFORM == U_PF_CYGWIN
1395 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1396 pkgDataFlags
[GENLIB
],
1398 libFileNames
[LIB_FILE_VERSION_TMP
],
1399 pkgDataFlags
[LDICUDTFLAGS
],
1401 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1402 #elif U_PLATFORM == U_PF_AIX
1403 sprintf(cmd
, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
1406 libFileNames
[LIB_FILE_VERSION_TMP
],
1407 pkgDataFlags
[GENLIB
],
1408 pkgDataFlags
[LDICUDTFLAGS
],
1410 libFileNames
[LIB_FILE_VERSION_TMP
],
1412 sprintf(cmd
, "%s %s -o %s%s %s %s%s %s %s",
1413 pkgDataFlags
[GENLIB
],
1414 pkgDataFlags
[LDICUDTFLAGS
],
1416 libFileNames
[LIB_FILE_VERSION_TMP
],
1419 pkgDataFlags
[LD_SONAME
],
1420 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1421 pkgDataFlags
[RPATH_FLAGS
],
1422 pkgDataFlags
[BIR_FLAGS
]);
1424 /* Generate the library file. */
1425 result
= runCommand(cmd
);
1427 #if U_PLATFORM == U_PF_OS390
1429 char PDS_LibName
[512];
1434 if (specialHandling
&& uprv_strcmp(libFileNames
[LIB_FILE
],"libicudata") == 0) {
1435 if (env_tmp
= getenv("ICU_PDS_NAME")) {
1436 sprintf(PDS_Name
, "%s%s",
1439 strcat(PDS_Name
, getenv("ICU_PDS_NAME_SUFFIX"));
1440 } else if (env_tmp
= getenv("PDS_NAME_PREFIX")) {
1441 sprintf(PDS_Name
, "%s%s",
1443 U_ICU_VERSION_SHORT
"DA");
1445 sprintf(PDS_Name
, "%s%s",
1447 U_ICU_VERSION_SHORT
"DA");
1449 } else if (!specialHandling
&& uprv_strcmp(libFileNames
[LIB_FILE
],"libicudata_stub") == 0) {
1450 if (env_tmp
= getenv("ICU_PDS_NAME")) {
1451 sprintf(PDS_Name
, "%s%s",
1454 strcat(PDS_Name
, getenv("ICU_PDS_NAME_SUFFIX"));
1455 } else if (env_tmp
= getenv("PDS_NAME_PREFIX")) {
1456 sprintf(PDS_Name
, "%s%s",
1458 U_ICU_VERSION_SHORT
"D1");
1460 sprintf(PDS_Name
, "%s%s",
1462 U_ICU_VERSION_SHORT
"D1");
1467 sprintf(PDS_LibName
,"%s%s%s%s%s",
1473 sprintf(cmd
, "%s %s -o %s %s %s%s %s %s",
1474 pkgDataFlags
[GENLIB
],
1475 pkgDataFlags
[LDICUDTFLAGS
],
1478 pkgDataFlags
[LD_SONAME
],
1479 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1480 pkgDataFlags
[RPATH_FLAGS
],
1481 pkgDataFlags
[BIR_FLAGS
]);
1483 result
= runCommand(cmd
);
1489 fprintf(stderr
, "Error generating library file. Failed command: %s\n", cmd
);
1499 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
) {
1500 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1506 /* Remove the ending .s and replace it with .o for the new object file. */
1507 uprv_strcpy(tempObjectFile
, gencFilePath
);
1508 tempObjectFile
[uprv_strlen(tempObjectFile
)-1] = 'o';
1510 length
= uprv_strlen(pkgDataFlags
[COMPILER
]) + uprv_strlen(pkgDataFlags
[LIBFLAGS
])
1511 + uprv_strlen(tempObjectFile
) + uprv_strlen(gencFilePath
) + BUFFER_PADDING_SIZE
;
1513 cmd
= (char *)uprv_malloc(sizeof(char) * length
);
1518 /* Generate the object file. */
1519 sprintf(cmd
, "%s %s -o %s %s",
1520 pkgDataFlags
[COMPILER
],
1521 pkgDataFlags
[LIBFLAGS
],
1525 result
= runCommand(cmd
);
1528 fprintf(stderr
, "Error creating with assembly code. Failed command: %s\n", cmd
);
1532 return pkg_generateLibraryFile(targetDir
, mode
, tempObjectFile
);
1535 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
1537 * Generation of the data library without assembly code needs to compile each data file
1538 * individually and then link it all together.
1539 * Note: Any update to the directory structure of the data needs to be reflected here.
1548 DATA_PREFIX_TRANSLIT
,
1554 const static char DATA_PREFIX
[DATA_PREFIX_LENGTH
][10] = {
1566 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
) {
1568 CharList
*list
= o
->filePaths
;
1569 CharList
*listNames
= o
->files
;
1570 int32_t listSize
= pkg_countCharList(list
);
1573 char gencmnFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1574 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1575 #ifdef USE_SINGLE_CCODE_FILE
1576 char icudtAll
[SMALL_BUFFER_MAX_SIZE
] = "";
1577 FileStream
*icudtAllFile
= NULL
;
1579 sprintf(icudtAll
, "%s%s%sall.c",
1581 PKGDATA_FILE_SEP_STRING
,
1582 libFileNames
[LIB_FILE
]);
1583 /* Remove previous icudtall.c file. */
1584 if (T_FileStream_file_exists(icudtAll
) && (result
= remove(icudtAll
)) != 0) {
1585 fprintf(stderr
, "Unable to remove old icudtall file: %s\n", icudtAll
);
1589 if((icudtAllFile
= T_FileStream_open(icudtAll
, "w"))==NULL
) {
1590 fprintf(stderr
, "Unable to write to icudtall file: %s\n", icudtAll
);
1595 if (list
== NULL
|| listNames
== NULL
) {
1596 /* list and listNames should never be NULL since we are looping through the CharList with
1602 if ((cmd
= (char *)uprv_malloc((listSize
+ 2) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1603 fprintf(stderr
, "Unable to allocate memory for cmd.\n");
1605 } else if ((buffer
= (char *)uprv_malloc((listSize
+ 1) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1606 fprintf(stderr
, "Unable to allocate memory for buffer.\n");
1611 for (int32_t i
= 0; i
< (listSize
+ 1); i
++) {
1616 /* The first iteration calls the gencmn function and initailizes the buffer. */
1617 createCommonDataFile(o
->tmpDir
, o
->shortName
, o
->entryName
, NULL
, o
->srcDir
, o
->comment
, o
->fileListFiles
->str
, 0, TRUE
, o
->verbose
, gencmnFile
);
1619 #ifdef USE_SINGLE_CCODE_FILE
1620 uprv_strcpy(tempObjectFile
, gencmnFile
);
1621 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1623 sprintf(cmd
, "%s %s -o %s %s",
1624 pkgDataFlags
[COMPILER
],
1625 pkgDataFlags
[LIBFLAGS
],
1629 result
= runCommand(cmd
);
1634 sprintf(buffer
, "%s",tempObjectFile
);
1637 char newName
[SMALL_BUFFER_MAX_SIZE
];
1638 char dataName
[SMALL_BUFFER_MAX_SIZE
];
1639 char dataDirName
[SMALL_BUFFER_MAX_SIZE
];
1640 const char *pSubstring
;
1642 name
= listNames
->str
;
1644 newName
[0] = dataName
[0] = 0;
1645 for (int32_t n
= 0; n
< DATA_PREFIX_LENGTH
; n
++) {
1647 sprintf(dataDirName
, "%s%s", DATA_PREFIX
[n
], PKGDATA_FILE_SEP_STRING
);
1648 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
1649 pSubstring
= uprv_strstr(name
, dataDirName
);
1650 if (pSubstring
!= NULL
) {
1651 char newNameTmp
[SMALL_BUFFER_MAX_SIZE
] = "";
1652 const char *p
= name
+ uprv_strlen(dataDirName
);
1653 for (int32_t i
= 0;;i
++) {
1655 newNameTmp
[i
] = '_';
1658 newNameTmp
[i
] = p
[i
];
1663 sprintf(newName
, "%s_%s",
1666 sprintf(dataName
, "%s_%s",
1670 if (newName
[0] != 0) {
1676 printf("# Generating %s \n", gencmnFile
);
1679 writeCCode(file
, o
->tmpDir
, dataName
[0] != 0 ? dataName
: o
->shortName
, newName
[0] != 0 ? newName
: NULL
, gencmnFile
);
1681 #ifdef USE_SINGLE_CCODE_FILE
1682 sprintf(cmd
, "#include \"%s\"\n", gencmnFile
);
1683 T_FileStream_writeLine(icudtAllFile
, cmd
);
1684 /* don't delete the file */
1688 #ifndef USE_SINGLE_CCODE_FILE
1689 uprv_strcpy(tempObjectFile
, gencmnFile
);
1690 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1692 sprintf(cmd
, "%s %s -o %s %s",
1693 pkgDataFlags
[COMPILER
],
1694 pkgDataFlags
[LIBFLAGS
],
1697 result
= runCommand(cmd
);
1699 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1703 uprv_strcat(buffer
, " ");
1704 uprv_strcat(buffer
, tempObjectFile
);
1710 listNames
= listNames
->next
;
1714 #ifdef USE_SINGLE_CCODE_FILE
1715 T_FileStream_close(icudtAllFile
);
1716 uprv_strcpy(tempObjectFile
, icudtAll
);
1717 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1719 sprintf(cmd
, "%s %s -I. -o %s %s",
1720 pkgDataFlags
[COMPILER
],
1721 pkgDataFlags
[LIBFLAGS
],
1725 result
= runCommand(cmd
);
1727 uprv_strcat(buffer
, " ");
1728 uprv_strcat(buffer
, tempObjectFile
);
1730 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1735 /* Generate the library file. */
1736 #if U_PLATFORM == U_PF_OS390
1737 result
= pkg_generateLibraryFile(targetDir
, mode
, buffer
, cmd
, (o
->pdsbuild
&& IN_DLL_MODE(mode
)));
1739 result
= pkg_generateLibraryFile(targetDir
,mode
, buffer
, cmd
);
1750 #ifdef WINDOWS_WITH_MSVC
1751 #define LINK_CMD "link.exe /nologo /release /out:"
1752 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:"
1753 #define LIB_CMD "LIB.exe /nologo /out:"
1754 #define LIB_FILE "icudt.lib"
1755 #define LIB_EXT UDATA_LIB_SUFFIX
1756 #define DLL_EXT UDATA_SO_SUFFIX
1758 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
) {
1760 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1761 if (IN_STATIC_MODE(mode
)) {
1762 char staticLibFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1765 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1767 PKGDATA_FILE_SEP_STRING
,
1768 pkgDataFlags
[LIBPREFIX
],
1772 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1774 PKGDATA_FILE_SEP_STRING
,
1775 (strstr(o
->libName
, "icudt") ? "s" : ""),
1780 sprintf(cmd
, "%s\"%s\" \"%s\"",
1784 } else if (IN_DLL_MODE(mode
)) {
1785 char dllFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1786 char libFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1787 char resFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1788 char tmpResFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1791 uprv_strcpy(dllFilePath
, o
->targetDir
);
1793 uprv_strcpy(dllFilePath
, o
->srcDir
);
1795 uprv_strcat(dllFilePath
, PKGDATA_FILE_SEP_STRING
);
1796 uprv_strcpy(libFilePath
, dllFilePath
);
1799 uprv_strcat(libFilePath
, o
->libName
);
1800 uprv_strcat(libFilePath
, ".lib");
1802 uprv_strcat(dllFilePath
, o
->libName
);
1803 uprv_strcat(dllFilePath
, o
->version
);
1805 if (strstr(o
->libName
, "icudt")) {
1806 uprv_strcat(libFilePath
, LIB_FILE
);
1808 uprv_strcat(libFilePath
, o
->libName
);
1809 uprv_strcat(libFilePath
, ".lib");
1811 uprv_strcat(dllFilePath
, o
->entryName
);
1813 uprv_strcat(dllFilePath
, DLL_EXT
);
1815 uprv_strcpy(tmpResFilePath
, o
->tmpDir
);
1816 uprv_strcat(tmpResFilePath
, PKGDATA_FILE_SEP_STRING
);
1817 uprv_strcat(tmpResFilePath
, ICUDATA_RES_FILE
);
1819 if (T_FileStream_file_exists(tmpResFilePath
)) {
1820 sprintf(resFilePath
, "\"%s\"", tmpResFilePath
);
1823 /* Check if dll file and lib file exists and that it is not newer than genc file. */
1824 if (!o
->rebuild
&& (T_FileStream_file_exists(dllFilePath
) && isFileModTimeLater(dllFilePath
, gencFilePath
)) &&
1825 (T_FileStream_file_exists(libFilePath
) && isFileModTimeLater(libFilePath
, gencFilePath
))) {
1827 printf("# Not rebuilding %s - up to date.\n", gencFilePath
);
1832 sprintf(cmd
, "%s\"%s\" %s\"%s\" \"%s\" %s",
1842 result
= runCommand(cmd
, TRUE
);
1844 fprintf(stderr
, "Error creating Windows DLL library. Failed command: %s\n", cmd
);
1851 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
) {
1852 #if U_PLATFORM == U_PF_AIX
1853 /* AIX needs a map file. */
1856 char tmpbuffer
[SMALL_BUFFER_MAX_SIZE
];
1857 const char MAP_FILE_EXT
[] = ".map";
1858 FileStream
*f
= NULL
;
1859 char mapFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1862 const char rm_cmd
[] = "rm -f all ;";
1864 flag
= pkgDataFlags
[GENLIB
];
1866 /* This portion of the code removes 'rm -f all' in the GENLIB.
1867 * Only occurs in AIX.
1869 if (uprv_strstr(flag
, rm_cmd
) != NULL
) {
1870 char *tmpGenlibFlagBuffer
= NULL
;
1873 length
= uprv_strlen(flag
) + 1;
1874 tmpGenlibFlagBuffer
= (char *)uprv_malloc(length
);
1875 if (tmpGenlibFlagBuffer
== NULL
) {
1876 /* Memory allocation error */
1877 fprintf(stderr
,"Unable to allocate buffer of size: %d.\n", length
);
1881 uprv_strcpy(tmpGenlibFlagBuffer
, flag
);
1883 offset
= uprv_strlen(rm_cmd
);
1885 for (i
= 0; i
< (length
- offset
); i
++) {
1886 flag
[i
] = tmpGenlibFlagBuffer
[offset
+ i
];
1889 /* Zero terminate the string */
1892 uprv_free(tmpGenlibFlagBuffer
);
1895 flag
= pkgDataFlags
[BIR_FLAGS
];
1896 length
= uprv_strlen(pkgDataFlags
[BIR_FLAGS
]);
1898 for (int32_t i
= 0; i
< length
; i
++) {
1899 if (flag
[i
] == MAP_FILE_EXT
[count
]) {
1908 if (count
== uprv_strlen(MAP_FILE_EXT
)) {
1915 for (int32_t i
= 0;;i
++) {
1917 for (int32_t n
= 0;;n
++) {
1918 if (o
->shortName
[n
] == 0) {
1921 tmpbuffer
[index
++] = o
->shortName
[n
];
1925 tmpbuffer
[index
++] = flag
[i
];
1932 uprv_memset(flag
, 0, length
);
1933 uprv_strcpy(flag
, tmpbuffer
);
1935 uprv_strcpy(mapFile
, o
->shortName
);
1936 uprv_strcat(mapFile
, MAP_FILE_EXT
);
1938 f
= T_FileStream_open(mapFile
, "w");
1940 fprintf(stderr
,"Unable to create map file: %s.\n", mapFile
);
1943 sprintf(tmpbuffer
, "%s%s ", o
->entryName
, UDATA_CMN_INTERMEDIATE_SUFFIX
);
1945 T_FileStream_writeLine(f
, tmpbuffer
);
1947 T_FileStream_close(f
);
1950 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
1951 /* Cygwin needs to change flag options. */
1955 flag
= pkgDataFlags
[GENLIB
];
1956 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1958 int32_t position
= length
- 1;
1960 for(;position
>= 0;position
--) {
1961 if (flag
[position
] == '=') {
1967 uprv_memset(flag
+ position
, 0, length
- position
);
1968 #elif U_PLATFORM == U_PF_OS400
1969 /* OS/400 needs to fix the ld options (swap single quote with double quote) */
1973 flag
= pkgDataFlags
[GENLIB
];
1974 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1976 int32_t position
= length
- 1;
1978 for(int32_t i
= 0; i
< length
; i
++) {
1979 if (flag
[i
] == '\'') {
1984 // Don't really need a return value, just need to stop compiler warnings about
1985 // the unused parameter 'o' on platforms where it is not otherwise used.
1989 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
)
1991 CharList
*l
, *tail
= NULL
, *tail2
= NULL
;
1994 char *linePtr
, *lineNext
;
1995 const uint32_t lineMax
= 16300;
1997 int32_t tmpLength
= 0;
1999 int32_t ln
=0; /* line number */
2001 for(l
= o
->fileListFiles
; l
; l
= l
->next
) {
2003 fprintf(stdout
, "# pkgdata: Reading %s..\n", l
->str
);
2006 in
= T_FileStream_open(l
->str
, "r"); /* open files list */
2009 fprintf(stderr
, "Error opening <%s>.\n", l
->str
);
2010 *status
= U_FILE_ACCESS_ERROR
;
2014 while(T_FileStream_readLine(in
, line
, sizeof(line
))!=NULL
) { /* for each line */
2016 if(uprv_strlen(line
)>lineMax
) {
2017 fprintf(stderr
, "%s:%d - line too long (over %d chars)\n", l
->str
, (int)ln
, (int)lineMax
);
2020 /* remove spaces at the beginning */
2022 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */
2023 #if U_PLATFORM != U_PF_OS390
2024 while(isspace(*linePtr
)) {
2029 /* remove trailing newline characters */
2031 if(*s
=='\r' || *s
=='\n') {
2037 if((*linePtr
== 0) || (*linePtr
== '#')) {
2038 continue; /* comment or empty line */
2041 /* Now, process the line */
2044 while(linePtr
&& *linePtr
) { /* process space-separated items */
2045 while(*linePtr
== ' ') {
2048 /* Find the next quote */
2049 if(linePtr
[0] == '"')
2051 lineNext
= uprv_strchr(linePtr
+1, '"');
2052 if(lineNext
== NULL
) {
2053 fprintf(stderr
, "%s:%d - missing trailing double quote (\")\n",
2059 if(*lineNext
!= ' ') {
2060 fprintf(stderr
, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
2061 l
->str
, (int)ln
, (int)(lineNext
-line
), (*lineNext
)?*lineNext
:'0');
2069 lineNext
= uprv_strchr(linePtr
, ' ');
2071 *lineNext
= 0; /* terminate at space */
2077 s
= (char*)getLongPathname(linePtr
);
2079 /* normal mode.. o->files is just the bare list without package names */
2080 o
->files
= pkg_appendToList(o
->files
, &tail
, uprv_strdup(linePtr
));
2081 if(uprv_pathIsAbsolute(s
) || s
[0] == '.') {
2082 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
);
2083 exit(U_ILLEGAL_ARGUMENT_ERROR
);
2085 tmpLength
= uprv_strlen(o
->srcDir
) +
2086 uprv_strlen(s
) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
2087 if((tmp
= (char *)uprv_malloc(tmpLength
)) == NULL
) {
2088 fprintf(stderr
, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength
);
2089 exit(U_MEMORY_ALLOCATION_ERROR
);
2091 uprv_strcpy(tmp
, o
->srcDir
);
2092 uprv_strcat(tmp
, o
->srcDir
[uprv_strlen(o
->srcDir
)-1] == U_FILE_SEP_CHAR
? "" : PKGDATA_FILE_SEP_STRING
);
2093 uprv_strcat(tmp
, s
);
2094 o
->filePaths
= pkg_appendToList(o
->filePaths
, &tail2
, tmp
);
2096 } /* for each entry on line */
2097 } /* for each line */
2098 T_FileStream_close(in
);
2099 } /* for each file list file */
2102 /* Try calling icu-config directly to get the option file. */
2103 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
) {
2105 LocalPipeFilePointer p
;
2107 static char buf
[512] = "";
2108 icu::CharString cmdBuf
;
2109 UErrorCode status
= U_ZERO_ERROR
;
2110 const char cmd
[] = "icu-config --incpkgdatafile";
2111 char dirBuf
[1024] = "";
2112 /* #1 try the same path where pkgdata was called from. */
2113 findDirname(progname
, dirBuf
, UPRV_LENGTHOF(dirBuf
), &status
);
2114 if(U_SUCCESS(status
)) {
2115 cmdBuf
.append(dirBuf
, status
);
2116 if (cmdBuf
[0] != 0) {
2117 cmdBuf
.append( U_FILE_SEP_STRING
, status
);
2119 cmdBuf
.append( cmd
, status
);
2122 fprintf(stdout
, "# Calling icu-config: %s\n", cmdBuf
.data());
2124 p
.adoptInstead(popen(cmdBuf
.data(), "r"));
2127 if(p
.isNull() || (n
= fread(buf
, 1, UPRV_LENGTHOF(buf
)-1, p
.getAlias())) <= 0) {
2129 fprintf(stdout
, "# Calling icu-config: %s\n", cmd
);
2132 p
.adoptInstead(popen(cmd
, "r"));
2133 if(p
.isNull() || (n
= fread(buf
, 1, UPRV_LENGTHOF(buf
)-1, p
.getAlias())) <= 0) {
2134 fprintf(stderr
, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname
);
2139 for (int32_t length
= strlen(buf
) - 1; length
>= 0; length
--) {
2140 if (buf
[length
] == '\n' || buf
[length
] == ' ') {
2147 if(buf
[strlen(buf
)-1]=='\n')
2149 buf
[strlen(buf
)-1]=0;
2154 fprintf(stderr
, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname
);
2159 fprintf(stdout
, "# icu-config said: %s\n", buf
);
2162 option
->value
= buf
;
2163 option
->doesOccur
= TRUE
;
2171 #ifdef CAN_WRITE_OBJ_CODE
2172 /* Create optMatchArch for genccode architecture detection */
2173 static void pkg_createOptMatchArch(char *optMatchArch
) {
2174 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
2175 const char* code
= "void oma(){}";
2176 const char* source
= "oma.c";
2177 const char* obj
= "oma.obj";
2178 FileStream
* stream
= NULL
;
2180 stream
= T_FileStream_open(source
,"w");
2181 if (stream
!= NULL
) {
2182 T_FileStream_writeLine(stream
, code
);
2183 T_FileStream_close(stream
);
2185 char cmd
[LARGE_BUFFER_MAX_SIZE
];
2186 sprintf(cmd
, "%s %s -o %s",
2187 pkgDataFlags
[COMPILER
],
2191 if (runCommand(cmd
) == 0){
2192 sprintf(optMatchArch
, "%s", obj
);
2195 fprintf(stderr
, "Failed to compile %s\n", source
);
2197 if(!T_FileStream_remove(source
)){
2198 fprintf(stderr
, "T_FileStream_remove failed to delete %s\n", source
);
2202 fprintf(stderr
, "T_FileStream_open failed to open %s for writing\n", source
);
2206 static void pkg_destroyOptMatchArch(char *optMatchArch
) {
2207 if(T_FileStream_file_exists(optMatchArch
) && !T_FileStream_remove(optMatchArch
)){
2208 fprintf(stderr
, "T_FileStream_remove failed to delete %s\n", optMatchArch
);