diff --git a/icu4c/source/tools/pkgdata/Makefile.in b/icu4c/source/tools/pkgdata/Makefile.in index a0c484f5f8c..9370da704ca 100644 --- a/icu4c/source/tools/pkgdata/Makefile.in +++ b/icu4c/source/tools/pkgdata/Makefile.in @@ -32,7 +32,7 @@ CLEANFILES = *~ $(DEPS) $(RES_FILES) $(TEST_FILES) mkmap.tmp $(ALL_MAN_FILES) TARGET = pkgdata DEFS = @DEFS@ -CPPFLAGS = @CPPFLAGS@ -I$(top_builddir)/common -I$(top_srcdir)/common -I$(srcdir)/../toolutil -DUDATA_SO_SUFFIX=\".$(SO)\" +CPPFLAGS = @CPPFLAGS@ -I$(top_builddir)/common -I$(top_srcdir)/common -I$(srcdir)/../toolutil -DUDATA_SO_SUFFIX=\".$(SO)\" -DSTATIC_O=\"$(STATIC_O)\" CFLAGS = @CFLAGS@ CXXFLAGS = @CXXFLAGS@ ifeq ($(ENABLE_RPATH),YES) @@ -41,7 +41,7 @@ endif LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS) LIBS = $(LIBICUTOOLUTIL) $(LIBICUUC) @LIBS@ @LIB_M@ -OBJECTS = pkgdata.o pkgtypes.o gmake.o dllmode.o cmnmode.o filemode.o +OBJECTS = pkgdata.o pkgtypes.o gmake.o dllmode.o cmnmode.o filemode.o staticmode.o DEPS = $(OBJECTS:.o=.d) diff --git a/icu4c/source/tools/pkgdata/gmake.c b/icu4c/source/tools/pkgdata/gmake.c index 95385f43e30..db48cef38e1 100644 --- a/icu4c/source/tools/pkgdata/gmake.c +++ b/icu4c/source/tools/pkgdata/gmake.c @@ -25,7 +25,7 @@ char linebuf[2048]; void pkg_mak_writeHeader(FileStream *f, const UPKGOptions *o) { - sprintf(linebuf, "## Makefile for %s created by pkgtool\n" + sprintf(linebuf, "## Makefile for %s created by pkgdata\n" "## from ICU Version %s\n" "\n", o->shortName, diff --git a/icu4c/source/tools/pkgdata/makefile.h b/icu4c/source/tools/pkgdata/makefile.h index 35610e54149..24a28c26340 100644 --- a/icu4c/source/tools/pkgdata/makefile.h +++ b/icu4c/source/tools/pkgdata/makefile.h @@ -46,6 +46,7 @@ extern void pkg_mode_windows(UPKGOptions *o, FileStream *makefile, UErrorCode *s #else /*#ifdef WIN32*/ #ifdef UDATA_SO_SUFFIX extern void pkg_mode_dll(UPKGOptions* o, FileStream *stream, UErrorCode *status); +extern void pkg_mode_static(UPKGOptions* o, FileStream *stream, UErrorCode *status); #endif /*#ifdef UDATA_SO_SUFFIX*/ extern void pkg_mode_common(UPKGOptions* o, FileStream *stream, UErrorCode *status); #endif /*#ifdef WIN32*/ diff --git a/icu4c/source/tools/pkgdata/nmake.c b/icu4c/source/tools/pkgdata/nmake.c index 88dffec7020..c6773ca398d 100644 --- a/icu4c/source/tools/pkgdata/nmake.c +++ b/icu4c/source/tools/pkgdata/nmake.c @@ -25,7 +25,7 @@ char linebuf[2048]; void pkg_mak_writeHeader(FileStream *f, const UPKGOptions *o) { - sprintf(linebuf, "## Makefile for %s created by pkgtool\n" + sprintf(linebuf, "## Makefile for %s created by pkgdata\n" "## from ICU Version %s\n" "\n", o->shortName, diff --git a/icu4c/source/tools/pkgdata/pkgdata.8.in b/icu4c/source/tools/pkgdata/pkgdata.8.in index 22ed6e1f168..5e813e8ad3f 100644 --- a/icu4c/source/tools/pkgdata/pkgdata.8.in +++ b/icu4c/source/tools/pkgdata/pkgdata.8.in @@ -2,11 +2,12 @@ .\" .\" pkgdata.8: manual page for the pkgdata utility .\" -.\" Copyright (C) 2000 IBM, Inc. and others. +.\" Copyright (C) 2000-2002 IBM, Inc. and others. .\" .\" Manual page by Yves Arrouye . +.\" Modified by Steven R. Loomis .\" -.TH PKGDATA 8 "20 December 2001" "ICU MANPAGE" "ICU @VERSION@ Manual" +.TH PKGDATA 8 "1 March 2002" "ICU MANPAGE" "ICU @VERSION@ Manual" .SH NAME .B pkgdata \- package data for use by ICU @@ -98,6 +99,23 @@ linked to the application that uses them. Such resource bundles can then be placed anywhere where the system's dynamic linker will be looking for shared libraries, instead of being forced to live inside the ICU data directory. +.PP +The +.BR static +packaging mode is similar to dll or library, however it produces a +static library. Note that many platforms are not able to dynamically load +symbols from static object files, so for this reason +.BR udata_setAppData() +must be called +to install this data. As a convenience, pkgdata will build a C source file +and a header file. Given a data package named "\fIname\fP", in the output +directory will be created \fIname\fR.c and \fIname\fR.h with the single +function \fBudata_install_\fIname\fB(UErrorCode *err)\fR. Call this function +once early in the program. The error code returned is that of \fBudata_setAppData()\fP. +Subsequently, the application can access this data by passing "\fIname\fP" for the "path" +argument to functions such as \fBures_open()\fP. + + .PP Finally, .B pkgdata diff --git a/icu4c/source/tools/pkgdata/pkgdata.c b/icu4c/source/tools/pkgdata/pkgdata.c index 33074c9fc84..ca87f4212ea 100644 --- a/icu4c/source/tools/pkgdata/pkgdata.c +++ b/icu4c/source/tools/pkgdata/pkgdata.c @@ -1,6 +1,6 @@ /****************************************************************************** * -* Copyright (C) 2000-2001, International Business Machines +* Copyright (C) 2000-2002, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -51,7 +51,8 @@ static struct #ifdef UDATA_SO_SUFFIX { "dll", "library", pkg_mode_dll, "Generates one shared library, " UDATA_SO_SUFFIX }, #endif - { "common", "archive", pkg_mode_common, "Generates one common data file, .dat" } + { "common", "archive", pkg_mode_common, "Generates one common data file, .dat" }, + { "static", "static", pkg_mode_static, "Generates one statically linked library, " LIB_PREFIX "" UDATA_LIB_SUFFIX } #endif /*#ifdef WIN32*/ }; diff --git a/icu4c/source/tools/pkgdata/pkgtypes.h b/icu4c/source/tools/pkgdata/pkgtypes.h index 1af07ed2ae6..8afcce22de6 100644 --- a/icu4c/source/tools/pkgdata/pkgtypes.h +++ b/icu4c/source/tools/pkgdata/pkgtypes.h @@ -127,6 +127,7 @@ typedef struct UPKGOptions_ #else /* POSIX? */ # define LIB_PREFIX "lib" # define OBJ_SUFFIX ".o" +# define UDATA_LIB_SUFFIX ".a" #endif diff --git a/icu4c/source/tools/pkgdata/staticmode.c b/icu4c/source/tools/pkgdata/staticmode.c new file mode 100644 index 00000000000..d47c1c6026e --- /dev/null +++ b/icu4c/source/tools/pkgdata/staticmode.c @@ -0,0 +1,220 @@ +/****************************************************************************** +* +* Copyright (C) 2002, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: staticmode.c +* encoding: ANSI X3.4 (1968) +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2000may15 +* created by: Steven \u24C7 Loomis +* +* This program packages the ICU data into different forms +* (DLL, common data, etc.) +*/ + +#include +#include +#include "unicode/utypes.h" +#include "cmemory.h" +#include "cstring.h" +#include "filestrm.h" +#include "toolutil.h" +#include "unewdata.h" +#include "uoptions.h" +#include "pkgtypes.h" +#include "makefile.h" + +static void +writeObjRules(UPKGOptions *o, FileStream *makefile, CharList **objects) +{ + const char *p, *baseName; + char tmp[1024]; + char stanza[1024]; + char cfile[1024]; + CharList *oTail = NULL; + CharList *infiles; + CharList *parents = NULL, *commands = NULL; + + infiles = o->filePaths; + + for(;infiles;infiles = infiles->next) { + baseName = findBasename(infiles->str); + p = uprv_strrchr(baseName, '.'); + if( (p == NULL) || (*p == '\0' ) ) { + continue; + } + + uprv_strncpy(tmp, baseName, p-baseName); + p++; + + uprv_strcpy(tmp+(p-1-baseName), "_"); /* to append */ + uprv_strcat(tmp, p); + uprv_strcat(tmp, "."); + uprv_strcat(tmp, STATIC_O); + + *objects = pkg_appendToList(*objects, &oTail, uprv_strdup(tmp)); + + /* write source list */ + strcpy(cfile,tmp); + strcpy(cfile+strlen(cfile)-strlen("." STATIC_O), ".c" ); + + + /* Make up parents.. */ + parents = pkg_appendToList(parents, NULL, uprv_strdup(infiles->str)); + + /* make up commands.. */ + sprintf(stanza, "$(INVOKE) $(GENCCODE) -n %s -d $(TEMP_DIR) $<", o->shortName); + commands = pkg_appendToList(commands, NULL, uprv_strdup(stanza)); + + sprintf(stanza, "$(COMPILE.c) -o $@ $(TEMP_DIR)/%s", cfile); + commands = pkg_appendToList(commands, NULL, uprv_strdup(stanza)); + + sprintf(stanza, "$(TEMP_DIR)/%s", tmp); + pkg_mak_writeStanza(makefile, o, stanza, parents, commands); + + pkg_deleteList(parents); + pkg_deleteList(commands); + parents = NULL; + commands = NULL; + } + +} + +void pkg_mode_static(UPKGOptions *o, FileStream *makefile, UErrorCode *status) +{ + char tmp[1024]; + CharList *tail = NULL; + CharList *objects = NULL; + + if(U_FAILURE(*status)) { + return; + } + + uprv_strcpy(tmp, LIB_PREFIX); + uprv_strcat(tmp, o->shortName); + uprv_strcat(tmp, UDATA_LIB_SUFFIX); + + o->outFiles = pkg_appendToList(o->outFiles, &tail, uprv_strdup(tmp)); + + if(o->nooutput || o->verbose) { + fprintf(stdout, "# Output file: %s%s%s\n", o->targetDir, U_FILE_SEP_STRING, tmp); + } + + if(o->nooutput) { + *status = U_ZERO_ERROR; + return; + } + + /* begin writing makefile ========================= */ + + + T_FileStream_writeLine(makefile, "# Version numbers:\nVERSIONED="); + if (o->version) { + sprintf(tmp, ".%s", o->version); + if (!uprv_strchr(o->version, '.')) { + uprv_strcat(tmp, ".0"); + } + T_FileStream_writeLine(makefile, tmp); + T_FileStream_writeLine(makefile, "\nDLL_LDFLAGS=$(LD_SONAME) $(RPATH_LDFLAGS)\n"); + } else { + T_FileStream_writeLine(makefile, "\nDLL_LDFLAGS=$(BIR_LDFLAGS)\n"); + } + T_FileStream_writeLine(makefile, "\n"); + + sprintf(tmp, "# File to make:\nTARGET=%s\n\n", o->outFiles->str); + T_FileStream_writeLine(makefile, tmp); + T_FileStream_writeLine(makefile, "LIB_TARGET=$(TARGET)\n" + "HEADER=$(TARGETDIR)/$(NAME).h\n"); + + + uprv_strcpy(tmp, "all: $(TARGETDIR)/$(LIB_TARGET) $(HEADER)"); + uprv_strcat(tmp, "\n\n"); + T_FileStream_writeLine(makefile, tmp); + + /* Write compile rules */ + writeObjRules(o, makefile, &objects); + + sprintf(tmp, "# List file for gencmn:\n" + "CMNLIST=%s%s%s_static.lst\n\n", + o->tmpDir, + U_FILE_SEP_STRING, + o->shortName); + T_FileStream_writeLine(makefile, tmp); + + if(o->hadStdin == FALSE) { /* shortcut */ + T_FileStream_writeLine(makefile, "$(CMNLIST): $(LISTFILES)\n" + "\tcat $(LISTFILES) > $(CMNLIST)\n\n"); + } else { + T_FileStream_writeLine(makefile, "$(CMNLIST): \n" + "\t@echo \"generating $@ (list of data files)\"\n" + "\t@-$(RMV) $@\n" + "\t@for file in $(DATAFILEPATHS); do \\\n" + "\t echo $$file >> $@; \\\n" + "\tdone;\n\n"); + } + + sprintf(tmp,"$(TEMP_DIR)/%s_dat.$(STATIC_O) : $(TEMP_DIR)/%s_dat.c\n" + "\t$(COMPILE.c) -o $@ $<\n\n", + o->shortName, + o->shortName); + T_FileStream_writeLine(makefile, tmp); + + T_FileStream_writeLine(makefile, "# 'TOCOBJ' contains C Table of Contents objects [if any]\n"); + + sprintf(tmp, "$(TEMP_DIR)/%s_dat.c: $(CMNLIST)\n" + "\t$(INVOKE) $(GENCMN) -e %s -n %s -S -d $(TEMP_DIR) 0 $(CMNLIST)\n\n", o->shortName, o->entryName, o->shortName); + T_FileStream_writeLine(makefile, tmp); + sprintf(tmp, "TOCOBJ= %s_dat%s \n\n", o->shortName,OBJ_SUFFIX); + T_FileStream_writeLine(makefile, tmp); + sprintf(tmp, "TOCSYM= %s_dat \n\n", o->entryName); /* entrypoint not always shortname! */ + T_FileStream_writeLine(makefile, tmp); + + T_FileStream_writeLine(makefile, "BASE_OBJECTS= $(TOCOBJ) $(NAME).$(STATIC_O) "); + + pkg_writeCharListWrap(makefile, objects, " ", " \\\n",0); + T_FileStream_writeLine(makefile, "\n\n"); + T_FileStream_writeLine(makefile, "OBJECTS=$(BASE_OBJECTS:%=$(TEMP_DIR)/%)\n\n"); + + T_FileStream_writeLine(makefile,"$(TEMP_DIR)/%.$(STATIC_O): $(TEMP_DIR)/%.c\n\t $(COMPILE.c) -o $@ $<\n\n"); + + T_FileStream_writeLine(makefile, "$(TARGETDIR)/$(LIB_TARGET):$(TARGETDIR)/$(LIB_TARGET)($(OBJECTS)) $(HPUX_JUNK_OBJ) $(LISTFILES)\n" + "\t$(RANLIB) $@\n\n"); + + + T_FileStream_writeLine(makefile, "CLEANFILES= $(CMNLIST) $(OBJECTS) $(HPUX_JUNK_OBJ) $(TARGETDIR)/$(LIB_TARGET) $(TARGETDIR)/$(MIDDLE_STATIC_LIB_TARGET) $(TARGETDIR)/$(TARGET)\n\nclean:\n\t-$(RMV) $(CLEANFILES) $(MAKEFILE)"); + T_FileStream_writeLine(makefile, "\n\n"); + + T_FileStream_writeLine(makefile, "# static mode shouldn't need to be installed, but we will install the header and static library for them.\n"); + + T_FileStream_writeLine(makefile, "install: $(TARGETDIR)/$(LIB_TARGET) $(HEADER)\n" + "\t$(INSTALL-L) $(TARGETDIR)/$(LIB_TARGET) $(INSTALLTO)/$(LIB_TARGET)\n" + "\t$(INSTALL_DATA) $(HEADER) $(INSTALLTO)/$(includedir)/unicode\n"); + if (o->version) { + T_FileStream_writeLine(makefile, "\tcd $(INSTALLTO) && $(RM) $(MIDDLE_STATIC_LIB_TARGET) && ln -s $(LIB_TARGET) $(MIDDLE_STATIC_LIB_TARGET)\n\tcd $(INSTALLTO) && $(RM) $(STATIC_LIB_TARGET) && ln -s $(LIB_TARGET) $(STATIC_LIB_TARGET)\n"); + } + T_FileStream_writeLine(makefile, "\n"); + T_FileStream_writeLine(makefile, "# We generate the following files from the Makefile, so that they don't get needlessly recompiled.\n"); + T_FileStream_writeLine(makefile, "\n"); + + T_FileStream_writeLine(makefile, "$(TARGETDIR)/$(NAME).h:\n" + "\techo '#include \"unicode/utypes.h\"' > $@\n" + "\techo >> $@\n" + "\techo '/* Call this function to install Application data */' >> $@\n" + "\techo \"U_CAPI void udata_install_$(NAME)(UErrorCode* err);\" >> $@\n\n"); + + T_FileStream_writeLine(makefile, "$(TARGETDIR)/$(NAME).c:\n" + "\techo '#include \"unicode/udata.h\"' > $@\n" + "\techo \"extern char $(NAME)_dat[];\" >> $@\n" + "\techo \"extern void udata_install_$(NAME)(UErrorCode* err){udata_setAppData(\"'\"'\"$(NAME)\"'\"'\", (const void*) $(NAME)_dat, err);}\" >> $@\n" + "\n"); + + *status = U_ZERO_ERROR; + +} + + +