Skip to content

Latest commit

 

History

History
209 lines (140 loc) · 15.6 KB

3___packaging.adoc

File metadata and controls

209 lines (140 loc) · 15.6 KB

Packaging and Code Generation/Loading

ZIP Archive Structure

Pathnames and Prefixes

Exporting implementations should ensure that the generated FMU ZIP archives are compliant with the ZIP specification. This implies that only the forward slash / shall be used as a path separator and that path specifications like . or .. do not have specific interpretations, like the current directory, etc.

More specifically, the ZIP archive should only contain entries with no leading prefix: For example, valid entries would be modelDescription.xml or binaries/x86_64-windows/myfmu.dll, not ./modelDescription.xml, or myfmu/binaries/x86_64-windows/myfmu.dll.

To enable interoperation with not-quite conforming implementations, importing implementations should be prepared to support the extraction of FMU ZIP archives with leading ./ prefixes on entries in the archive. Similarly, implementations should be prepared to support the extraction of FMU ZIP archives that use "\" as the path separator.

Access to FMU package content

The exporting implementation should not rely on the importing implementation completely unpacking the FMU in one location. The standard only specifies access to the resources folder.

Some of the fallbacks (discussed in Handling of Code Dependencies and [Instantiation]) for locating the resources folder relative to the executing DLL/shared object rely on the structure being completely recreated. However, these fallbacks are, by their nature non-portable mechanisms, that only come into play when other, standard-conforming mechanisms are not available.

When possible, implementations should unpack the complete ZIP archive content in one location since some FMUs depend on this even if the standard only specifies access to the resources folder.

Note that FMI 3.0 provides access to the resource folder using a native path, whereas FMI 1.0 and FMI 2.0 specify a URI to the resource folder that still needs to be translated to a system path for access.

Documentation and Additional Resources

Icons

Implementations should support using supplied icon information in the FMU when displaying the FMU in a graphical notation or user interface.

For FMI 3.0, icon information is available as part of the ports and icons information contained in the icons/terminalsAndIcons.xml file of the FMU. This optionally includes detailed icon information for individual ports, as well as global icon information.

For prior versions of FMI, only a model.png file in PNG format in the root of the ZIP archive is available.

Exporting implementations should, at a minimum, generate an informative icon for the FMU and package this in the ZIP archive in the way documented in the FMI standards. Whenever possible, more detailed information should be provided using the ports and icons information.

Meta Data

Exporting implementations should make use of the standard meta data attributes FMI provides in the root element of the modelDescription.xml:

  • description
    A user-readable description of the FMU/model at a suitable level of detail for a short overview. Note that additional information can be provided in the Documentation.

  • author
    Author information should ideally include organization and contact information, e.g. in the [RFC5322] name-addr format:
    Example User <[email protected]>
    Note that privacy regulations might necessitate the use of author information that is not personally identifiable, e.g. company or department names and addresses instead of individual users.

  • version
    This field provides a version for the FMU/model, which is not to be confused with the FMI version field fmiVersion.

  • copyright
    Copyright information in a suitably short form. Note that additional information can be provided in the Documentation.

  • license
    License information in a suitably short form. Note that additional information can be provided in the Documentation.

  • generationTool
    Description, including version number, on the tool generating the FMU.

  • generationDateAndTime
    Date and time when the FMU was generated. Note the specific [ISO8601-1]-derived format required here, and the prescribed use of UTC (Zulu time zone):
    2009-12-08T14:33:22Z

While some of the fields can be filled in a fully automated fashion, for most user input is needed. Generally the information to be included in generated FMUs should be fully under user control.

Importing implementations should make the meta data found in imported FMUs available to the user for inspection.

Note that not all of the meta data fields are available in FMI 1.0.

Documentation

The documentation folder of FMUs provides a specific way to ensure that important documentation needed to use FMUs effectively always travel with the FMU. Implementations should therefore allow easy access to any documentation supplied in the FMU.

Exporting implementations should allow the user to easily author/add documentation for the FMU.

Exporting implementations should also include any additional documentation needed to effectively run the FMU in the documentation:

  • Implementations which export FMUs that are not considered stand-alone, i.e., specifying needsExecutionTool=true in their model description, should provide sufficient information inside the documentation so that the recipient of the FMU will know what tools, licenses, and other dependencies are needed to run the FMU.

  • Implementations which export FMUs that require runtime licenses should provide information on what kind of license is needed and how to provide this license so the FMU can use it.

In many instances, for example, when open-source licenses are employed, license information and other additional information is needed to be shipped with an FMU for distribution. In these cases, exporting implementations should allow the user to easily add information items, like licenses, to the documentation shipped with an FMU.

Where the license information is required by the exporting implementation itself, it can directly add this information to the FMU itself.

This support by an implementation should not be understood to remove the need for the user to ensure that they are in compliance with relevant licenses and their legal obligations.

Support for 32&64bit Variants of Platforms

Common platforms in use today are available in 32bit and 64bit variants, for example Windows or Linux on Intel processors, or Linux ARM processors.

While these variants are usually closely related, and 64bit variants commonly support running 32bit and 64bit binaries side-by-side, this support is limited: Most platforms do not support running 32bit and 64bit inside one process image, but only in separate processes.

Since FMI is designed around the ability to run FMUs inside the host implementation process image for efficiency, this means that 32bit and 64bit variants of the same platform are usually not directly compatible.

For this reason exporting implementations should ideally generate FMUs that contain both 32bit and 64bit variants of the binaries, allowing importers to select an appropriate binary.

Since not all exporting implementations can generate both variants easily, importing implementations should consider providing the ability to bridge between 32bit and 64bit implementations, using either inter-process communication or system provided facilities where possible.

Going forward, this is likely to be less of a problem on desktop systems, which are migrating to 64bit only implementation spaces. For mobile or embedded platforms, this issue is likely to be still pertinent for some time.

Support for Multiple Platforms

FMU exporting implementations should strive to support common platforms out of the box. They should provide support for generating FMUs that contain multiple binary implementations, and where feasible, a source code implementation in one go.

Compiler Dependencies

Exporting implementations should document supported compilers, their versions, and required compiler flags and settings to compile generated source FMUs for common platforms.

For FMI 3.0, the languages, compilers and required compiler flags and settings should be placed in the buildDescription.xml file of the FMU to allow automated building from source as far as possible. The following are lists of commonly agreed upon names for languages and compilers, that should be used if no other values are more appropriate:

Languages
C90

ISO/IEC 9899:1990, which is technically identical to ANSI X3.159-1989 (sometimes termed C89)

C95

ISO/IEC 9899:1990/AMD1:1995, i.e. ISO/IEC 9899:1990 as ammended by Ammendment 1, including wide characters, digraphs, and standard macro STDC_VERSION

C99

ISO/IEC 9899:1999

C11

ISO/IEC 9899:2011

C17

ISO/IEC 9899:2018

C++98

ISO/IEC 14882:1998

C++03

ISO/IEC 14882:2003

C++11

ISO/IEC 14882:2011

C++14

ISO/IEC 14882:2014

C++17

ISO/IEC 14882:2017

C++20

ISO/IEC 14882:2020

Compilers
VisualC

Microsoft Visual Studio C/C++ compiler

gcc

GNU Compiler Collection (gcc) C/C++ compiler

clang

CLANG LLVM-based C/C++ compiler

When generating binary FMUs directly, the supported and used compilers, compiler flags, and settings should also be documented. This allows users to troubleshoot integration issues when integrating binary FMUs into other environments.

Where possible, user-supplied compilers, compiler flags, and settings should be supported to automate the generation of binary FMUs for non-common targets or to support user-specific requirements in the binary FMU compilation/linking stage.

Handling of FMU namespaces

Importing implementations should correctly handle the import of multiple FMI 1.0 FMUs with identical model identifiers. In the case of FMUs with dynamic library implementations, this is supported by most platforms since symbol lookup can be performed scoped to one dynamic library namespace (see, for example, the dlsym and GetProcAddr functions for Linux and Windows, respectively).

Starting with FMI 2.0, FMUs with dynamic library implementations will always use identical symbols for the entry points in any case, so that this has to be supported correctly.

For source code or static library implementations, the problem of conflicting model identifiers can usually only be solved through compilation/linking to corresponding separate dynamic libraries or other similar mechanisms to deal with the relevant scoping issues.

For source code FMUs in FMI 3.0, the actual prefix that is used for the entry points is controlled through the mechanisms of the fmi3Functions.h header in the following way:

  • The source code of the FMU predefines the FMI3_FUNCTION_PREFIX preprocessor macro with the function prefix that matches the modelIdentifier attribute given in the modelDescription.xml. This is done before including the fmi3Functions.h header.

  • If the fmi3Functions.h header supplied with the standard is used for compilation, then this predefined prefix will be used as the function prefix, unless the FMI3_OVERRIDE_FUNCTION_PREFIX preprocessor macro is defined. If this macro is defined, then the actual function prefix will be taken from the preprocessor macro FMI3_ACTUAL_FUNCTION_PREFIX, if it is defined, or no prefix will be used, if it is undefined.

  • If an importing implementation requires something different, it can provide a fmi3Functions.h header file that does whatever the implementation requires, ignoring or using the predefined FMI3_FUNCTION_PREFIX macro as it sees fit.

As the actual function symbols generated for an FMU are dependent on the implementation and its supplied fmi3Functions.h header any any other predefined preprocessor macros, FMU exporters must ensure that they only refer to the FMI API entry-points via the names generated from the fmi3Functions.h mechanisms. In other words, any references in the exported source code should be amenable to preprocessor expansion.

For FMI 2.0 source code FMUs a similar approach can be used, however there are fewer guarantees on pre-defined preprocessor macros, since this area was only clarified in later patch releases of 2.0.

Handling of Code Dependencies

Importing implementations should consider changing the working directory of the process to the relevant binary subdirectory of the unpacked FMU when loading the FMU dynamic library. This is to allow unsophisticated exporting implementations to load dependent dynamic libraries relative to this directory. It is, of course, the responsibility of the FMU to implement proper dependent dynamic library loading regardless of the current working directory of the process. However, in practice, a number of current or former implementations did not correctly implement this. They can thus fail to load when the current directory is not the directory that contains the FMU dynamic library.

Exporting implementations should ideally avoid reliance on additional dynamic libraries: Generated dynamic libraries should ideally be stand-alone.

Where this is not feasible, implementations should prefer to use manual dynamic loading of dependent libraries at runtime (for example, using dlopen or LoadLibrary). The load path of the libraries should be based on the path to the resources folder provided. When the resources path is not available (for example, in FMI 1.0 ME) or not valid, an implementation can use dynamic library-relative path derivation, either against the binary folder or the resources folder.

Relying on pre-linking, where the dynamic loading of the dependent libraries is automatically handled by the platform dynamic linker/loader, is not likely to work in all cases: For example, on Windows, the searched paths will be based on the location of the importer executable, not the location of the FMU DLL. Furthermore, in case of failure, automatic linking is unlikely to provide user-understandable error messages.

Note that simple calls to LoadLibrary or LoadLibraryEx on Windows, without specifying the full path to the library are also not going to work in general, for the same reasons: The search path will be based on the location of the importer executable and not the FMU DLL.

Importers should consider using flags like RTLD_LOCAL on POSIX platforms with dlopen, to avoid symbols from loaded shared objects being resolved against other loaded shared objects (i.e. other FMUs) by accident.

Note that for POSIX platforms, like Linux, dlclose is not required to unload a shared object, but it can, as specified in IEEE Std 1003.1-2017 (and earlier). In particular, shared objects compiled with GCC without the flag -fno-gnu-unique, can be marked as unloadable, and thus will not generally be unloaded upon dlclose. In many instances shared objects loaded with RTLD_GLOBAL cannot unload until all relocations of other objects to symbols in the shared object have been unloaded.

Interaction between FMU and Importer

The FMU code will run in the process environment that the importer provides. This might be the same process as the importer, or it might be a separate process or processes. The FMU code cannot make any assumptions on this, but must rather be conservative in its behavior in the face of this.

Global State

The functions the FMU provides must not change global settings which affect the overall process and/or thread environment:

For example, an FMU function must not change the current working directory of the process, since this is by definition visible outside of the current execution thread.

FMU funtions can, on the other hand, change the floating point control word of the CPU during their execution, since this is directly tied to the thread of execution. However they must restore the floating point control word before returning, so as to not affect state outside of the current thread of execution.