| <html><head> | |
| <meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"> | |
| </head> | |
| <body> | |
| <h1>Compiler and Other Technical Issues in the Mac OS X 10.0.x Platform</h1> | |
| <br> | |
| <p> Several compiler and operating system issues were encountered during the portingof | |
| the Abstraction and Infrastructure Layers of OpenOffice.org. They are described | |
| below for your reference. They pertain to Mac OS X 10.0.x and Mac OS X 10.0.x Developer Tools | |
| 10.0.x. The solutions discussed in this document are current as of the OO638C | |
| release tag and are specifically coded for the Mac OS X 10.0.x platform only. Hence, | |
| when implementing the solutions discussed in this document, you need to enclose | |
| any corrective code within the following preprocessor statements:</p> | |
| <blockquote> | |
| <pre>#ifdef MACOSX | |
| ... | |
| #endif</pre> | |
| <pre>#if defined(__GNUC__) && defined(__APPLE__) | |
| ... | |
| #endif<b></b></pre> | |
| </blockquote> | |
| <b> | |
| <h2>Static data members in template classes</h2> | |
| </b> | |
| <p></p> | |
| <p>As the Mac OS X 10.0.x C++ compiler behaves somewhat differently from GCC compilers | |
| for other platforms, the static datat members in template classes, if not explicitly | |
| initialized, will cause undefined symbols at link time. For example: | |
| <pre> | |
| template <abc> | |
| class ImplHelper: public ImplHelperBase<abc> | |
| { | |
| static ClassData s_aCD; | |
| ... | |
| } | |
| </pre> | |
| <p>Each instantiation of s_aCD needs to be explicitly initialized once and only | |
| once somewhere. Note that it can only be instantiated once or you will get duplicate | |
| symbol errors that will crash an executable at runtime. So a mechanism (solenv/unxmacxp/bin/init-static-template-data) | |
| was created to automatically detect and collect these static members into a | |
| set of files and initialized them. One set of files is created for each source | |
| directory. For example, the following files are created for the source directory | |
| in the cppuhelper module: </p> | |
| <ul> | |
| <li>cppuhelpercppuhelperstaticdatamembers.h | |
| <li>cppuhelpercppuhelperstaticdatamembers.hxx | |
| <li>cppuhelpercppuhelperstaticdatamembers.cxx | |
| </ul> | |
| <p>Then, immediately before an executable or shared library is linked, the standard | |
| build recipes merge the above files with the same files from all of the other | |
| source directories that have been built to create an aggregate list of static | |
| data members that require initialization. These merged files are then compiled | |
| and linked into a shared library called libstaticmxp.dylib. Since all executables | |
| and shared libraries generated by the Mac OS X 10.0.x build are linked to the library, | |
| all executables are guaranteed to have each required static data member initialized | |
| once and only once.</p> | |
| <p> As of the OO638C release tag, only the following template classes are | |
| supported by this mechanism: | |
| <ul> | |
| <li>vos::ODynamicLoader | |
| <li>cppu::*ImplHelper[0-9]* | |
| <li>com::sun::star::uno::Sequence | |
| <li>comphelper::OPropertyArrayUsageHelper | |
| <li>comphelper::OIdPropertyArrayUsageHelper | |
| </ul> | |
| Should any new static data members be found in template classes, you will need | |
| to implement support for these new static data members in the following script: | |
| <ul> | |
| <li>$SRC_ROOT/solenv/unxmacxp/bin/init-static-template-data | |
| </ul> | |
| <br> | |
| <h2>Static automatic variables in inline functions</h2> | |
| <p>Each time an inline function is inlined, a static automatic variable's definition | |
| is generated once. So we usually end up having multiple copies of these variable | |
| definitions. The compiler may or may not generate a warning about this. However, | |
| the assembler will generate error messages like the following: </p> | |
| <pre> | |
| {standard input}:unknown:Can't emit reloc {- symbol "L37$pb"} @ file address 36. | |
| {standard input}:unknown:Can't emit reloc {- symbol "L37$pb"} @ file address 32. | |
| </pre> | |
| <p>To solve this problem, you must either move the static automatic variable in | |
| an inline function to outside of the function (i.e. make it a file scope variable) | |
| or reimplement the inline function so that a static automatic variable is no | |
| longer used.</p> | |
| <p>For examples of how to implement the first option, take a look at any of the | |
| *.hpp files that are generated by the build.</p> | |
| <p> | |
| <b> | |
| <h2>Static automatic variables in C++ class destructors</h2> | |
| </b> | |
| <p></p> | |
| <p>In certain situations, when the following 2 conditions exist: | |
| <ul> | |
| <li>A C++ class destructor contains a static automatic variable or calls a method | |
| or function that contains a static automatic variable | |
| <li>The static variable is a C++ class | |
| </ul> | |
| The virtual methods of the static variable will be treated as non-virtual. As | |
| a result, the incorrect code may be called. This can be illustrated by the following | |
| sample code. | |
| <p></p> | |
| <pre> | |
| #include <stdio.h> | |
| // Create a class with a pure virtual method | |
| class MyAbstractClass | |
| { | |
| public: | |
| virtual void print() = 0; | |
| protected: | |
| MyAbstractClass() { } | |
| virtual ~MyAbstractClass() { } | |
| }; | |
| // Create a subclass of the class with a pure virtual method | |
| class MyConcreteClass : public MyAbstractClass | |
| { | |
| public: | |
| MyConcreteClass() { } | |
| virtual ~MyConcreteClass() { } | |
| virtual void print() { printf( "In MyConcreteClass\n" ); } | |
| }; | |
| // Create a class that invokes the subclasses method in it's destructor | |
| class MyWrapperClass | |
| { | |
| public: | |
| MyWrapperClass() { } | |
| ~MyWrapperClass(); | |
| static MyAbstractClass getClass(); | |
| }; | |
| MyAbstractClass MyWrapperClass::getClass() | |
| { | |
| static MyConcreteClass rClass; | |
| return rClass; | |
| } | |
| MyWrapperClass::~MyWrapperClass() | |
| { | |
| MyAbstractClass& aClass = getClass(); | |
| aClass.print(); | |
| } | |
| // Create problem where the MyWrapperClass' destructor accidentally invokes | |
| // the base class' print method instead of the subclass' print method. | |
| MyWrapperClass aClass; | |
| int main( int argc, char **argv ) | |
| { | |
| MyWrapperClass bClass; | |
| } | |
| </pre> | |
| <p>When this sample program is executed, the program generates the following output:</p> | |
| <pre> | |
| In MyConcreteClass | |
| pure virtual method called | |
| Abort | |
| </pre> | |
| <p>instead of the expected output: | |
| <pre> | |
| In MyConcreteClass | |
| In MyConcreteClass | |
| </pre> | |
| <p>To solve this problem, you must either move the static automatic variable in | |
| an inline function to outside of the function (i.e. make it a file scope variable) | |
| or reimplement the inline function so that a static automatic variable is no | |
| longer used.</p> | |
| <p>In the above example, we would change the following lines: | |
| <pre> | |
| MyAbstractClass MyWrapperClass::getClass() | |
| { | |
| static MyConcreteClass rClass; | |
| return rClass; | |
| } | |
| </pre> | |
| to: | |
| <pre> | |
| static MyConcreteClass rClass; | |
| MyAbstractClass MyWrapperClass::getClass() | |
| { | |
| return rClass; | |
| } | |
| </pre> | |
| <br><br> | |
| <b> | |
| <h2>Optimization bugs when exceptions are turned on</h2> | |
| </b> | |
| <p></p> | |
| <p>When -fexceptions and optimization flags (e.g. -O or -O<i>n</i>) are both turned | |
| on while compiling a source file, the runtime code execution can be very unpredictable. | |
| The exact cause of this compiler bug is unknown. The solution is to turn off | |
| optimization whenever the -fexception flag is set (i.e. when either the ENABLE_EXCEPTIONS | |
| or EXCEPTIONSFILES macros are set in a makefile.mk file). </p> | |
| <p>As of the OO638C release tag, the standard build recipes will automatically | |
| turn off optimization whenever exceptions are turned on. </p> | |
| <br> | |
| <h2>Duplicate symbol bug in the dynamic library loader</h2> | |
| <p>When loading two different modules/functions with the same symbol name from | |
| two different libraries, the Mac OS X 10.0.x dynamic loader resolves to the symbol | |
| of the library first loaded even though we wanted two different versions from | |
| the two different libraries. In addition, there is no way to unload a library | |
| once it is loaded, so we can not unload the first and then load the second. | |
| This bug renders OpenOffice.org's UNO plugin technology unusable since the UNO | |
| plugin technology needs each UNO shared library to implement the following standard | |
| functions: </p> | |
| <ul> | |
| <li>component_writeInfo() | |
| <li>component_getFactory() | |
| <li>component_getFactory() | |
| <li>component_getDescriptionFunc() | |
| <li>component_getDescriptionFunc() | |
| <li>uno_initEnvironment() | |
| <li>uno_ext_getMapping() | |
| </ul> | |
| <p>The solution is to prepend "lib(library name)" onto each of these standard | |
| functions so that each UNO shared library's standard functions are uniquely | |
| name. Then, at runtime, the library loading functions implemented in the sal/osl/unx/module.c | |
| source file will automatically prepend the library name to the requested function | |
| before retrieving a pointer to the function from the library. </p> | |
| <p>For this solution to work, developers must implement the following after porting | |
| a module: </p> | |
| <ol> | |
| <li>Determine if any of the above standard functions exist in any of the shared | |
| libraries built in the module. Note that the functions may already contain | |
| an incorrect "lib(some text)" prefix. These functions need to be included | |
| in the next step. | |
| <li>For each standard function that does exist in the shared libraries build | |
| in the module, determine which source file implements the function. | |
| <li>In the makefile.mk file in each of the directories that contains a source | |
| file that implements one or more of the standard functions, add the following | |
| macro definition: | |
| <pre> | |
| .IF "$(OS)"=="MACOSX" | |
| SYMBOLPREFIX=(library name) | |
| .ENDIF | |
| </pre> | |
| In the above macro definition, substitute "(library name)" with portion of | |
| the shared library name after stripping off the leading "lib" and trailing | |
| ".dylib". For example, if the shared library name is libi18n625mxp.dylib, | |
| "(library name)" should be replaced with "i18n625mxp". | |
| <li>Perform a clean build of the module using "dmake -u" to verify that standard | |
| functions have been correctly renamed. | |
| </ol> | |
| <p>The SYMBOLPREFIX macro is used by the build to create "-D" options for the | |
| compiler. These defines are used to rename the standard functions. For a list | |
| of these "-D" options that the SYMBOLPREFIX macro affects, take a look at the | |
| following file: </p> | |
| <ul> | |
| <li>$SRC_ROOT/solenv/inc/unxmacxp.mk | |
| </ul> | |
| <p> | |
| <b> | |
| <h2>Bugs in tempnam() and mktemp() system functions</h2> | |
| </b> | |
| <p></p> | |
| <p>In Mac OS X 10.0.x, multiple invocations of either the tempnam() or mktemp() | |
| system functions will return the same filename. On other platforms, these functions | |
| generate a unique filename with each invocation. This Mac OS X 10.0.x bug will cause | |
| unpredictable results at runtime. </p> | |
| <p>The solution is to use the tmpnam() function instead of the tempnam() function | |
| and to use the mkstemp() function instead of the mktemp() function. Both tmpnam() | |
| and mkstemp() return a unique filename with each invocation. Note that since | |
| the default behavior for both tmpnam() and mkstemp() is to create their files | |
| in the /var/tmp directory, you need to make sure that the /var/tmp directory | |
| is readable and writable by all users. The Mac OS X 10.0.x installation | |
| program, /var/tmp is set to be readable and writable only by root.</p> | |
| <p> | |
| <b> | |
| <h2>Special packaging requirements for shared libraries</h2> | |
| </b> | |
| <p></p> | |
| <p>Most Unix platforms use ".so" as the suffix for shared libraries. However, | |
| the Mac OS X 10.0.x linker expects ".dylib" as the suffix for shared libraries. </p> | |
| <p>In addition, the library loading functions in the CoreFoundation framework | |
| expect that a shared library be "bundled" within the a libname.dylib.framework | |
| directory. For example, "libmyshared.dylib" needs to be put into a directory | |
| named "libmyshared.dylib.framework". </p> | |
| <p>Lastly, the Java call System.loadLibrary expects ".jnilib" as the suffix for | |
| shared libraries. </p> | |
| <p>As of the OO638C release tag, the standard build recipes will automatically | |
| create the matching lib*.dylib.framework/lib*.dylib and lib*.jnilib files for | |
| each lib*.dylib file that is linked. However, developers need to be aware that | |
| the source code may use ".so" in the shared library name. In such cases, developers | |
| should modify the code to use ".dylib.framework" in the shared library name | |
| for Mac OS X 10.0.x. </p> | |
| </body> | |
| </html> | |