Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a bare-bones ModelicaUtilities.h file only providing the ModelicaUtilities function declarations #4484

Open
casella opened this issue Oct 21, 2024 · 8 comments
Assignees
Milestone

Comments

@casella
Copy link
Contributor

casella commented Oct 21, 2024

In #3867 there was a discussion about whether ModelicaUtilities.h in the MSL was meant to be tool-specific, which ended up in the removal of that file from the MSL.

If I understand correctly, the key argument for that made by @henrikt-ma:

While it is fine for a library to need this file, each library should not contain the file. The file should be provided by the Modelica tool environment, which should provide a file corresponding to the currently active language version.

In my opinion, the file should be removed from the MSL to make this clear, and the issue should stay in this repository.

Unfortunately, this leaves the following scenario without a clear solution. Suppose that I am writing a library (not the MSL, whose binaries are compiled by each tool vendor) that is meant to be usable by multiple tools (ca va sans dire), uses external functions, and is released with pre-compiled binaries (DLL/shared libraries). When I am writing the C code of external functions that need to call ModelicaUtilities stuff, I need to #include "ModelicaUtilities.h" to actually compile the code.

The question is, where do I take that ModelicaUtilities.h file? Currently, I only see two feasible options:

  1. I take it a specific tool version from the tool's installation directory
  2. I write ModelicaUtilities.h myself, based on what I read in Section 12.9.6

Option 1. is obviously dangerous from a portability point of view: what guarantee do I have that the resulting binary libraries are compatible with all Modelica tools? In fact, I may not even be allowed to do that by licencing agreements.
Option 2. is straightforward, but it seems a bit odd that we are not providing those definitions arlready packaged in a ModelicaUtilitites.h file somewhere.

I think we should provide a version of ModelicaUtilities.h that only contains the function declarations (the interfaces / fingerprints), making it clear in the file header that this is not meant to be used by Modelica tools to manage their runtimes, but only to compile external functions in a tool-independent way.

Technically speaking, this is part of the Modelica Language Specification. I guess that putting it in the MSL makes sense, provided we explain clearly what the purpose is.

Keeping @fedetftpolimi in the loop.

@casella casella added this to the MSL4.1.0 milestone Oct 21, 2024
@casella casella self-assigned this Oct 21, 2024
@henrikt-ma
Copy link
Contributor

henrikt-ma commented Oct 21, 2024

One way to deal with the dependency on the MLS version would be to include some sort of assert that will fail unless a (MODELICA_LANGUAGE_MAJOR, MODELICA_LANGUAGE_MINOR) tuple has been set to values matching exactly what is in the ModelicaUtilities.h. I don't know exactly how to do this in a C header, but expect that there will be some way…

If we solve that part, we "only" need to agree upon what a correct content of ModelicaUtilities.h should look like. Once agreed, we should stop thinking of this file as a tool-specific file, and it should be expected (and probably even defined in the specification) that the file as provided by one tool should work with any other tool.

At this point, I don't see why there should be any differences at all between tools, and it would be natural to include the file with every library, including ModelicaServices. The file included with ModelicaServices would then naturally become the de-facto standard file for tools makers and library authors to copy into their products.

@henrikt-ma
Copy link
Contributor

Option 1. is obviously dangerous from a portability point of view: what guarantee do I have that the resulting binary libraries are compatible with all Modelica tools? In fact, I may not even be allowed to do that by licencing agreements.

The central question here is why any tool would depend on ModelicaUtilities.h content that would not work with different tools?

@beutlich
Copy link
Member

In #3867 we agreed that ModelicaUtilities.h is tool-specific, right? In that case it is no more applicable to compile external objects/functions with one tool-specific ModelicaUtilities.h and re-use the binary in different simulation tools.

I also consider the removal of ModelicaUtilities.h as a breaking change in the sense that it should force a v5.0.0 instead of v4.1.0.

@beutlich
Copy link
Member

The central question here is why any tool would depend on ModelicaUtilities.h content that would not work with different tools?

One scenario is that tools might not yet fully support all utility functions of MLS 3.6, i.e. the later introduced functions ModelicaWarning or ModelicaDuplicateString.

@fedetftpolimi
Copy link

Making ModelicaUtilities.h tool-specific is a massive pain for library developers, if that decision was made I strongly suggest it should be un-done asap.

Case in point, https://github.com/modelica-3rdparty/ExternalMedia
It is a library that is distributed with pre-built shared objects for Windows, Linux and Mac. We currently link those shared objects against a ModelicaUtilities.h that I think is an old version of the one provided with the MSL: https://github.com/modelica-3rdparty/ExternalMedia/blob/master/Projects/Sources/ModelicaUtilities.h

It would be unreasonable to have to recompile and distribute ExternalMedia with a different ModelicaUtilities.h for every OS and tool combination, also considering that:

  1. making ModelicaUtilities.h tool-specific means tool vendors are free to alter its content at will from one tool release to the other, what should ExternalMedia do, keep track of those changes and compile a different version of the shared library for every OS and tool and tool version?
  2. new tool vendors could enter the market, what should ExternalMedia do, keep track of all Modelica tool vendors?

Unless ModelicaUtilities.h is standardized, the external functions interface is essentially broken and portability basically works "by chance" relying on undefined behavior. This needs to change.

@fedetftpolimi
Copy link

A tool that does not yet support all utility functions can provide the missing ones as stubs printing a message to the user "This feature is currently unsupported" or similar.

beutlich added a commit to beutlich/ModelicaStandardLibrary that referenced this issue Oct 21, 2024
Revert "refs modelica#3867: Remove LICENSE_ModelicaUtilities.txt"

This reverts commit 7fe506f.

Revert "refs modelica#3867: Remove ModelicaUtilities.h"

This reverts commit 1bb1d40.
beutlich added a commit to beutlich/ModelicaStandardLibrary that referenced this issue Oct 21, 2024
Revert "refs modelica#3867: Remove LICENSE_ModelicaUtilities.txt"

This reverts commit 7fe506f.

Revert "refs modelica#3867: Remove ModelicaUtilities.h"

This reverts commit 1bb1d40.
beutlich added a commit to beutlich/ModelicaStandardLibrary that referenced this issue Oct 21, 2024
Revert "refs modelica#3867: Remove LICENSE_ModelicaUtilities.txt"

This reverts commit 7fe506f.

Revert "refs modelica#3867: Remove ModelicaUtilities.h"

This reverts commit 1bb1d40.
@beutlich
Copy link
Member

I am also in favour of reverting #3871 for MSL v4.1.0 and provided a (draft) PR in #4487.

@casella
Copy link
Contributor Author

casella commented Oct 21, 2024

The central question here is why any tool would depend on ModelicaUtilities.h content that would not work with different tools?

Excerpt from OpenModelica's ModelicaUtilities.h:

void ModelicaFormatMessage(const char *string, ...) MODELICA_FORMATATTR_PRINTF;
/*
Output the message under the same format control as the C-function printf.
*/

void ModelicaVFormatMessage(const char *string, va_list args) MODELICA_FORMATATTR_VPRINTF;
/*
Output the message under the same format control as the C-function vprintf.
*/

MODELICA_NORETURN void ModelicaError(const char *string) MODELICA_NORETURNATTR;
/*
Output the error message string (no format control). This function
never returns to the calling function, but handles the error
similarly to an assert in the Modelica code.
*/

Excerpt from Dymola's ModelicaUtilities.h:

DYMOLA_STATIC void ModelicaFormatMessage(const char *string, ...) MODELICA_FORMATATTR_PRINTF;
/*
Output the message under the same format control as the C-function printf.
*/

DYMOLA_STATIC void ModelicaVFormatMessage(const char *string, va_list args) MODELICA_FORMATATTR_VPRINTF;
/*
Output the message under the same format control as the C-function vprintf.
*/

MODELICA_NORETURN DYMOLA_STATIC void ModelicaError(const char *string) MODELICA_NORETURNATTR;
/*
Output the error message string (no format control). This function
never returns to the calling function, but handles the error
similarly to an assert in the Modelica code.
*/

As I understand (I'm not the expert here, I might be wrong), the tool-specific macros are needed when compiling the simulation executable with a given tool, which is OK.

However, if I am writing a library with external functions that needs to call such utility functions, I obviously don't want to use any such tool-specific .h file in its source code, because it may not work with other tools. I just need a Modelica.Utilities.h header that contains the headers as described in the MLS Section 12.9.6:

void ModelicaMessage (const char* string);
void ModelicaWarning (const char* string);
void ModelicaError(const char* string);
void ModelicaFormatMessage (const char* format , ...);
void ModelicaFormatWarning (const char* format , ...);
void ModelicaFormatError (const char* format , ...);
void ModelicaVFormatMessage (const char* format , va_list ap);
void ModelicaVFormatWarning (const char* format , va_list ap);
void ModelicaVFormatError (const char* format , va_list ap);
char* ModelicaAllocateString (size_t len);
char* ModelicaAllocateStringWithErrorReturn (size_t len);
char* ModelicaDuplicateString (const char* str );
char* ModelicaDuplicateStringWithErrorReturn (const char* str );

That's the public interface of those functions defined by the MLS, so if I use this for my external functions, I expect them to work in all tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants