1 /******************************************************************************
2 * Copyright (C) 2000-2011, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *******************************************************************************
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.)
18 * We define _XOPEN_SOURCE so that we can get popen and pclose.
20 #if !defined(_XOPEN_SOURCE)
21 #if __STDC_VERSION__ >= 199901L
22 /* It is invalid to compile an XPG3, XPG4, XPG4v2 or XPG5 application using c99 on Solaris */
23 #define _XOPEN_SOURCE 600
25 #define _XOPEN_SOURCE 4
30 #include "unicode/utypes.h"
33 #if defined(U_CYGWIN) && defined(__STRICT_ANSI__)
34 /* popen/pclose aren't defined in strict ANSI on Cygwin */
35 #undef __STRICT_ANSI__
39 #include "unicode/putil.h"
44 #include "unicode/uclean.h"
51 #include "pkg_gencmn.h"
52 #include "flagparser.h"
53 #include "filetools.h"
68 #define WINDOWS_WITH_GNUC
70 #define WINDOWS_WITH_MSVC
73 #if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX)
74 #define BUILD_DATA_WITHOUT_ASSEMBLY
76 #if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
77 #define CAN_WRITE_OBJ_CODE
79 #if defined(U_CYGWIN) || defined(CYGWINMSVC)
84 * When building the data library without assembly,
85 * some platforms use a single c code file for all of
86 * the data to generate the final data library. This can
87 * increase the performance of the pkdata tool.
90 #define USE_SINGLE_CCODE_FILE
93 /* Need to fix the file seperator character when using MinGW. */
94 #if defined(WINDOWS_WITH_GNUC) || defined(USING_CYGWIN)
95 #define PKGDATA_FILE_SEP_STRING "/"
97 #define PKGDATA_FILE_SEP_STRING U_FILE_SEP_STRING
100 #define LARGE_BUFFER_MAX_SIZE 2048
101 #define SMALL_BUFFER_MAX_SIZE 512
102 #define BUFFER_PADDING_SIZE 20
104 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
);
106 static int32_t pkg_executeOptions(UPKGOptions
*o
);
108 #ifdef WINDOWS_WITH_MSVC
109 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
);
111 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
=FALSE
);
112 static int32_t pkg_installLibrary(const char *installDir
, const char *dir
);
113 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
);
114 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
);
116 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
117 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
);
120 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
);
121 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
= NULL
);
122 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
);
123 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, const UBool reverseExt
);
124 static int32_t initializePkgDataFlags(UPKGOptions
*o
);
126 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
);
127 static int runCommand(const char* command
, UBool specialHandling
=FALSE
);
150 /* This sets the modes that are available */
152 const char *name
, *alt_name
;
155 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
157 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
158 { "common", "archive", "Generates just the common file, <package>.dat"},
159 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
161 #ifdef UDATA_SO_SUFFIX
162 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX
},
164 { "common", "archive", "Generates one common data file, <package>.dat" },
165 { "static", "static", "Generates one statically linked library, " LIB_PREFIX
"<package>" UDATA_LIB_SUFFIX
}
169 static UOption options
[]={
170 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG
),
171 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG
), /* on Win32 it is release or debug */
172 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG
),
173 /*03*/ UOPTION_HELP_H
, /* -h */
174 /*04*/ UOPTION_HELP_QUESTION_MARK
, /* -? */
175 /*05*/ UOPTION_VERBOSE
, /* -v */
176 /*06*/ UOPTION_COPYRIGHT
, /* -c */
177 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG
),
178 /*08*/ UOPTION_DESTDIR
, /* -d */
179 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG
),
180 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG
),
181 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG
),
182 /*14*/ UOPTION_SOURCEDIR
,
183 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG
),
184 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG
),
185 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG
),
186 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG
),
187 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG
)
191 GENCCODE_ASSEMBLY_TYPE
,
210 static char **pkgDataFlags
= NULL
;
214 LIB_FILE_VERSION_MAJOR
,
216 LIB_FILE_VERSION_TMP
,
219 LIB_FILE_CYGWIN_VERSION
,
223 static char libFileNames
[LIB_FILENAMES_SIZE
][256];
225 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
);
227 const char options_help
[][320]={
229 #ifdef U_MAKE_IS_NMAKE
230 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
232 "Specify options for the builder.",
234 "Specify the mode of building (see below; default: common)",
237 "Make the output verbose",
238 "Use the standard ICU copyright",
239 "Use a custom comment (instead of the copyright)",
240 "Specify the destination directory for files",
241 "Force rebuilding of all data",
242 "Specify temporary dir (default: output dir)",
243 "Install the data (specify target)",
244 "Specify a custom source directory",
245 "Specify a custom entrypoint name (default: short name)",
246 "Specify a version when packaging in dll or static mode",
247 "Add package to all file names if not present",
248 "Library name to build (if different than package name)",
249 "Quite mode. (e.g. Do not output a readme file for static libraries)"
252 const char *progname
= "PKGDATA";
255 main(int argc
, char* argv
[]) {
257 /* FileStream *out; */
260 UBool needsHelp
= FALSE
;
261 UErrorCode status
= U_ZERO_ERROR
;
262 /* char tmp[1024]; */
266 U_MAIN_INIT_ARGS(argc
, argv
);
270 options
[MODE
].value
= "common";
272 /* read command line options */
273 argc
=u_parseArgs(argc
, argv
, sizeof(options
)/sizeof(options
[0]), options
);
275 /* error handling, printing usage message */
276 /* I've decided to simply print an error and quit. This tool has too
277 many options to just display them all of the time. */
279 if(options
[HELP
].doesOccur
|| options
[HELP_QUESTION_MARK
].doesOccur
) {
283 if(!needsHelp
&& argc
<0) {
285 "%s: error in command line argument \"%s\"\n",
288 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
293 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
294 if(!options
[BLDOPT
].doesOccur
&& uprv_strcmp(options
[MODE
].value
, "common") != 0) {
295 if (pkg_getOptionsFromICUConfig(options
[VERBOSE
].doesOccur
, &options
[BLDOPT
]) != 0) {
296 fprintf(stderr
, " required parameter is missing: -O is required for static and shared builds.\n");
297 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
302 if(options
[BLDOPT
].doesOccur
) {
303 fprintf(stdout
, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
307 if(!options
[NAME
].doesOccur
) /* -O we already have - don't report it. */
309 fprintf(stderr
, " required parameter -p is missing \n");
310 fprintf(stderr
, "Run '%s --help' for help.\n", progname
);
316 "No input files specified.\n"
317 "Run '%s --help' for help.\n", progname
);
320 } /* end !needsHelp */
322 if(argc
<0 || needsHelp
) {
324 "usage: %s [-options] [-] [packageFile] \n"
325 "\tProduce packaged ICU data from the given list(s) of files.\n"
326 "\t'-' by itself means to read from stdin.\n"
327 "\tpackageFile is a text file containing the list of files to package.\n",
330 fprintf(stderr
, "\n options:\n");
331 for(i
=0;i
<(sizeof(options
)/sizeof(options
[0]));i
++) {
332 fprintf(stderr
, "%-5s -%c %s%-10s %s\n",
334 options
[i
].shortName
,
335 options
[i
].longName
? "or --" : " ",
336 options
[i
].longName
? options
[i
].longName
: "",
340 fprintf(stderr
, "modes: (-m option)\n");
341 for(i
=0;i
<(sizeof(modes
)/sizeof(modes
[0]));i
++) {
342 fprintf(stderr
, " %-9s ", modes
[i
].name
);
343 if (modes
[i
].alt_name
) {
344 fprintf(stderr
, "/ %-9s", modes
[i
].alt_name
);
346 fprintf(stderr
, " ");
348 fprintf(stderr
, " %s\n", modes
[i
].desc
);
353 /* OK, fill in the options struct */
354 uprv_memset(&o
, 0, sizeof(o
));
356 o
.mode
= options
[MODE
].value
;
357 o
.version
= options
[REVISION
].doesOccur
? options
[REVISION
].value
: 0;
359 o
.shortName
= options
[NAME
].value
;
361 int32_t len
= (int32_t)uprv_strlen(o
.shortName
);
365 cp
= csname
= (char *) uprv_malloc((len
+ 1 + 1) * sizeof(*o
.cShortName
));
366 if (*(sp
= o
.shortName
)) {
367 *cp
++ = isalpha(*sp
) ? * sp
: '_';
368 for (++sp
; *sp
; ++sp
) {
369 *cp
++ = isalnum(*sp
) ? *sp
: '_';
374 o
.cShortName
= csname
;
377 if(options
[LIBNAME
].doesOccur
) { /* get libname from shortname, or explicit -L parameter */
378 o
.libName
= options
[LIBNAME
].value
;
380 o
.libName
= o
.shortName
;
383 if(options
[QUIET
].doesOccur
) {
389 o
.verbose
= options
[VERBOSE
].doesOccur
;
392 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
393 if (options
[BLDOPT
].doesOccur
) {
394 o
.options
= options
[BLDOPT
].value
;
399 if(options
[COPYRIGHT
].doesOccur
) {
400 o
.comment
= U_COPYRIGHT_STRING
;
401 } else if (options
[COMMENT
].doesOccur
) {
402 o
.comment
= options
[COMMENT
].value
;
405 if( options
[DESTDIR
].doesOccur
) {
406 o
.targetDir
= options
[DESTDIR
].value
;
408 o
.targetDir
= "."; /* cwd */
411 o
.rebuild
= options
[REBUILD
].doesOccur
;
413 if( options
[TEMPDIR
].doesOccur
) {
414 o
.tmpDir
= options
[TEMPDIR
].value
;
416 o
.tmpDir
= o
.targetDir
;
419 if( options
[INSTALL
].doesOccur
) {
420 o
.install
= options
[INSTALL
].value
;
425 if( options
[SOURCEDIR
].doesOccur
) {
426 o
.srcDir
= options
[SOURCEDIR
].value
;
431 if( options
[ENTRYPOINT
].doesOccur
) {
432 o
.entryName
= options
[ENTRYPOINT
].value
;
434 o
.entryName
= o
.cShortName
;
437 /* OK options are set up. Now the file lists. */
439 for( n
=1; n
<argc
; n
++) {
440 o
.fileListFiles
= pkg_appendToList(o
.fileListFiles
, &tail
, uprv_strdup(argv
[n
]));
444 loadLists(&o
, &status
);
445 if( U_FAILURE(status
) ) {
446 fprintf(stderr
, "error loading input file lists: %s\n", u_errorName(status
));
450 result
= pkg_executeOptions(&o
);
452 if (pkgDataFlags
!= NULL
) {
453 for (n
= 0; n
< PKGDATA_FLAGS_SIZE
; n
++) {
454 if (pkgDataFlags
[n
] != NULL
) {
455 uprv_free(pkgDataFlags
[n
]);
458 uprv_free(pkgDataFlags
);
461 if (o
.cShortName
!= NULL
) {
462 uprv_free((char *)o
.cShortName
);
464 if (o
.fileListFiles
!= NULL
) {
465 pkg_deleteList(o
.fileListFiles
);
467 if (o
.filePaths
!= NULL
) {
468 pkg_deleteList(o
.filePaths
);
470 if (o
.files
!= NULL
) {
471 pkg_deleteList(o
.files
);
477 static int runCommand(const char* command
, UBool specialHandling
) {
479 char cmdBuffer
[SMALL_BUFFER_MAX_SIZE
];
480 int32_t len
= strlen(command
);
486 if (!specialHandling
) {
487 #if defined(USING_CYGWIN) || defined(OS400)
488 if ((len
+ BUFFER_PADDING_SIZE
) >= SMALL_BUFFER_MAX_SIZE
) {
489 cmd
= (char *)uprv_malloc(len
+ BUFFER_PADDING_SIZE
);
494 sprintf(cmd
, "bash -c \"%s\"", command
);
497 sprintf(cmd
, "QSH CMD('%s')", command
);
500 goto normal_command_mode
;
504 cmd
= (char *)command
;
507 printf("pkgdata: %s\n", cmd
);
508 int result
= system(cmd
);
510 printf("-- return status = %d\n", result
);
513 if (cmd
!= cmdBuffer
&& cmd
!= command
) {
520 #define LN_CMD "ln -s"
521 #define RM_CMD "rm -f"
523 #define MODE_COMMON 'c'
524 #define MODE_STATIC 's'
526 #define MODE_FILES '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 (mode
== MODE_FILES
) {
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 (mode == MODE_COMMON || mode == MODE_STATIC || mode == MODE_DLL) */ {
556 uprv_strcpy(targetDir
, o
->targetDir
);
557 uprv_strcat(targetDir
, PKGDATA_FILE_SEP_STRING
);
559 uprv_strcpy(tmpDir
, o
->tmpDir
);
560 uprv_strcat(tmpDir
, PKGDATA_FILE_SEP_STRING
);
562 uprv_strcpy(datFileNamePath
, tmpDir
);
564 uprv_strcpy(datFileName
, o
->shortName
);
565 uprv_strcat(datFileName
, UDATA_CMN_SUFFIX
);
567 uprv_strcat(datFileNamePath
, datFileName
);
570 fprintf(stdout
, "# Writing package file %s ..\n", datFileNamePath
);
572 result
= writePackageDatFile(datFileNamePath
, o
->comment
, o
->srcDir
, o
->fileListFiles
->str
, NULL
, U_CHARSET_FAMILY
? 'e' : U_IS_BIG_ENDIAN
? 'b' : 'l');
574 fprintf(stderr
,"Error writing package dat file.\n");
578 if (mode
== MODE_COMMON
) {
579 char targetFileNamePath
[LARGE_BUFFER_MAX_SIZE
] = "";
581 uprv_strcpy(targetFileNamePath
, targetDir
);
582 uprv_strcat(targetFileNamePath
, datFileName
);
584 if (T_FileStream_file_exists(targetFileNamePath
)) {
585 if ((result
= remove(targetFileNamePath
)) != 0) {
586 fprintf(stderr
, "Unable to remove old dat file: %s\n", targetFileNamePath
);
591 /* Move the dat file created to the target directory. */
592 result
= rename(datFileNamePath
, targetFileNamePath
);
595 fprintf(stdout
, "# Moving package file to %s ..\n", targetFileNamePath
);
598 fprintf(stderr
, "Unable to move dat file (%s) to target location (%s).\n", datFileNamePath
, targetFileNamePath
);
601 if (o
->install
!= NULL
) {
602 result
= pkg_installCommonMode(o
->install
, targetFileNamePath
);
606 } else /* if (mode[0] == MODE_STATIC || mode[0] == MODE_DLL) */ {
607 char gencFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
608 char version_major
[10] = "";
609 UBool reverseExt
= FALSE
;
611 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
612 /* Get the version major number. */
613 if (o
->version
!= NULL
) {
614 for (uint32_t i
= 0;i
< sizeof(version_major
);i
++) {
615 if (o
->version
[i
] == '.') {
616 version_major
[i
] = 0;
619 version_major
[i
] = o
->version
[i
];
624 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
625 * reverseExt is FALSE if the suffix should be the version number.
627 if (pkgDataFlags
[LIB_EXT_ORDER
][uprv_strlen(pkgDataFlags
[LIB_EXT_ORDER
])-1] == pkgDataFlags
[SO_EXT
][uprv_strlen(pkgDataFlags
[SO_EXT
])-1]) {
631 /* Using the base libName and version number, generate the library file names. */
632 createFileNames(o
, mode
, version_major
, o
->version
, o
->libName
, reverseExt
);
634 if ((o
->version
!=NULL
|| (mode
==MODE_STATIC
)) && o
->rebuild
== FALSE
) {
635 /* Check to see if a previous built data library file exists and check if it is the latest. */
636 sprintf(checkLibFile
, "%s%s", targetDir
, libFileNames
[LIB_FILE_VERSION
]);
637 if (T_FileStream_file_exists(checkLibFile
)) {
638 if (isFileModTimeLater(checkLibFile
, o
->srcDir
, TRUE
) && isFileModTimeLater(checkLibFile
, o
->options
)) {
639 if (o
->install
!= NULL
) {
641 fprintf(stdout
, "# Installing already-built library into %s\n", o
->install
);
643 result
= pkg_installLibrary(o
->install
, targetDir
);
646 printf("# Not rebuilding %s - up to date.\n", checkLibFile
);
650 } else if (o
->verbose
&& (o
->install
!=NULL
)) {
651 fprintf(stdout
, "# Not installing up-to-date library %s into %s\n", checkLibFile
, o
->install
);
653 } else if(o
->verbose
&& (o
->install
!=NULL
)) {
654 fprintf(stdout
, "# Not installing missing %s into %s\n", checkLibFile
, o
->install
);
661 if (pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
][0] != 0) {
662 const char* genccodeAssembly
= pkgDataFlags
[GENCCODE_ASSEMBLY_TYPE
];
665 fprintf(stdout
, "# Generating assembly code %s of type %s ..\n", gencFilePath
, genccodeAssembly
);
668 /* Offset genccodeAssembly by 3 because "-a " */
669 if (genccodeAssembly
&&
670 (uprv_strlen(genccodeAssembly
)>3) &&
671 checkAssemblyHeaderName(genccodeAssembly
+3)) {
672 writeAssemblyCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, NULL
, gencFilePath
);
674 result
= pkg_createWithAssemblyCode(targetDir
, mode
, gencFilePath
);
676 fprintf(stderr
, "Error generating assembly code for data.\n");
678 } else if (mode
== MODE_STATIC
) {
679 if(o
->install
!= NULL
) {
681 fprintf(stdout
, "# Installing static library into %s\n", o
->install
);
683 result
= pkg_installLibrary(o
->install
, targetDir
);
688 fprintf(stderr
,"Assembly type \"%s\" is unknown.\n", genccodeAssembly
);
693 fprintf(stdout
, "# Writing object code to %s ..\n", gencFilePath
);
695 #ifdef CAN_WRITE_OBJ_CODE
696 writeObjectCode(datFileNamePath
, o
->tmpDir
, o
->entryName
, NULL
, NULL
, gencFilePath
);
698 result
= pkg_generateLibraryFile(targetDir
, mode
, gencFilePath
);
699 #elif defined(WINDOWS_WITH_MSVC)
700 result
= pkg_createWindowsDLL(mode
, gencFilePath
, o
);
702 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
703 result
= pkg_createWithoutAssemblyCode(o
, targetDir
, mode
);
706 fprintf(stderr
, "Error generating package data.\n");
711 if(mode
!= MODE_STATIC
) {
712 /* Certain platforms uses archive library. (e.g. AIX) */
714 fprintf(stdout
, "# Creating data archive library file ..\n");
716 result
= pkg_archiveLibrary(targetDir
, o
->version
, reverseExt
);
718 fprintf(stderr
, "Error creating data archive library file.\n");
722 /* Create symbolic links for the final library file. */
723 result
= pkg_createSymLinks(targetDir
);
725 fprintf(stderr
, "Error creating symbolic links of the data library file.\n");
732 #if !defined(U_WINDOWS) || defined(USING_CYGWIN)
733 /* Install the libraries if option was set. */
734 if (o
->install
!= NULL
) {
736 fprintf(stdout
, "# Installing library file to %s ..\n", o
->install
);
738 result
= pkg_installLibrary(o
->install
, targetDir
);
740 fprintf(stderr
, "Error installing the data library.\n");
750 /* Initialize the pkgDataFlags with the option file given. */
751 static int32_t initializePkgDataFlags(UPKGOptions
*o
) {
752 UErrorCode status
= U_ZERO_ERROR
;
754 int32_t currentBufferSize
= SMALL_BUFFER_MAX_SIZE
;
755 int32_t tmpResult
= 0;
757 /* Initialize pkgdataFlags */
758 pkgDataFlags
= (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE
);
760 /* If we run out of space, allocate more */
761 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
764 if (pkgDataFlags
!= NULL
) {
765 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
766 pkgDataFlags
[i
] = (char*)uprv_malloc(sizeof(char) * currentBufferSize
);
767 if (pkgDataFlags
[i
] != NULL
) {
768 pkgDataFlags
[i
][0] = 0;
770 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
775 fprintf(stderr
,"Error allocating memory for pkgDataFlags.\n");
779 if (o
->options
== NULL
) {
783 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
784 /* Read in options file. */
786 fprintf(stdout
, "# Reading options file %s\n", o
->options
);
788 status
= U_ZERO_ERROR
;
789 tmpResult
= parseFlagsFile(o
->options
, pkgDataFlags
, currentBufferSize
, (int32_t)PKGDATA_FLAGS_SIZE
, &status
);
790 if (status
== U_BUFFER_OVERFLOW_ERROR
) {
791 for (int32_t i
= 0; i
< PKGDATA_FLAGS_SIZE
; i
++) {
792 uprv_free(pkgDataFlags
[i
]);
794 currentBufferSize
= tmpResult
;
795 } else if (U_FAILURE(status
)) {
796 fprintf(stderr
,"Unable to open or read \"%s\" option file. status = %s\n", o
->options
, u_errorName(status
));
801 fprintf(stdout
, "# pkgDataFlags=");
802 for(int32_t i
=0;i
<PKGDATA_FLAGS_SIZE
&& pkgDataFlags
[i
][0];i
++) {
803 fprintf(stdout
, "%c \"%s\"", (i
>0)?',':' ',pkgDataFlags
[i
]);
805 fprintf(stdout
, "\n");
807 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
808 } while (status
== U_BUFFER_OVERFLOW_ERROR
);
816 * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
817 * Depending on the configuration, the library name may either end with version number or shared object suffix.
819 static void createFileNames(UPKGOptions
*o
, const char mode
, const char *version_major
, const char *version
, const char *libName
, UBool reverseExt
) {
820 sprintf(libFileNames
[LIB_FILE
], "%s%s",
821 pkgDataFlags
[LIBPREFIX
],
825 fprintf(stdout
, "# libFileName[LIB_FILE] = %s\n", libFileNames
[LIB_FILE
]);
828 if (version
!= NULL
) {
830 sprintf(libFileNames
[LIB_FILE_CYGWIN
], "cyg%s.%s",
832 pkgDataFlags
[SO_EXT
]);
833 sprintf(libFileNames
[LIB_FILE_CYGWIN_VERSION
], "cyg%s%s.%s",
836 pkgDataFlags
[SO_EXT
]);
838 uprv_strcat(pkgDataFlags
[SO_EXT
], ".");
839 uprv_strcat(pkgDataFlags
[SO_EXT
], pkgDataFlags
[A_EXT
]);
841 #elif defined(OS400) || defined(_AIX)
842 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s.%s",
843 libFileNames
[LIB_FILE
],
844 pkgDataFlags
[SOBJ_EXT
]);
846 sprintf(libFileNames
[LIB_FILE_VERSION_TMP
], "%s%s%s.%s",
847 libFileNames
[LIB_FILE
],
848 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
849 reverseExt
? version
: pkgDataFlags
[SOBJ_EXT
],
850 reverseExt
? pkgDataFlags
[SOBJ_EXT
] : version
);
852 sprintf(libFileNames
[LIB_FILE_VERSION_MAJOR
], "%s%s%s.%s",
853 libFileNames
[LIB_FILE
],
854 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
855 reverseExt
? version_major
: pkgDataFlags
[SO_EXT
],
856 reverseExt
? pkgDataFlags
[SO_EXT
] : version_major
);
858 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s.%s",
859 libFileNames
[LIB_FILE
],
860 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
861 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
862 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
865 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames
[LIB_FILE_VERSION
]);
869 /* Cygwin only deals with the version major number. */
870 uprv_strcpy(libFileNames
[LIB_FILE_VERSION_TMP
], libFileNames
[LIB_FILE_VERSION_MAJOR
]);
873 if(mode
== MODE_STATIC
) {
874 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s.%s", libFileNames
[LIB_FILE
], pkgDataFlags
[A_EXT
]);
875 libFileNames
[LIB_FILE_VERSION_MAJOR
][0]=0;
877 fprintf(stdout
, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames
[LIB_FILE_VERSION
]);
882 /* Create the symbolic links for the final library file. */
883 static int32_t pkg_createSymLinks(const char *targetDir
, UBool specialHandling
) {
885 char cmd
[LARGE_BUFFER_MAX_SIZE
];
886 char name1
[SMALL_BUFFER_MAX_SIZE
]; /* symlink file name */
887 char name2
[SMALL_BUFFER_MAX_SIZE
]; /* file name to symlink */
890 /* No symbolic link to make. */
891 if (uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) == 0 || uprv_strlen(libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0 ||
892 uprv_strcmp(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_MAJOR
]) == 0) {
896 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
899 libFileNames
[LIB_FILE_VERSION_MAJOR
],
901 libFileNames
[LIB_FILE_VERSION
],
902 libFileNames
[LIB_FILE_VERSION_MAJOR
]);
903 result
= runCommand(cmd
);
909 if (specialHandling
) {
911 sprintf(name1
, "%s", libFileNames
[LIB_FILE_CYGWIN
]);
912 sprintf(name2
, "%s", libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
914 goto normal_symlink_mode
;
918 sprintf(name1
, "%s.%s", libFileNames
[LIB_FILE
], pkgDataFlags
[SO_EXT
]);
919 sprintf(name2
, "%s", libFileNames
[LIB_FILE_VERSION
]);
922 sprintf(cmd
, "cd %s && %s %s && %s %s %s",
930 result
= runCommand(cmd
);
935 static int32_t pkg_installLibrary(const char *installDir
, const char *targetDir
) {
937 char cmd
[SMALL_BUFFER_MAX_SIZE
];
939 sprintf(cmd
, "cd %s && %s %s %s%s%s",
941 pkgDataFlags
[INSTALL_CMD
],
942 libFileNames
[LIB_FILE_VERSION
],
943 installDir
, PKGDATA_FILE_SEP_STRING
, libFileNames
[LIB_FILE_VERSION
]
946 result
= runCommand(cmd
);
953 sprintf(cmd
, "cd %s && %s %s.lib %s",
955 pkgDataFlags
[INSTALL_CMD
],
956 libFileNames
[LIB_FILE
],
959 result
= runCommand(cmd
);
964 #elif defined (U_CYGWIN)
965 sprintf(cmd
, "cd %s && %s %s %s",
967 pkgDataFlags
[INSTALL_CMD
],
968 libFileNames
[LIB_FILE_CYGWIN_VERSION
],
971 result
= runCommand(cmd
);
978 return pkg_createSymLinks(installDir
, TRUE
);
981 static int32_t pkg_installCommonMode(const char *installDir
, const char *fileName
) {
983 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
985 if (!T_FileStream_file_exists(installDir
)) {
986 UErrorCode status
= U_ZERO_ERROR
;
988 uprv_mkdir(installDir
, &status
);
989 if (U_FAILURE(status
)) {
990 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
994 #ifndef U_WINDOWS_WITH_MSVC
995 sprintf(cmd
, "%s %s %s", pkgDataFlags
[INSTALL_CMD
], fileName
, installDir
);
997 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, fileName
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1000 result
= runCommand(cmd
);
1002 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1008 #ifdef U_WINDOWS_MSVC
1009 /* Copy commands for installing the raw data files on Windows. */
1010 #define WIN_INSTALL_CMD "xcopy"
1011 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
1013 static int32_t pkg_installFileMode(const char *installDir
, const char *srcDir
, const char *fileListName
) {
1015 char cmd
[SMALL_BUFFER_MAX_SIZE
] = "";
1017 if (!T_FileStream_file_exists(installDir
)) {
1018 UErrorCode status
= U_ZERO_ERROR
;
1020 uprv_mkdir(installDir
, &status
);
1021 if (U_FAILURE(status
)) {
1022 fprintf(stderr
, "Error creating installation directory: %s\n", installDir
);
1026 #ifndef U_WINDOWS_WITH_MSVC
1027 char buffer
[SMALL_BUFFER_MAX_SIZE
] = "";
1029 FileStream
*f
= T_FileStream_open(fileListName
, "r");
1032 if (T_FileStream_readLine(f
, buffer
, SMALL_BUFFER_MAX_SIZE
) != NULL
) {
1033 /* Remove new line character. */
1034 buffer
[uprv_strlen(buffer
)-1] = 0;
1036 sprintf(cmd
, "%s %s%s%s %s%s%s",
1037 pkgDataFlags
[INSTALL_CMD
],
1038 srcDir
, PKGDATA_FILE_SEP_STRING
, buffer
,
1039 installDir
, PKGDATA_FILE_SEP_STRING
, buffer
);
1041 result
= runCommand(cmd
);
1043 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1047 if (!T_FileStream_eof(f
)) {
1048 fprintf(stderr
, "Failed to read line from file: %s\n", fileListName
);
1054 T_FileStream_close(f
);
1057 fprintf(stderr
, "Unable to open list file: %s\n", fileListName
);
1060 sprintf(cmd
, "%s %s %s %s", WIN_INSTALL_CMD
, srcDir
, installDir
, WIN_INSTALL_CMD_FLAGS
);
1061 result
= runCommand(cmd
);
1063 fprintf(stderr
, "Failed to install data file with command: %s\n", cmd
);
1070 /* Archiving of the library file may be needed depending on the platform and options given.
1071 * If archiving is not needed, copy over the library file name.
1073 static int32_t pkg_archiveLibrary(const char *targetDir
, const char *version
, UBool reverseExt
) {
1075 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1077 /* If the shared object suffix and the final object suffix is different and the final object suffix and the
1078 * archive file suffix is the same, then the final library needs to be archived.
1080 if (uprv_strcmp(pkgDataFlags
[SOBJ_EXT
], pkgDataFlags
[SO_EXT
]) != 0 && uprv_strcmp(pkgDataFlags
[A_EXT
], pkgDataFlags
[SO_EXT
]) == 0) {
1081 sprintf(libFileNames
[LIB_FILE_VERSION
], "%s%s%s.%s",
1082 libFileNames
[LIB_FILE
],
1083 pkgDataFlags
[LIB_EXT_ORDER
][0] == '.' ? "." : "",
1084 reverseExt
? version
: pkgDataFlags
[SO_EXT
],
1085 reverseExt
? pkgDataFlags
[SO_EXT
] : version
);
1087 sprintf(cmd
, "%s %s %s%s %s%s",
1089 pkgDataFlags
[ARFLAGS
],
1091 libFileNames
[LIB_FILE_VERSION
],
1093 libFileNames
[LIB_FILE_VERSION_TMP
]);
1095 result
= runCommand(cmd
);
1100 sprintf(cmd
, "%s %s%s",
1101 pkgDataFlags
[RANLIB
],
1103 libFileNames
[LIB_FILE_VERSION
]);
1105 result
= runCommand(cmd
);
1110 /* Remove unneeded library file. */
1111 sprintf(cmd
, "%s %s%s",
1114 libFileNames
[LIB_FILE_VERSION_TMP
]);
1116 result
= runCommand(cmd
);
1122 uprv_strcpy(libFileNames
[LIB_FILE_VERSION
], libFileNames
[LIB_FILE_VERSION_TMP
]);
1129 * Using the compiler information from the configuration file set by -O option, generate the library file.
1130 * command may be given to allow for a larger buffer for cmd.
1132 static int32_t pkg_generateLibraryFile(const char *targetDir
, const char mode
, const char *objectFile
, char *command
) {
1135 UBool freeCmd
= FALSE
;
1138 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
1139 * containing many object files and so the calling function should supply a command buffer that is large
1140 * enough to handle this. Otherwise, use the default size.
1142 if (command
!= NULL
) {
1146 if (mode
== MODE_STATIC
) {
1148 length
= uprv_strlen(pkgDataFlags
[AR
]) + uprv_strlen(pkgDataFlags
[ARFLAGS
]) + uprv_strlen(targetDir
) +
1149 uprv_strlen(libFileNames
[LIB_FILE_VERSION
]) + uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[RANLIB
]) + BUFFER_PADDING_SIZE
;
1150 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1151 fprintf(stderr
, "Unable to allocate memory for command.\n");
1156 sprintf(cmd
, "%s %s %s%s %s",
1158 pkgDataFlags
[ARFLAGS
],
1160 libFileNames
[LIB_FILE_VERSION
],
1163 result
= runCommand(cmd
);
1165 sprintf(cmd
, "%s %s%s",
1166 pkgDataFlags
[RANLIB
],
1168 libFileNames
[LIB_FILE_VERSION
]);
1170 result
= runCommand(cmd
);
1172 } else /* if (mode == MODE_DLL) */ {
1174 length
= uprv_strlen(pkgDataFlags
[GENLIB
]) + uprv_strlen(pkgDataFlags
[LDICUDTFLAGS
]) +
1175 uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_VERSION_TMP
]) +
1176 uprv_strlen(objectFile
) + uprv_strlen(pkgDataFlags
[LD_SONAME
]) +
1177 uprv_strlen(pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
]) +
1178 uprv_strlen(pkgDataFlags
[RPATH_FLAGS
]) + uprv_strlen(pkgDataFlags
[BIR_FLAGS
]) + BUFFER_PADDING_SIZE
;
1180 length
+= uprv_strlen(targetDir
) + uprv_strlen(libFileNames
[LIB_FILE_CYGWIN_VERSION
]);
1182 if ((cmd
= (char *)uprv_malloc(sizeof(char) * length
)) == NULL
) {
1183 fprintf(stderr
, "Unable to allocate memory for command.\n");
1189 sprintf(cmd
, "%s%s%s %s -o %s%s %s %s%s %s %s",
1190 pkgDataFlags
[GENLIB
],
1192 libFileNames
[LIB_FILE_VERSION_TMP
],
1193 pkgDataFlags
[LDICUDTFLAGS
],
1194 targetDir
, libFileNames
[LIB_FILE_CYGWIN_VERSION
],
1196 sprintf(cmd
, "%s %s -o %s%s %s %s%s %s %s",
1197 pkgDataFlags
[GENLIB
],
1198 pkgDataFlags
[LDICUDTFLAGS
],
1200 libFileNames
[LIB_FILE_VERSION_TMP
],
1203 pkgDataFlags
[LD_SONAME
],
1204 pkgDataFlags
[LD_SONAME
][0] == 0 ? "" : libFileNames
[LIB_FILE_VERSION_MAJOR
],
1205 pkgDataFlags
[RPATH_FLAGS
],
1206 pkgDataFlags
[BIR_FLAGS
]);
1208 /* Generate the library file. */
1209 result
= runCommand(cmd
);
1219 static int32_t pkg_createWithAssemblyCode(const char *targetDir
, const char mode
, const char *gencFilePath
) {
1220 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1226 /* Remove the ending .s and replace it with .o for the new object file. */
1227 uprv_strcpy(tempObjectFile
, gencFilePath
);
1228 tempObjectFile
[uprv_strlen(tempObjectFile
)-1] = 'o';
1230 length
= uprv_strlen(pkgDataFlags
[COMPILER
]) + uprv_strlen(pkgDataFlags
[LIBFLAGS
])
1231 + uprv_strlen(tempObjectFile
) + uprv_strlen(gencFilePath
) + BUFFER_PADDING_SIZE
;
1233 cmd
= (char *)uprv_malloc(sizeof(char) * length
);
1238 /* Generate the object file. */
1239 sprintf(cmd
, "%s %s -o %s %s",
1240 pkgDataFlags
[COMPILER
],
1241 pkgDataFlags
[LIBFLAGS
],
1245 result
= runCommand(cmd
);
1251 return pkg_generateLibraryFile(targetDir
, mode
, tempObjectFile
);
1254 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
1256 * Generation of the data library without assembly code needs to compile each data file
1257 * individually and then link it all together.
1258 * Note: Any update to the directory structure of the data needs to be reflected here.
1267 DATA_PREFIX_TRANSLIT
,
1272 const static char DATA_PREFIX
[DATA_PREFIX_LENGTH
][10] = {
1283 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions
*o
, const char *targetDir
, const char mode
) {
1285 CharList
*list
= o
->filePaths
;
1286 CharList
*listNames
= o
->files
;
1287 int32_t listSize
= pkg_countCharList(list
);
1290 char gencmnFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1291 char tempObjectFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1292 #ifdef USE_SINGLE_CCODE_FILE
1293 char icudtAll
[SMALL_BUFFER_MAX_SIZE
] = "";
1295 sprintf(icudtAll
, "%s%s%sall.c",
1297 PKGDATA_FILE_SEP_STRING
,
1298 libFileNames
[LIB_FILE
]);
1299 /* Remove previous icudtall.c file. */
1300 if (T_FileStream_file_exists(icudtAll
) && (result
= remove(icudtAll
)) != 0) {
1301 fprintf(stderr
, "Unable to remove old icudtall file: %s\n", icudtAll
);
1306 if (list
== NULL
|| listNames
== NULL
) {
1307 /* list and listNames should never be NULL since we are looping through the CharList with
1313 if ((cmd
= (char *)uprv_malloc((listSize
+ 2) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1314 fprintf(stderr
, "Unable to allocate memory for cmd.\n");
1316 } else if ((buffer
= (char *)uprv_malloc((listSize
+ 1) * SMALL_BUFFER_MAX_SIZE
)) == NULL
) {
1317 fprintf(stderr
, "Unable to allocate memory for buffer.\n");
1322 for (int32_t i
= 0; i
< (listSize
+ 1); i
++) {
1327 /* The first iteration calls the gencmn function and initailizes the buffer. */
1328 createCommonDataFile(o
->tmpDir
, o
->shortName
, o
->entryName
, NULL
, o
->srcDir
, o
->comment
, o
->fileListFiles
->str
, 0, TRUE
, o
->verbose
, gencmnFile
);
1330 #ifdef USE_SINGLE_CCODE_FILE
1331 uprv_strcpy(tempObjectFile
, gencmnFile
);
1332 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1334 sprintf(cmd
, "%s %s -o %s %s"
1335 pkgDataFlags
[COMPILER
],
1336 pkgDataFlags
[LIBFLAGS
],
1340 result
= runCommand(cmd
);
1345 sprintf(buffer
, "%s",tempObjectFile
);
1348 char newName
[SMALL_BUFFER_MAX_SIZE
];
1349 char dataName
[SMALL_BUFFER_MAX_SIZE
];
1350 char dataDirName
[SMALL_BUFFER_MAX_SIZE
];
1351 const char *pSubstring
;
1353 name
= listNames
->str
;
1355 newName
[0] = dataName
[0] = 0;
1356 for (int32_t n
= 0; n
< DATA_PREFIX_LENGTH
; n
++) {
1358 sprintf(dataDirName
, "%s%s", DATA_PREFIX
[n
], PKGDATA_FILE_SEP_STRING
);
1359 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
1360 pSubstring
= uprv_strstr(name
, dataDirName
);
1361 if (pSubstring
!= NULL
) {
1362 char newNameTmp
[SMALL_BUFFER_MAX_SIZE
] = "";
1363 const char *p
= name
+ uprv_strlen(dataDirName
);
1364 for (int32_t i
= 0;;i
++) {
1366 newNameTmp
[i
] = '_';
1369 newNameTmp
[i
] = p
[i
];
1374 sprintf(newName
, "%s_%s",
1377 sprintf(dataName
, "%s_%s",
1381 if (newName
[0] != 0) {
1386 writeCCode(file
, o
->tmpDir
, dataName
[0] != 0 ? dataName
: o
->shortName
, newName
[0] != 0 ? newName
: NULL
, gencmnFile
);
1387 #ifdef USE_SINGLE_CCODE_FILE
1388 sprintf(cmd
, "cat %s >> %s", gencmnFile
, icudtAll
);
1390 result
= runCommand(cmd
);
1394 /* Remove the c code file after concatenating it to icudtall.c file. */
1395 if ((result
= remove(gencmnFile
)) != 0) {
1396 fprintf(stderr
, "Unable to remove c code file: %s\n", gencmnFile
);
1403 #ifndef USE_SINGLE_CCODE_FILE
1404 uprv_strcpy(tempObjectFile
, gencmnFile
);
1405 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1407 sprintf(cmd
, "%s %s -o %s %s",
1408 pkgDataFlags
[COMPILER
],
1409 pkgDataFlags
[LIBFLAGS
],
1412 result
= runCommand(cmd
);
1417 uprv_strcat(buffer
, " ");
1418 uprv_strcat(buffer
, tempObjectFile
);
1424 listNames
= listNames
->next
;
1428 #ifdef USE_SINGLE_CCODE_FILE
1429 uprv_strcpy(tempObjectFile
, icudtAll
);
1430 tempObjectFile
[uprv_strlen(tempObjectFile
) - 1] = 'o';
1432 sprintf(cmd
, "%s %s -o %s %s",
1433 pkgDataFlags
[COMPILER
],
1434 pkgDataFlags
[LIBFLAGS
],
1438 result
= runCommand(cmd
);
1440 uprv_strcat(buffer
, " ");
1441 uprv_strcat(buffer
, tempObjectFile
);
1446 /* Generate the library file. */
1447 result
= pkg_generateLibraryFile(targetDir
, mode
, buffer
, cmd
);
1457 #ifdef WINDOWS_WITH_MSVC
1458 #define LINK_CMD "link.exe /nologo /release /out:"
1459 #define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /base:0x4ad00000 /implib:"
1460 #define LIB_CMD "LIB.exe /nologo /out:"
1461 #define LIB_FILE "icudt.lib"
1462 #define LIB_EXT UDATA_LIB_SUFFIX
1463 #define DLL_EXT UDATA_SO_SUFFIX
1465 static int32_t pkg_createWindowsDLL(const char mode
, const char *gencFilePath
, UPKGOptions
*o
) {
1466 char cmd
[LARGE_BUFFER_MAX_SIZE
];
1467 if (mode
== MODE_STATIC
) {
1468 char staticLibFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1470 uprv_strcpy(staticLibFilePath
, o
->tmpDir
);
1471 uprv_strcat(staticLibFilePath
, PKGDATA_FILE_SEP_STRING
);
1473 uprv_strcat(staticLibFilePath
, o
->entryName
);
1474 uprv_strcat(staticLibFilePath
, LIB_EXT
);
1476 sprintf(cmd
, "%s\"%s\" \"%s\"",
1480 } else if (mode
== MODE_DLL
) {
1481 char dllFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1482 char libFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1483 char resFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1484 char tmpResFilePath
[SMALL_BUFFER_MAX_SIZE
] = "";
1487 uprv_strcpy(dllFilePath
, o
->targetDir
);
1489 uprv_strcpy(dllFilePath
, o
->srcDir
);
1491 uprv_strcat(dllFilePath
, PKGDATA_FILE_SEP_STRING
);
1492 uprv_strcpy(libFilePath
, dllFilePath
);
1495 uprv_strcat(libFilePath
, o
->libName
);
1496 uprv_strcat(libFilePath
, ".lib");
1498 uprv_strcat(dllFilePath
, o
->libName
);
1499 uprv_strcat(dllFilePath
, o
->version
);
1501 if (strstr(o
->libName
, "icudt")) {
1502 uprv_strcat(libFilePath
, LIB_FILE
);
1504 uprv_strcat(libFilePath
, o
->libName
);
1505 uprv_strcat(libFilePath
, ".lib");
1507 uprv_strcat(dllFilePath
, o
->entryName
);
1509 uprv_strcat(dllFilePath
, DLL_EXT
);
1511 uprv_strcpy(tmpResFilePath
, o
->tmpDir
);
1512 uprv_strcat(tmpResFilePath
, PKGDATA_FILE_SEP_STRING
);
1513 uprv_strcat(tmpResFilePath
, ICUDATA_RES_FILE
);
1515 if (T_FileStream_file_exists(tmpResFilePath
)) {
1516 sprintf(resFilePath
, "\"%s\"", tmpResFilePath
);
1519 /* Check if dll file and lib file exists and that it is not newer than genc file. */
1520 if (!o
->rebuild
&& (T_FileStream_file_exists(dllFilePath
) && isFileModTimeLater(dllFilePath
, gencFilePath
)) &&
1521 (T_FileStream_file_exists(libFilePath
) && isFileModTimeLater(libFilePath
, gencFilePath
))) {
1523 printf("# Not rebuilding %s - up to date.\n", gencFilePath
);
1528 sprintf(cmd
, "%s\"%s\" %s\"%s\" \"%s\" %s",
1538 return runCommand(cmd
, TRUE
);
1542 static UPKGOptions
*pkg_checkFlag(UPKGOptions
*o
) {
1544 /* AIX needs a map file. */
1547 char tmpbuffer
[SMALL_BUFFER_MAX_SIZE
];
1548 const char MAP_FILE_EXT
[] = ".map";
1549 FileStream
*f
= NULL
;
1550 char mapFile
[SMALL_BUFFER_MAX_SIZE
] = "";
1554 flag
= pkgDataFlags
[BIR_FLAGS
];
1555 length
= uprv_strlen(pkgDataFlags
[BIR_FLAGS
]);
1557 for (int32_t i
= 0; i
< length
; i
++) {
1558 if (flag
[i
] == MAP_FILE_EXT
[count
]) {
1567 if (count
== uprv_strlen(MAP_FILE_EXT
)) {
1574 for (int32_t i
= 0;;i
++) {
1576 for (int32_t n
= 0;;n
++) {
1577 if (o
->shortName
[n
] == 0) {
1580 tmpbuffer
[index
++] = o
->shortName
[n
];
1584 tmpbuffer
[index
++] = flag
[i
];
1591 uprv_memset(flag
, 0, length
);
1592 uprv_strcpy(flag
, tmpbuffer
);
1594 uprv_strcpy(mapFile
, o
->shortName
);
1595 uprv_strcat(mapFile
, MAP_FILE_EXT
);
1597 f
= T_FileStream_open(mapFile
, "w");
1599 fprintf(stderr
,"Unable to create map file: %s.\n", mapFile
);
1601 sprintf(tmpbuffer
, "%s%s ", o
->entryName
, UDATA_CMN_INTERMEDIATE_SUFFIX
);
1603 T_FileStream_writeLine(f
, tmpbuffer
);
1605 T_FileStream_close(f
);
1608 #elif defined(U_CYGWIN)
1609 /* Cygwin needs to change flag options. */
1613 flag
= pkgDataFlags
[GENLIB
];
1614 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1616 int32_t position
= length
- 1;
1618 for(;position
>= 0;position
--) {
1619 if (flag
[position
] == '=') {
1625 uprv_memset(flag
+ position
, 0, length
- position
);
1626 #elif defined(OS400)
1627 /* OS400 needs to fix the ld options (swap single quote with double quote) */
1631 flag
= pkgDataFlags
[GENLIB
];
1632 length
= uprv_strlen(pkgDataFlags
[GENLIB
]);
1634 int32_t position
= length
- 1;
1636 for(int32_t i
= 0; i
< length
; i
++) {
1637 if (flag
[i
] == '\'') {
1642 // Don't really need a return value, just need to stop compiler warnings about
1643 // the unused parameter 'o' on platforms where it is not otherwise used.
1647 static void loadLists(UPKGOptions
*o
, UErrorCode
*status
)
1649 CharList
*l
, *tail
= NULL
, *tail2
= NULL
;
1652 char *linePtr
, *lineNext
;
1653 const uint32_t lineMax
= 16300;
1656 int32_t ln
=0; /* line number */
1658 for(l
= o
->fileListFiles
; l
; l
= l
->next
) {
1660 fprintf(stdout
, "# pkgdata: Reading %s..\n", l
->str
);
1663 in
= T_FileStream_open(l
->str
, "r"); /* open files list */
1666 fprintf(stderr
, "Error opening <%s>.\n", l
->str
);
1667 *status
= U_FILE_ACCESS_ERROR
;
1671 while(T_FileStream_readLine(in
, line
, sizeof(line
))!=NULL
) { /* for each line */
1673 if(uprv_strlen(line
)>lineMax
) {
1674 fprintf(stderr
, "%s:%d - line too long (over %d chars)\n", l
->str
, (int)ln
, (int)lineMax
);
1677 /* remove spaces at the beginning */
1679 while(isspace(*linePtr
)) {
1683 /* remove trailing newline characters */
1685 if(*s
=='\r' || *s
=='\n') {
1691 if((*linePtr
== 0) || (*linePtr
== '#')) {
1692 continue; /* comment or empty line */
1695 /* Now, process the line */
1698 while(linePtr
&& *linePtr
) { /* process space-separated items */
1699 while(*linePtr
== ' ') {
1702 /* Find the next quote */
1703 if(linePtr
[0] == '"')
1705 lineNext
= uprv_strchr(linePtr
+1, '"');
1706 if(lineNext
== NULL
) {
1707 fprintf(stderr
, "%s:%d - missing trailing double quote (\")\n",
1713 if(*lineNext
!= ' ') {
1714 fprintf(stderr
, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
1715 l
->str
, (int)ln
, (int)(lineNext
-line
), (*lineNext
)?*lineNext
:'0');
1723 lineNext
= uprv_strchr(linePtr
, ' ');
1725 *lineNext
= 0; /* terminate at space */
1731 s
= (char*)getLongPathname(linePtr
);
1733 /* normal mode.. o->files is just the bare list without package names */
1734 o
->files
= pkg_appendToList(o
->files
, &tail
, uprv_strdup(linePtr
));
1735 if(uprv_pathIsAbsolute(s
)) {
1736 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
);
1737 exit(U_ILLEGAL_ARGUMENT_ERROR
);
1739 uprv_strcpy(tmp
, o
->srcDir
);
1740 uprv_strcat(tmp
, o
->srcDir
[uprv_strlen(o
->srcDir
)-1] == U_FILE_SEP_CHAR
? "" :PKGDATA_FILE_SEP_STRING
);
1741 uprv_strcat(tmp
, s
);
1742 o
->filePaths
= pkg_appendToList(o
->filePaths
, &tail2
, uprv_strdup(tmp
));
1744 } /* for each entry on line */
1745 } /* for each line */
1746 T_FileStream_close(in
);
1747 } /* for each file list file */
1750 /* Try calling icu-config directly to get the option file. */
1751 static int32_t pkg_getOptionsFromICUConfig(UBool verbose
, UOption
*option
) {
1755 static char buf
[512] = "";
1757 UErrorCode status
= U_ZERO_ERROR
;
1758 const char cmd
[] = "icu-config --incpkgdatafile";
1760 /* #1 try the same path where pkgdata was called from. */
1761 findDirname(progname
, cmdBuf
, 1024, &status
);
1762 if(U_SUCCESS(status
)) {
1763 uprv_strncat(cmdBuf
, U_FILE_SEP_STRING
, 1024);
1764 uprv_strncat(cmdBuf
, cmd
, 1024);
1767 fprintf(stdout
, "# Calling icu-config: %s\n", cmdBuf
);
1769 p
= popen(cmdBuf
, "r");
1774 fprintf(stdout
, "# Calling icu-config: %s\n", cmd
);
1776 p
= popen(cmd
, "r");
1781 fprintf(stderr
, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname
);
1785 n
= fread(buf
, 1, 511, p
);
1791 fprintf(stderr
,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname
);
1795 for (int32_t length
= strlen(buf
) - 1; length
>= 0; length
--) {
1796 if (buf
[length
] == '\n' || buf
[length
] == ' ') {
1803 if(buf
[strlen(buf
)-1]=='\n')
1805 buf
[strlen(buf
)-1]=0;
1810 fprintf(stderr
, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname
);
1815 fprintf(stdout
, "# icu-config said: %s\n", buf
);
1818 option
->value
= buf
;
1819 option
->doesOccur
= TRUE
;