1 /******************************************************************************
2 * Copyright (C) 2000-2013, 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"
59 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
);
61 static int32_t pkg_executeOptions(UPKGOptions
*o
);
63 #ifdef WINDOWS_WITH_MSVC
64 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
);
66 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
=FALSE
);
67 static int32_t pkg_installLibrary(const char *installDir
, const char *dir
, UBool noVersion
);
68 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
);
69 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
);
71 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
72 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
);
75 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
);
76 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
= NULL
);
77 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
);
78 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, const UBool reverseExt
, UBool noVersion
);
79 static int32_t initializePkgDataFlags(UPKGOptions
*o
);
81 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
);
82 static int runCommand(const char* command
, UBool specialHandling
=FALSE
);
84 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
85 #define IN_DLL_MODE(mode) (mode == 'd' || mode == 'l')
86 #define IN_STATIC_MODE(mode) (mode == 's')
87 #define IN_FILES_MODE(mode) (mode == 'f')
112 /* This sets the modes that are available */
114 const char *name
, *alt_name
;
117 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
118 #if U_PLATFORM_HAS_WIN32_API
119 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
120 { "common", "archive", "Generates just the common file, <package>.dat"},
121 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
123 #ifdef UDATA_SO_SUFFIX
124 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX
},
126 { "common", "archive", "Generates one common data file, <package>.dat" },
127 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
131 static UOption options
[]={
132 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG
),
133 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG
), /* on Win32 it is release or debug */
134 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG
),
135 /*03*/ UOPTION_HELP_H
, /* -h */
136 /*04*/ UOPTION_HELP_QUESTION_MARK
, /* -? */
137 /*05*/ UOPTION_VERBOSE
, /* -v */
138 /*06*/ UOPTION_COPYRIGHT
, /* -c */
139 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG
),
140 /*08*/ UOPTION_DESTDIR
, /* -d */
141 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG
),
142 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG
),
143 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG
),
144 /*14*/ UOPTION_SOURCEDIR
,
145 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG
),
146 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG
),
147 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG
),
148 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG
),
149 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG
),
150 /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG
),
151 /*21*/ UOPTION_DEF( "zos-pds-build", 'z', UOPT_NO_ARG
)
154 /* This enum and the following char array should be kept in sync. */
156 GENCCODE_ASSEMBLY_TYPE
,
175 static const char* FLAG_NAMES
[PKGDATA_FLAGS_SIZE
] = {
176 "GENCCODE_ASSEMBLY_TYPE",
194 static char **pkgDataFlags
= NULL
;
198 LIB_FILE_VERSION_MAJOR
,
200 LIB_FILE_VERSION_TMP
,
201 #if U_PLATFORM == U_PF_CYGWIN
203 LIB_FILE_CYGWIN_VERSION
,
204 #elif U_PLATFORM == U_PF_MINGW
209 static char libFileNames
[LIB_FILENAMES_SIZE
][256];
211 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
);
213 const char options_help
[][320]={
215 #ifdef U_MAKE_IS_NMAKE
216 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
218 "Specify options for the builder.",
220 "Specify the mode of building (see below; default: common)",
223 "Make the output verbose",
224 "Use the standard ICU copyright",
225 "Use a custom comment (instead of the copyright)",
226 "Specify the destination directory for files",
227 "Force rebuilding of all data",
228 "Specify temporary dir (default: output dir)",
229 "Install the data (specify target)",
230 "Specify a custom source directory",
231 "Specify a custom entrypoint name (default: short name)",
232 "Specify a version when packaging in dll or static mode",
233 "Add package to all file names if not present",
234 "Library name to build (if different than package name)",
235 "Quite mode. (e.g. Do not output a readme file for static libraries)",
236 "Build the data without assembly code"
239 const char *progname
= "PKGDATA";
242 main(int argc
, char* argv
[]) {
244 /* FileStream *out; */
247 UBool needsHelp
= FALSE
;
248 UErrorCode status
= U_ZERO_ERROR
;
249 /* char tmp[1024]; */
253 U_MAIN_INIT_ARGS(argc
, argv
);
257 options
[MODE
].value
= "common";
259 /* read command line options */
260 argc
=u_parseArgs(argc
, argv
, sizeof(options
)/sizeof(options
[0]), options
);
262 /* error handling, printing usage message */
263 /* I've decided to simply print an error and quit. This tool has too
264 many options to just display them all of the time. */
266 if(options
[HELP
].doesOccur
|| options
[HELP_QUESTION_MARK
].doesOccur
) {
270 if(!needsHelp
&& argc
<0) {
272 "%s: error in command line argument \"%s\"\n",
275 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
280 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
281 if(!options
[BLDOPT
].doesOccur
&& uprv_strcmp(options
[MODE
].value
, "common") != 0) {
282 if (pkg_getOptionsFromICUConfig(options
[VERBOSE
].doesOccur
, &options
[BLDOPT
]) != 0) {
283 fprintf(stderr
, " required parameter is missing: -O is required for static and shared builds.\n");
284 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
289 if(options
[BLDOPT
].doesOccur
) {
290 fprintf(stdout
, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
294 if(!options
[NAME
].doesOccur
) /* -O we already have - don't report it. */
296 fprintf(stderr
, " required parameter -p is missing \n");
297 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
303 "No input files specified.\n"
304 "Run '%s --help' for help.\n", progname
);
307 } /* end !needsHelp */
309 if(argc
<0 || needsHelp
) {
311 "usage: %s [-options] [-] [packageFile] \n"
312 "\tProduce packaged ICU data from the given list(s) of files.\n"
313 "\t'-' by itself means to read from stdin.\n"
314 "\tpackageFile is a text file containing the list of files to package.\n",
317 fprintf(stderr
, "\n options:\n");
318 for(i
=0;i
<(sizeof(options
)/sizeof(options
[0]));i
++) {
319 fprintf(stderr
, "%-5s -%c %s%-10s %s\n",
321 options
[i
].shortName
,
322 options
[i
].longName
? "or --" : " ",
323 options
[i
].longName
? options
[i
].longName
: "",
327 fprintf(stderr
, "modes: (-m option)\n");
328 for(i
=0;i
<(sizeof(modes
)/sizeof(modes
[0]));i
++) {
329 fprintf(stderr
, " %-9s ", modes
[i
].name
);
330 if (modes
[i
].alt_name
) {
331 fprintf(stderr
, "/ %-9s", modes
[i
].alt_name
);
333 fprintf(stderr
, " ");
335 fprintf(stderr
, " %s\n", modes
[i
].desc
);
340 /* OK, fill in the options struct */
341 uprv_memset(&o
, 0, sizeof(o
));
343 o
.mode
= options
[MODE
].value
;
344 o
.version
= options
[REVISION
].doesOccur
? options
[REVISION
].value
: 0;
346 o
.shortName
= options
[NAME
].value
;
348 int32_t len
= (int32_t)uprv_strlen(o
.shortName
);
352 cp
= csname
= (char *) uprv_malloc((len
+ 1 + 1) * sizeof(*o
.cShortName
));
353 if (*(sp
= o
.shortName
)) {
354 *cp
++ = isalpha(*sp
) ? * sp
: '_';
355 for (++sp
; *sp
; ++sp
) {
356 *cp
++ = isalnum(*sp
) ? *sp
: '_';
361 o
.cShortName
= csname
;
364 if(options
[LIBNAME
].doesOccur
) { /* get libname from shortname, or explicit -L parameter */
365 o
.libName
= options
[LIBNAME
].value
;
367 o
.libName
= o
.shortName
;
370 if(options
[QUIET
].doesOccur
) {
376 if(options
[PDS_BUILD
].doesOccur
) {
382 o
.verbose
= options
[VERBOSE
].doesOccur
;
385 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
386 if (options
[BLDOPT
].doesOccur
) {
387 o
.options
= options
[BLDOPT
].value
;
392 if(options
[COPYRIGHT
].doesOccur
) {
393 o
.comment
= U_COPYRIGHT_STRING
;
394 } else if (options
[COMMENT
].doesOccur
) {
395 o
.comment
= options
[COMMENT
].value
;
398 if( options
[DESTDIR
].doesOccur
) {
399 o
.targetDir
= options
[DESTDIR
].value
;
401 o
.targetDir
= "."; /* cwd */
404 o
.rebuild
= options
[REBUILD
].doesOccur
;
406 if( options
[TEMPDIR
].doesOccur
) {
407 o
.tmpDir
= options
[TEMPDIR
].value
;
409 o
.tmpDir
= o
.targetDir
;
412 if( options
[INSTALL
].doesOccur
) {
413 o
.install
= options
[INSTALL
].value
;
418 if( options
[SOURCEDIR
].doesOccur
) {
419 o
.srcDir
= options
[SOURCEDIR
].value
;
424 if( options
[ENTRYPOINT
].doesOccur
) {
425 o
.entryName
= options
[ENTRYPOINT
].value
;
427 o
.entryName
= o
.cShortName
;
430 o
.withoutAssembly
= FALSE
;
431 if (options
[WITHOUT_ASSEMBLY
].doesOccur
) {
432 #ifndef BUILD_DATA_WITHOUT_ASSEMBLY
433 fprintf(stdout
, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n");
434 fprintf(stdout
, "Warning: This option will be ignored.\n");
436 o
.withoutAssembly
= TRUE
;
440 /* OK options are set up. Now the file lists. */
442 for( n
=1; n
<argc
; n
++) {
443 o
.fileListFiles
= pkg_appendToList(o
.fileListFiles
, &tail
, uprv_strdup(argv
[n
]));
447 loadLists(&o
, &status
);
448 if( U_FAILURE(status
) ) {
449 fprintf(stderr
, "error loading input file lists: %s\n", u_errorName(status
));
453 result
= pkg_executeOptions(&o
);
455 if (pkgDataFlags
!= NULL
) {
456 for (n
= 0; n
< PKGDATA_FLAGS_SIZE
; n
++) {
457 if (pkgDataFlags
[n
] != NULL
) {
458 uprv_free(pkgDataFlags
[n
]);
461 uprv_free(pkgDataFlags
);
464 if (o
.cShortName
!= NULL
) {
465 uprv_free((char *)o
.cShortName
);
467 if (o
.fileListFiles
!= NULL
) {
468 pkg_deleteList(o
.fileListFiles
);
470 if (o
.filePaths
!= NULL
) {
471 pkg_deleteList(o
.filePaths
);
473 if (o
.files
!= NULL
) {
474 pkg_deleteList(o
.files
);
480 static int runCommand(const char* command
, UBool specialHandling
) {
482 char cmdBuffer
[SMALL_BUFFER_MAX_SIZE
];
483 int32_t len
= strlen(command
);
489 if (!specialHandling
) {
490 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400
491 if ((len
+ BUFFER_PADDING_SIZE
) >= SMALL_BUFFER_MAX_SIZE
) {
492 cmd
= (char *)uprv_malloc(len
+ BUFFER_PADDING_SIZE
);
496 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
497 sprintf(cmd
, "bash -c \"%s\"", command
);
499 #elif U_PLATFORM == U_PF_OS400
500 sprintf(cmd
, "QSH CMD('%s')", command
);
503 goto normal_command_mode
;
506 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
509 cmd
= (char *)command
;
512 printf("pkgdata: %s\n", cmd
);
513 int result
= system(cmd
);
515 fprintf(stderr
, "-- return status = %d\n", result
);
518 if (cmd
!= cmdBuffer
&& cmd
!= command
) {
525 #define LN_CMD "ln -s"
526 #define RM_CMD "rm -f"
528 static int32_t pkg_executeOptions(UPKGOptions
*o
) {
531 const char mode
= o
->mode
[0];
532 char targetDir
[SMALL_BUFFER_MAX_SIZE
] = "";
533 char tmpDir
[SMALL_BUFFER_MAX_SIZE
] = "";
534 char datFileName
[SMALL_BUFFER_MAX_SIZE
] = "";
535 char datFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
536 char checkLibFile
[LARGE_BUFFER_MAX_SIZE
] = "";
538 initializePkgDataFlags(o
);
540 if (IN_FILES_MODE(mode
)) {
541 /* Copy the raw data to the installation directory. */
542 if (o
->install
!= NULL
) {
543 uprv_strcpy(targetDir
, o
->install
);
544 if (o
->shortName
!= NULL
) {
545 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
546 uprv_strcat(targetDir
, o
->shortName
);
550 fprintf(stdout
, "# Install: Files mode, copying files to %s..\n", targetDir
);
552 result
= pkg_installFileMode(targetDir
, o
->srcDir
, o
->fileListFiles
->str
);
555 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
556 UBool noVersion
= FALSE
;
558 uprv_strcpy(targetDir
, o
->targetDir
);
559 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
561 uprv_strcpy(tmpDir
, o
->tmpDir
);
562 uprv_strcat(tmpDir
, PKGDATA_FILE_SEP_STRING
);
564 uprv_strcpy(datFileNamePath
, tmpDir
);
566 uprv_strcpy(datFileName
, o
->shortName
);
567 uprv_strcat(datFileName
, UDATA_CMN_SUFFIX
);
569 uprv_strcat(datFileNamePath
, datFileName
);
572 fprintf(stdout
, "# Writing package file %s ..\n", datFileNamePath
);
574 result
= writePackageDatFile(datFileNamePath
, o
->comment
, o
->srcDir
, o
->fileListFiles
->str
, NULL
, U_CHARSET_FAMILY
? 'e' : U_IS_BIG_ENDIAN
? 'b' : 'l');
576 fprintf(stderr
,"Error writing package dat file.\n");
580 if (IN_COMMON_MODE(mode
)) {
581 char targetFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
583 uprv_strcpy(targetFileNamePath
, targetDir
);
584 uprv_strcat(targetFileNamePath
, datFileName
);
586 /* Move the dat file created to the target directory. */
587 if (uprv_strcmp(datFileNamePath
, targetFileNamePath
) != 0) {
588 if (T_FileStream_file_exists(targetFileNamePath
)) {
589 if ((result
= remove(targetFileNamePath
)) != 0) {
590 fprintf(stderr
, "Unable to remove old dat file: %s\n",
596 result
= rename(datFileNamePath
, targetFileNamePath
);
599 fprintf(stdout
, "# Moving package file to %s ..\n",
605 "Unable to move dat file (%s) to target location (%s).\n",
606 datFileNamePath
, targetFileNamePath
);
611 if (o
->install
!= NULL
) {
612 result
= pkg_installCommonMode(o
->install
, targetFileNamePath
);
616 } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ {
617 char gencFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
618 char version_major
[10] = "";
619 UBool reverseExt
= FALSE
;
621 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
622 /* Get the version major number. */
623 if (o
->version
!= NULL
) {
624 for (uint32_t i
= 0;i
< sizeof(version_major
);i
++) {
625 if (o
->version
[i
] == '.') {
626 version_major
[i
] = 0;
629 version_major
[i
] = o
->version
[i
];
633 if (IN_DLL_MODE(mode
)) {
634 fprintf(stdout
, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n");
638 #if U_PLATFORM != U_PF_OS400
639 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
640 * reverseExt is FALSE if the suffix should be the version number.
642 if (pkgDataFlags
[LIB_EXT_ORDER
][uprv_strlen(pkgDataFlags
[LIB_EXT_ORDER
])-1] == pkgDataFlags
[SO_EXT
][uprv_strlen(pkgDataFlags
[SO_EXT
])-1]) {
646 /* Using the base libName and version number, generate the library file names. */
647 createFileNames(o
, mode
, version_major
, o
->version
== NULL
? "" : o
->version
, o
->libName
, reverseExt
, noVersion
);
649 if ((o
->version
!=NULL
|| IN_STATIC_MODE(mode
)) && o
->rebuild
== FALSE
) {
650 /* Check to see if a previous built data library file exists and check if it is the latest. */
651 sprintf(checkLibFile
, "%s%s", targetDir
, libFileNames
[LIB_FILE_VERSION
]);
652 if (T_FileStream_file_exists(checkLibFile
)) {
653 if (isFileModTimeLater(checkLibFile
, o
->srcDir
, TRUE
) && isFileModTimeLater(checkLibFile
, o
->options
)) {
654 if (o
->install
!= NULL
) {
656 fprintf(stdout
, "# Installing already-built library into %s\n", o
->install
);
658 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
661 printf("# Not rebuilding %s - up to date.\n", checkLibFile
);
665 } else if (o
->verbose
&& (o
->install
!=NULL
)) {
666 fprintf(stdout
, "# Not installing up-to-date library %s into %s\n", checkLibFile
, o
->install
);
668 } else if(o
->verbose
&& (o
->install
!=NULL
)) {
669 fprintf(stdout
, "# Not installing missing %s into %s\n", checkLibFile
, o
->install
);
673 if (pkg_checkFlag(o
) == NULL
) {
674 /* Error occurred. */
679 if (!o
->withoutAssembly
&& pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
][0] != 0) {
680 const char* genccodeAssembly
= pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
];
683 fprintf(stdout
, "# Generating assembly code %s of type %s ..\n", gencFilePath
, genccodeAssembly
);
686 /* Offset genccodeAssembly by 3 because "-a " */
687 if (genccodeAssembly
&&
688 (uprv_strlen(genccodeAssembly
)>3) &&
689 checkAssemblyHeaderName(genccodeAssembly
+3)) {
690 writeAssemblyCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, NULL
, gencFilePath
);
692 result
= pkg_createWithAssemblyCode(targetDir
, mode
, gencFilePath
);
694 fprintf(stderr
, "Error generating assembly code for data.\n");
696 } else if (IN_STATIC_MODE(mode
)) {
697 if(o
->install
!= NULL
) {
699 fprintf(stdout
, "# Installing static library into %s\n", o
->install
);
701 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
706 fprintf(stderr
,"Assembly type \"%s\" is unknown.\n", genccodeAssembly
);
711 fprintf(stdout
, "# Writing object code to %s ..\n", gencFilePath
);
713 if (o
->withoutAssembly
) {
714 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
715 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
717 /* This error should not occur. */
718 fprintf(stderr
, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
721 #ifdef CAN_WRITE_OBJ_CODE
722 writeObjectCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, NULL
, NULL
, gencFilePath
);
723 #if U_PLATFORM_IS_LINUX_BASED
724 result
= pkg_generateLibraryFile(targetDir
, mode
, gencFilePath
);
725 #elif defined(WINDOWS_WITH_MSVC)
726 result
= pkg_createWindowsDLL(mode
, gencFilePath
, o
);
728 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
729 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
731 fprintf(stderr
, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
737 fprintf(stderr
, "Error generating package data.\n");
741 #if !U_PLATFORM_USES_ONLY_WIN32_API
742 if(!IN_STATIC_MODE(mode
)) {
743 /* Certain platforms uses archive library. (e.g. AIX) */
745 fprintf(stdout
, "# Creating data archive library file ..\n");
747 result
= pkg_archiveLibrary(targetDir
, o
->version
, reverseExt
);
749 fprintf(stderr
, "Error creating data archive library file.\n");
752 #if U_PLATFORM != U_PF_OS400
754 /* Create symbolic links for the final library file. */
755 #if U_PLATFORM == U_PF_OS390
757 result
= pkg_createSymLinks(targetDir
, noVersion
);
760 result
= pkg_createSymLinks(targetDir
, noVersion
);
763 fprintf(stderr
, "Error creating symbolic links of the data library file.\n");
768 } /* !IN_STATIC_MODE */
771 #if !U_PLATFORM_USES_ONLY_WIN32_API
772 /* Install the libraries if option was set. */
773 if (o
->install
!= NULL
) {
775 fprintf(stdout
, "# Installing library file to %s ..\n", o
->install
);
777 result
= pkg_installLibrary(o
->install
, targetDir
, noVersion
);
779 fprintf(stderr
, "Error installing the data library.\n");
789 /* Initialize the pkgDataFlags with the option file given. */
790 static int32_t initializePkgDataFlags(UPKGOptions
*o
) {
791 UErrorCode status
= U_ZERO_ERROR
;
793 int32_t currentBufferSize
= SMALL_BUFFER_MAX_SIZE
;
794 int32_t tmpResult
= 0;
796 /* Initialize pkgdataFlags */
797 pkgDataFlags
= (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE
);
799 /* If we run out of space, allocate more */
800 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
803 if (pkgDataFlags
!= NULL
) {
804 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
805 pkgDataFlags
[i
] = (char*)uprv_malloc(sizeof(char) * currentBufferSize
);
806 if (pkgDataFlags
[i
] != NULL
) {
807 pkgDataFlags
[i
][0] = 0;
809 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
814 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
818 if (o
->options
== NULL
) {
822 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
823 /* Read in options file. */
825 fprintf(stdout
, "# Reading options file %s\n", o
->options
);
827 status
= U_ZERO_ERROR
;
828 tmpResult
= parseFlagsFile(o
->options
, pkgDataFlags
, currentBufferSize
, FLAG_NAMES
, (int32_t)PKGDATA_FLAGS_SIZE
, &status
);
829 if (status
== U_BUFFER_OVERFLOW_ERROR
) {
830 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
831 uprv_free(pkgDataFlags
[i
]);
833 currentBufferSize
= tmpResult
;
834 } else if (U_FAILURE(status
)) {
835 fprintf(stderr
,"Unable to open or read \"%s\" option file. status = %s\n", o
->options
, u_errorName(status
));
840 fprintf(stdout
, "# pkgDataFlags=\n");
841 for(int32_t i
=0;i
<PKGDATA_FLAGS_SIZE
;i
++) {
842 fprintf(stdout
, " [%d] %s: %s\n", i
, FLAG_NAMES
[i
], pkgDataFlags
[i
]);
844 fprintf(stdout
, "\n");
846 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
847 } while (status
== U_BUFFER_OVERFLOW_ERROR
);
855 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
856 * Depending on the configuration, the library name may either end with version number or shared object suffix.
858 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, UBool reverseExt
, UBool noVersion
) {
859 #if U_PLATFORM == U_PF_MINGW
860 /* MinGW does not need the library prefix when building in dll mode. */
861 if (IN_DLL_MODE(mode
)) {
862 sprintf(libFileNames
[LIB_FILE
], "%s", libName
);
864 sprintf(libFileNames
[LIB_FILE
], "%s%s",
865 pkgDataFlags
[LIBPREFIX
],
869 sprintf(libFileNames
[LIB_FILE
], "%s%s",
870 pkgDataFlags
[LIBPREFIX
],
875 fprintf(stdout
, "# libFileName[LIB_FILE] = %s\n", libFileNames
[LIB_FILE
]);
878 #if U_PLATFORM == U_PF_MINGW
879 sprintf(libFileNames
[LIB_FILE_MINGW
], "%s%s.lib", pkgDataFlags
[LIBPREFIX
], libName
);
880 #elif U_PLATFORM == U_PF_CYGWIN
881 sprintf(libFileNames
[LIB_FILE_CYGWIN
], "cyg%s.%s",
883 pkgDataFlags
[SO_EXT
]);
884 sprintf(libFileNames
[LIB_FILE_CYGWIN_VERSION
], "cyg%s%s.%s",
887 pkgDataFlags
[SO_EXT
]);
889 uprv_strcat(pkgDataFlags
[SO_EXT
], ".");
890 uprv_strcat(pkgDataFlags
[SO_EXT
], pkgDataFlags
[A_EXT
]);
891 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
892 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s.%s",
893 libFileNames
[LIB_FILE
],
894 pkgDataFlags
[SOBJ_EXT
]);
895 #elif U_PLATFROM == U_PF_OS390
897 sprintf(libFileNames
[LIB_FILE
], "%s",
899 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "\"%s\"",
900 libFileNames
[LIB_FILE
]);
902 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s.%s",
903 libFileNames
[LIB_FILE
],
904 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
905 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
906 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
909 if (noVersion
&& !reverseExt
) {
910 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s",
911 libFileNames
[LIB_FILE
],
912 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
913 pkgDataFlags
[SOBJ_EXT
]);
915 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s.%s",
916 libFileNames
[LIB_FILE
],
917 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
918 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
919 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
922 if (noVersion
&& !reverseExt
) {
923 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s",
924 libFileNames
[LIB_FILE
],
925 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
926 pkgDataFlags
[SO_EXT
]);
928 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s",
929 libFileNames
[LIB_FILE
],
930 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
931 pkgDataFlags
[SO_EXT
]);
933 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s.%s",
934 libFileNames
[LIB_FILE
],
935 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
936 reverseExt
? version_major
: pkgDataFlags
[SO_EXT
],
937 reverseExt
? pkgDataFlags
[SO_EXT
] : version_major
);
939 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s.%s",
940 libFileNames
[LIB_FILE
],
941 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
942 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
943 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
947 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames
[LIB_FILE_VERSION
]);
950 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
951 /* Cygwin and MinGW only deals with the version major number. */
952 uprv_strcpy(libFileNames
[LIB_FILE_VERSION_TMP
], libFileNames
[LIB_FILE_VERSION_MAJOR
]);
955 if(IN_STATIC_MODE(mode
)) {
956 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s.%s", libFileNames
[LIB_FILE
], pkgDataFlags
[A_EXT
]);
957 libFileNames
[LIB_FILE_VERSION_MAJOR
][0]=0;
959 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames
[LIB_FILE_VERSION
]);
964 /* Create the symbolic links for the final library file. */
965 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
) {
967 char cmd
[LARGE_BUFFER_MAX_SIZE
];
968 char name1
[SMALL_BUFFER_MAX_SIZE
]; /* symlink file name */
969 char name2
[SMALL_BUFFER_MAX_SIZE
]; /* file name to symlink */
971 #if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW
972 /* No symbolic link to make. */
973 if (uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) == 0 || uprv_strlen(libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0 ||
974 uprv_strcmp(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0) {
978 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
981 libFileNames
[LIB_FILE_VERSION_MAJOR
],
983 libFileNames
[LIB_FILE_VERSION
],
984 libFileNames
[LIB_FILE_VERSION_MAJOR
]);
985 result
= runCommand(cmd
);
987 fprintf(stderr
, "Error creating symbolic links. Failed command: %s\n", cmd
);
992 if (specialHandling
) {
993 #if U_PLATFORM == U_PF_CYGWIN
994 sprintf(name1
, "%s", libFileNames
[LIB_FILE_CYGWIN
]);
995 sprintf(name2
, "%s", libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
997 goto normal_symlink_mode
;
1000 #if U_PLATFORM != U_PF_CYGWIN
1001 normal_symlink_mode
:
1003 sprintf(name1
, "%s.%s", libFileNames
[LIB_FILE
], pkgDataFlags
[SO_EXT
]);
1004 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
1007 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
1015 result
= runCommand(cmd
);
1020 static int32_t pkg_installLibrary(const char *installDir
, const char *targetDir
, UBool noVersion
) {
1022 char cmd
[SMALL_BUFFER_MAX_SIZE
];
1024 sprintf(cmd
, "cd %s && %s %s %s%s%s",
1026 pkgDataFlags
[INSTALL_CMD
],
1027 libFileNames
[LIB_FILE_VERSION
],
1028 installDir
, PKGDATA_FILE_SEP_STRING
, libFileNames
[LIB_FILE_VERSION
]
1031 result
= runCommand(cmd
);
1034 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1039 sprintf(cmd
, "cd %s && %s %s.lib %s",
1041 pkgDataFlags
[INSTALL_CMD
],
1042 libFileNames
[LIB_FILE
],
1045 result
= runCommand(cmd
);
1048 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1051 #elif U_PLATFORM == U_PF_CYGWIN
1052 sprintf(cmd
, "cd %s && %s %s %s",
1054 pkgDataFlags
[INSTALL_CMD
],
1055 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1058 result
= runCommand(cmd
);
1061 fprintf(stderr
, "Error installing library. Failed command: %s\n", cmd
);
1069 return pkg_createSymLinks(installDir
, TRUE
);
1073 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
) {
1075 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1077 if (!T_FileStream_file_exists(installDir
)) {
1078 UErrorCode status
= U_ZERO_ERROR
;
1080 uprv_mkdir(installDir
, &status
);
1081 if (U_FAILURE(status
)) {
1082 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1086 #ifndef U_WINDOWS_WITH_MSVC
1087 sprintf(cmd
, "%s %s %s", pkgDataFlags
[INSTALL_CMD
], fileName
, installDir
);
1089 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, fileName
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1092 result
= runCommand(cmd
);
1094 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1100 #ifdef U_WINDOWS_MSVC
1101 /* Copy commands for installing the raw data files on Windows. */
1102 #define WIN_INSTALL_CMD "xcopy"
1103 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
1105 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
) {
1107 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1109 if (!T_FileStream_file_exists(installDir
)) {
1110 UErrorCode status
= U_ZERO_ERROR
;
1112 uprv_mkdir(installDir
, &status
);
1113 if (U_FAILURE(status
)) {
1114 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1118 #ifndef U_WINDOWS_WITH_MSVC
1119 char buffer
[SMALL_BUFFER_MAX_SIZE
] = "";
1120 int32_t bufferLength
= 0;
1122 FileStream
*f
= T_FileStream_open(fileListName
, "r");
1125 if (T_FileStream_readLine(f
, buffer
, SMALL_BUFFER_MAX_SIZE
) != NULL
) {
1126 bufferLength
= uprv_strlen(buffer
);
1127 /* Remove new line character. */
1128 if (bufferLength
> 0) {
1129 buffer
[bufferLength
-1] = 0;
1132 sprintf(cmd
, "%s %s%s%s %s%s%s",
1133 pkgDataFlags
[INSTALL_CMD
],
1134 srcDir
, PKGDATA_FILE_SEP_STRING
, buffer
,
1135 installDir
, PKGDATA_FILE_SEP_STRING
, buffer
);
1137 result
= runCommand(cmd
);
1139 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1143 if (!T_FileStream_eof(f
)) {
1144 fprintf(stderr
, "Failed to read line from file: %s\n", fileListName
);
1150 T_FileStream_close(f
);
1153 fprintf(stderr
, "Unable to open list file: %s\n", fileListName
);
1156 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, srcDir
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1157 result
= runCommand(cmd
);
1159 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1166 /* Archiving of the library file may be needed depending on the platform and options given.
1167 * If archiving is not needed, copy over the library file name.
1169 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
) {
1171 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1173 /* If the shared object suffix and the final object suffix is different and the final object suffix and the
1174 * archive file suffix is the same, then the final library needs to be archived.
1176 if (uprv_strcmp(pkgDataFlags
[SOBJ_EXT
], pkgDataFlags
[SO_EXT
]) != 0 && uprv_strcmp(pkgDataFlags
[A_EXT
], pkgDataFlags
[SO_EXT
]) == 0) {
1177 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s.%s",
1178 libFileNames
[LIB_FILE
],
1179 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
1180 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
1181 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
1183 sprintf(cmd
, "%s %s %s%s %s%s",
1185 pkgDataFlags
[ARFLAGS
],
1187 libFileNames
[LIB_FILE_VERSION
],
1189 libFileNames
[LIB_FILE_VERSION_TMP
]);
1191 result
= runCommand(cmd
);
1193 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1197 sprintf(cmd
, "%s %s%s",
1198 pkgDataFlags
[RANLIB
],
1200 libFileNames
[LIB_FILE_VERSION
]);
1202 result
= runCommand(cmd
);
1204 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1208 /* Remove unneeded library file. */
1209 sprintf(cmd
, "%s %s%s",
1212 libFileNames
[LIB_FILE_VERSION_TMP
]);
1214 result
= runCommand(cmd
);
1216 fprintf(stderr
, "Error creating archive library. Failed command: %s\n", cmd
);
1221 uprv_strcpy(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_TMP
]);
1228 * Using the compiler information from the configuration file set by -O option, generate the library file.
1229 * command may be given to allow for a larger buffer for cmd.
1231 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
) {
1234 UBool freeCmd
= FALSE
;
1237 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
1238 * containing many object files and so the calling function should supply a command buffer that is large
1239 * enough to handle this. Otherwise, use the default size.
1241 if (command
!= NULL
) {
1245 if (IN_STATIC_MODE(mode
)) {
1247 length
= uprv_strlen(pkgDataFlags
[AR
]) + uprv_strlen(pkgDataFlags
[ARFLAGS
]) + uprv_strlen(targetDir
) +
1248 uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) + uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[RANLIB
]) + BUFFER_PADDING_SIZE
;
1249 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1250 fprintf(stderr
, "Unable to allocate memory for command.\n");
1255 sprintf(cmd
, "%s %s %s%s %s",
1257 pkgDataFlags
[ARFLAGS
],
1259 libFileNames
[LIB_FILE_VERSION
],
1262 result
= runCommand(cmd
);
1264 sprintf(cmd
, "%s %s%s",
1265 pkgDataFlags
[RANLIB
],
1267 libFileNames
[LIB_FILE_VERSION
]);
1269 result
= runCommand(cmd
);
1271 } else /* if (IN_DLL_MODE(mode)) */ {
1273 length
= uprv_strlen(pkgDataFlags
[GENLIB
]) + uprv_strlen(pkgDataFlags
[LDICUDTFLAGS
]) +
1274 ((uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_VERSION_TMP
])) * 2) +
1275 uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[LD_SONAME
]) +
1276 uprv_strlen(pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
]) +
1277 uprv_strlen(pkgDataFlags
[RPATH_FLAGS
]) + uprv_strlen(pkgDataFlags
[BIR_FLAGS
]) + BUFFER_PADDING_SIZE
;
1278 #if U_PLATFORM == U_PF_CYGWIN
1279 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
1280 #elif U_PLATFORM == U_PF_MINGW
1281 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_MINGW
]);
1283 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1284 fprintf(stderr
, "Unable to allocate memory for command.\n");
1289 #if U_PLATFORM == U_PF_MINGW
1290 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1291 pkgDataFlags
[GENLIB
],
1293 libFileNames
[LIB_FILE_MINGW
],
1294 pkgDataFlags
[LDICUDTFLAGS
],
1296 libFileNames
[LIB_FILE_VERSION_TMP
],
1297 #elif U_PLATFORM == U_PF_CYGWIN
1298 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1299 pkgDataFlags
[GENLIB
],
1301 libFileNames
[LIB_FILE_VERSION_TMP
],
1302 pkgDataFlags
[LDICUDTFLAGS
],
1304 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1305 #elif U_PLATFORM == U_PF_AIX
1306 sprintf(cmd
, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
1309 libFileNames
[LIB_FILE_VERSION_TMP
],
1310 pkgDataFlags
[GENLIB
],
1311 pkgDataFlags
[LDICUDTFLAGS
],
1313 libFileNames
[LIB_FILE_VERSION_TMP
],
1315 sprintf(cmd
, "%s %s -o %s%s %s %s%s %s %s",
1316 pkgDataFlags
[GENLIB
],
1317 pkgDataFlags
[LDICUDTFLAGS
],
1319 libFileNames
[LIB_FILE_VERSION_TMP
],
1322 pkgDataFlags
[LD_SONAME
],
1323 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1324 pkgDataFlags
[RPATH_FLAGS
],
1325 pkgDataFlags
[BIR_FLAGS
]);
1327 /* Generate the library file. */
1328 result
= runCommand(cmd
);
1332 fprintf(stderr
, "Error generating library file. Failed command: %s\n", cmd
);
1342 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
) {
1343 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1349 /* Remove the ending .s and replace it with .o for the new object file. */
1350 uprv_strcpy(tempObjectFile
, gencFilePath
);
1351 tempObjectFile
[uprv_strlen(tempObjectFile
)-1] = 'o';
1353 length
= uprv_strlen(pkgDataFlags
[COMPILER
]) + uprv_strlen(pkgDataFlags
[LIBFLAGS
])
1354 + uprv_strlen(tempObjectFile
) + uprv_strlen(gencFilePath
) + BUFFER_PADDING_SIZE
;
1356 cmd
= (char *)uprv_malloc(sizeof(char) * length
);
1361 /* Generate the object file. */
1362 sprintf(cmd
, "%s %s -o %s %s",
1363 pkgDataFlags
[COMPILER
],
1364 pkgDataFlags
[LIBFLAGS
],
1368 result
= runCommand(cmd
);
1371 fprintf(stderr
, "Error creating with assembly code. Failed command: %s\n", cmd
);
1375 return pkg_generateLibraryFile(targetDir
, mode
, tempObjectFile
);
1378 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
1380 * Generation of the data library without assembly code needs to compile each data file
1381 * individually and then link it all together.
1382 * Note: Any update to the directory structure of the data needs to be reflected here.
1391 DATA_PREFIX_TRANSLIT
,
1396 const static char DATA_PREFIX
[DATA_PREFIX_LENGTH
][10] = {
1407 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
) {
1409 CharList
*list
= o
->filePaths
;
1410 CharList
*listNames
= o
->files
;
1411 int32_t listSize
= pkg_countCharList(list
);
1414 char gencmnFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1415 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1416 #ifdef USE_SINGLE_CCODE_FILE
1417 char icudtAll
[SMALL_BUFFER_MAX_SIZE
] = "";
1418 FileStream
*icudtAllFile
= NULL
;
1420 sprintf(icudtAll
, "%s%s%sall.c",
1422 PKGDATA_FILE_SEP_STRING
,
1423 libFileNames
[LIB_FILE
]);
1424 /* Remove previous icudtall.c file. */
1425 if (T_FileStream_file_exists(icudtAll
) && (result
= remove(icudtAll
)) != 0) {
1426 fprintf(stderr
, "Unable to remove old icudtall file: %s\n", icudtAll
);
1430 if((icudtAllFile
= T_FileStream_open(icudtAll
, "w"))==NULL
) {
1431 fprintf(stderr
, "Unable to write to icudtall file: %s\n", icudtAll
);
1436 if (list
== NULL
|| listNames
== NULL
) {
1437 /* list and listNames should never be NULL since we are looping through the CharList with
1443 if ((cmd
= (char *)uprv_malloc((listSize
+ 2) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1444 fprintf(stderr
, "Unable to allocate memory for cmd.\n");
1446 } else if ((buffer
= (char *)uprv_malloc((listSize
+ 1) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1447 fprintf(stderr
, "Unable to allocate memory for buffer.\n");
1452 for (int32_t i
= 0; i
< (listSize
+ 1); i
++) {
1457 /* The first iteration calls the gencmn function and initailizes the buffer. */
1458 createCommonDataFile(o
->tmpDir
, o
->shortName
, o
->entryName
, NULL
, o
->srcDir
, o
->comment
, o
->fileListFiles
->str
, 0, TRUE
, o
->verbose
, gencmnFile
);
1460 #ifdef USE_SINGLE_CCODE_FILE
1461 uprv_strcpy(tempObjectFile
, gencmnFile
);
1462 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1464 sprintf(cmd
, "%s %s -o %s %s",
1465 pkgDataFlags
[COMPILER
],
1466 pkgDataFlags
[LIBFLAGS
],
1470 result
= runCommand(cmd
);
1475 sprintf(buffer
, "%s",tempObjectFile
);
1478 char newName
[SMALL_BUFFER_MAX_SIZE
];
1479 char dataName
[SMALL_BUFFER_MAX_SIZE
];
1480 char dataDirName
[SMALL_BUFFER_MAX_SIZE
];
1481 const char *pSubstring
;
1483 name
= listNames
->str
;
1485 newName
[0] = dataName
[0] = 0;
1486 for (int32_t n
= 0; n
< DATA_PREFIX_LENGTH
; n
++) {
1488 sprintf(dataDirName
, "%s%s", DATA_PREFIX
[n
], PKGDATA_FILE_SEP_STRING
);
1489 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
1490 pSubstring
= uprv_strstr(name
, dataDirName
);
1491 if (pSubstring
!= NULL
) {
1492 char newNameTmp
[SMALL_BUFFER_MAX_SIZE
] = "";
1493 const char *p
= name
+ uprv_strlen(dataDirName
);
1494 for (int32_t i
= 0;;i
++) {
1496 newNameTmp
[i
] = '_';
1499 newNameTmp
[i
] = p
[i
];
1504 sprintf(newName
, "%s_%s",
1507 sprintf(dataName
, "%s_%s",
1511 if (newName
[0] != 0) {
1517 printf("# Generating %s \n", gencmnFile
);
1520 writeCCode(file
, o
->tmpDir
, dataName
[0] != 0 ? dataName
: o
->shortName
, newName
[0] != 0 ? newName
: NULL
, gencmnFile
);
1522 #ifdef USE_SINGLE_CCODE_FILE
1523 sprintf(cmd
, "#include \"%s\"\n", gencmnFile
);
1524 T_FileStream_writeLine(icudtAllFile
, cmd
);
1525 /* don't delete the file */
1529 #ifndef USE_SINGLE_CCODE_FILE
1530 uprv_strcpy(tempObjectFile
, gencmnFile
);
1531 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1533 sprintf(cmd
, "%s %s -o %s %s",
1534 pkgDataFlags
[COMPILER
],
1535 pkgDataFlags
[LIBFLAGS
],
1538 result
= runCommand(cmd
);
1540 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1544 uprv_strcat(buffer
, " ");
1545 uprv_strcat(buffer
, tempObjectFile
);
1551 listNames
= listNames
->next
;
1555 #ifdef USE_SINGLE_CCODE_FILE
1556 T_FileStream_close(icudtAllFile
);
1557 uprv_strcpy(tempObjectFile
, icudtAll
);
1558 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1560 sprintf(cmd
, "%s %s -I. -o %s %s",
1561 pkgDataFlags
[COMPILER
],
1562 pkgDataFlags
[LIBFLAGS
],
1566 result
= runCommand(cmd
);
1568 uprv_strcat(buffer
, " ");
1569 uprv_strcat(buffer
, tempObjectFile
);
1571 fprintf(stderr
, "Error creating library without assembly code. Failed command: %s\n", cmd
);
1576 /* Generate the library file. */
1577 #if U_PLATFORM == U_PF_OS390
1578 if (o
->pdsbuild
&& IN_DLL_MODE(mode
)) {
1579 result
= pkg_generateLibraryFile("",mode
, buffer
, cmd
);
1581 result
= pkg_generateLibraryFile(targetDir
,mode
, buffer
, cmd
);
1584 result
= pkg_generateLibraryFile(targetDir
,mode
, buffer
, cmd
);
1595 #ifdef WINDOWS_WITH_MSVC
1596 #define LINK_CMD "link.exe /nologo /release /out:"
1597 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:"
1598 #define LIB_CMD "LIB.exe /nologo /out:"
1599 #define LIB_FILE "icudt.lib"
1600 #define LIB_EXT UDATA_LIB_SUFFIX
1601 #define DLL_EXT UDATA_SO_SUFFIX
1603 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
) {
1605 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1606 if (IN_STATIC_MODE(mode
)) {
1607 char staticLibFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1610 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1612 PKGDATA_FILE_SEP_STRING
,
1613 pkgDataFlags
[LIBPREFIX
],
1617 sprintf(staticLibFilePath
, "%s%s%s%s%s",
1619 PKGDATA_FILE_SEP_STRING
,
1620 (strstr(o
->libName
, "icudt") ? "s" : ""),
1625 sprintf(cmd
, "%s\"%s\" \"%s\"",
1629 } else if (IN_DLL_MODE(mode
)) {
1630 char dllFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1631 char libFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1632 char resFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1633 char tmpResFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1636 uprv_strcpy(dllFilePath
, o
->targetDir
);
1638 uprv_strcpy(dllFilePath
, o
->srcDir
);
1640 uprv_strcat(dllFilePath
, PKGDATA_FILE_SEP_STRING
);
1641 uprv_strcpy(libFilePath
, dllFilePath
);
1644 uprv_strcat(libFilePath
, o
->libName
);
1645 uprv_strcat(libFilePath
, ".lib");
1647 uprv_strcat(dllFilePath
, o
->libName
);
1648 uprv_strcat(dllFilePath
, o
->version
);
1650 if (strstr(o
->libName
, "icudt")) {
1651 uprv_strcat(libFilePath
, LIB_FILE
);
1653 uprv_strcat(libFilePath
, o
->libName
);
1654 uprv_strcat(libFilePath
, ".lib");
1656 uprv_strcat(dllFilePath
, o
->entryName
);
1658 uprv_strcat(dllFilePath
, DLL_EXT
);
1660 uprv_strcpy(tmpResFilePath
, o
->tmpDir
);
1661 uprv_strcat(tmpResFilePath
, PKGDATA_FILE_SEP_STRING
);
1662 uprv_strcat(tmpResFilePath
, ICUDATA_RES_FILE
);
1664 if (T_FileStream_file_exists(tmpResFilePath
)) {
1665 sprintf(resFilePath
, "\"%s\"", tmpResFilePath
);
1668 /* Check if dll file and lib file exists and that it is not newer than genc file. */
1669 if (!o
->rebuild
&& (T_FileStream_file_exists(dllFilePath
) && isFileModTimeLater(dllFilePath
, gencFilePath
)) &&
1670 (T_FileStream_file_exists(libFilePath
) && isFileModTimeLater(libFilePath
, gencFilePath
))) {
1672 printf("# Not rebuilding %s - up to date.\n", gencFilePath
);
1677 sprintf(cmd
, "%s\"%s\" %s\"%s\" \"%s\" %s",
1687 result
= runCommand(cmd
, TRUE
);
1689 fprintf(stderr
, "Error creating Windows DLL library. Failed command: %s\n", cmd
);
1696 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
) {
1697 #if U_PLATFORM == U_PF_AIX
1698 /* AIX needs a map file. */
1701 char tmpbuffer
[SMALL_BUFFER_MAX_SIZE
];
1702 const char MAP_FILE_EXT
[] = ".map";
1703 FileStream
*f
= NULL
;
1704 char mapFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1707 const char rm_cmd
[] = "rm -f all ;";
1709 flag
= pkgDataFlags
[GENLIB
];
1711 /* This portion of the code removes 'rm -f all' in the GENLIB.
1712 * Only occurs in AIX.
1714 if (uprv_strstr(flag
, rm_cmd
) != NULL
) {
1715 char *tmpGenlibFlagBuffer
= NULL
;
1718 length
= uprv_strlen(flag
) + 1;
1719 tmpGenlibFlagBuffer
= (char *)uprv_malloc(length
);
1720 if (tmpGenlibFlagBuffer
== NULL
) {
1721 /* Memory allocation error */
1722 fprintf(stderr
,"Unable to allocate buffer of size: %d.\n", length
);
1726 uprv_strcpy(tmpGenlibFlagBuffer
, flag
);
1728 offset
= uprv_strlen(rm_cmd
);
1730 for (i
= 0; i
< (length
- offset
); i
++) {
1731 flag
[i
] = tmpGenlibFlagBuffer
[offset
+ i
];
1734 /* Zero terminate the string */
1737 uprv_free(tmpGenlibFlagBuffer
);
1740 flag
= pkgDataFlags
[BIR_FLAGS
];
1741 length
= uprv_strlen(pkgDataFlags
[BIR_FLAGS
]);
1743 for (int32_t i
= 0; i
< length
; i
++) {
1744 if (flag
[i
] == MAP_FILE_EXT
[count
]) {
1753 if (count
== uprv_strlen(MAP_FILE_EXT
)) {
1760 for (int32_t i
= 0;;i
++) {
1762 for (int32_t n
= 0;;n
++) {
1763 if (o
->shortName
[n
] == 0) {
1766 tmpbuffer
[index
++] = o
->shortName
[n
];
1770 tmpbuffer
[index
++] = flag
[i
];
1777 uprv_memset(flag
, 0, length
);
1778 uprv_strcpy(flag
, tmpbuffer
);
1780 uprv_strcpy(mapFile
, o
->shortName
);
1781 uprv_strcat(mapFile
, MAP_FILE_EXT
);
1783 f
= T_FileStream_open(mapFile
, "w");
1785 fprintf(stderr
,"Unable to create map file: %s.\n", mapFile
);
1788 sprintf(tmpbuffer
, "%s%s ", o
->entryName
, UDATA_CMN_INTERMEDIATE_SUFFIX
);
1790 T_FileStream_writeLine(f
, tmpbuffer
);
1792 T_FileStream_close(f
);
1795 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
1796 /* Cygwin needs to change flag options. */
1800 flag
= pkgDataFlags
[GENLIB
];
1801 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1803 int32_t position
= length
- 1;
1805 for(;position
>= 0;position
--) {
1806 if (flag
[position
] == '=') {
1812 uprv_memset(flag
+ position
, 0, length
- position
);
1813 #elif U_PLATFORM == U_PF_OS400
1814 /* OS/400 needs to fix the ld options (swap single quote with double quote) */
1818 flag
= pkgDataFlags
[GENLIB
];
1819 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1821 int32_t position
= length
- 1;
1823 for(int32_t i
= 0; i
< length
; i
++) {
1824 if (flag
[i
] == '\'') {
1829 // Don't really need a return value, just need to stop compiler warnings about
1830 // the unused parameter 'o' on platforms where it is not otherwise used.
1834 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
)
1836 CharList
*l
, *tail
= NULL
, *tail2
= NULL
;
1839 char *linePtr
, *lineNext
;
1840 const uint32_t lineMax
= 16300;
1842 int32_t tmpLength
= 0;
1844 int32_t ln
=0; /* line number */
1846 for(l
= o
->fileListFiles
; l
; l
= l
->next
) {
1848 fprintf(stdout
, "# pkgdata: Reading %s..\n", l
->str
);
1851 in
= T_FileStream_open(l
->str
, "r"); /* open files list */
1854 fprintf(stderr
, "Error opening <%s>.\n", l
->str
);
1855 *status
= U_FILE_ACCESS_ERROR
;
1859 while(T_FileStream_readLine(in
, line
, sizeof(line
))!=NULL
) { /* for each line */
1861 if(uprv_strlen(line
)>lineMax
) {
1862 fprintf(stderr
, "%s:%d - line too long (over %d chars)\n", l
->str
, (int)ln
, (int)lineMax
);
1865 /* remove spaces at the beginning */
1867 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */
1868 #if U_PLATFORM != U_PF_OS390
1869 while(isspace(*linePtr
)) {
1874 /* remove trailing newline characters */
1876 if(*s
=='\r' || *s
=='\n') {
1882 if((*linePtr
== 0) || (*linePtr
== '#')) {
1883 continue; /* comment or empty line */
1886 /* Now, process the line */
1889 while(linePtr
&& *linePtr
) { /* process space-separated items */
1890 while(*linePtr
== ' ') {
1893 /* Find the next quote */
1894 if(linePtr
[0] == '"')
1896 lineNext
= uprv_strchr(linePtr
+1, '"');
1897 if(lineNext
== NULL
) {
1898 fprintf(stderr
, "%s:%d - missing trailing double quote (\")\n",
1904 if(*lineNext
!= ' ') {
1905 fprintf(stderr
, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
1906 l
->str
, (int)ln
, (int)(lineNext
-line
), (*lineNext
)?*lineNext
:'0');
1914 lineNext
= uprv_strchr(linePtr
, ' ');
1916 *lineNext
= 0; /* terminate at space */
1922 s
= (char*)getLongPathname(linePtr
);
1924 /* normal mode.. o->files is just the bare list without package names */
1925 o
->files
= pkg_appendToList(o
->files
, &tail
, uprv_strdup(linePtr
));
1926 if(uprv_pathIsAbsolute(s
) || s
[0] == '.') {
1927 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
);
1928 exit(U_ILLEGAL_ARGUMENT_ERROR
);
1930 tmpLength
= uprv_strlen(o
->srcDir
) +
1931 uprv_strlen(s
) + 5; /* 5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
1932 if((tmp
= (char *)uprv_malloc(tmpLength
)) == NULL
) {
1933 fprintf(stderr
, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength
);
1934 exit(U_MEMORY_ALLOCATION_ERROR
);
1936 uprv_strcpy(tmp
, o
->srcDir
);
1937 uprv_strcat(tmp
, o
->srcDir
[uprv_strlen(o
->srcDir
)-1] == U_FILE_SEP_CHAR
? "" : PKGDATA_FILE_SEP_STRING
);
1938 uprv_strcat(tmp
, s
);
1939 o
->filePaths
= pkg_appendToList(o
->filePaths
, &tail2
, tmp
);
1941 } /* for each entry on line */
1942 } /* for each line */
1943 T_FileStream_close(in
);
1944 } /* for each file list file */
1947 /* Try calling icu-config directly to get the option file. */
1948 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
) {
1952 static char buf
[512] = "";
1954 UErrorCode status
= U_ZERO_ERROR
;
1955 const char cmd
[] = "icu-config --incpkgdatafile";
1957 /* #1 try the same path where pkgdata was called from. */
1958 findDirname(progname
, cmdBuf
, 1024, &status
);
1959 if(U_SUCCESS(status
)) {
1960 if (cmdBuf
[0] != 0) {
1961 uprv_strncat(cmdBuf
, U_FILE_SEP_STRING
, 1024);
1963 uprv_strncat(cmdBuf
, cmd
, 1024);
1966 fprintf(stdout
, "# Calling icu-config: %s\n", cmdBuf
);
1968 p
= popen(cmdBuf
, "r");
1971 if(p
== NULL
|| (n
= fread(buf
, 1, 511, p
)) <= 0) {
1973 fprintf(stdout
, "# Calling icu-config: %s\n", cmd
);
1977 p
= popen(cmd
, "r");
1978 if(p
== NULL
|| (n
= fread(buf
, 1, 511, p
)) <= 0) {
1979 fprintf(stderr
, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname
);
1986 for (int32_t length
= strlen(buf
) - 1; length
>= 0; length
--) {
1987 if (buf
[length
] == '\n' || buf
[length
] == ' ') {
1994 if(buf
[strlen(buf
)-1]=='\n')
1996 buf
[strlen(buf
)-1]=0;
2001 fprintf(stderr
, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname
);
2006 fprintf(stdout
, "# icu-config said: %s\n", buf
);
2009 option
->value
= buf
;
2010 option
->doesOccur
= TRUE
;