lingua-franca
lingua-franca copied to clipboard
Specifying libraries to link is too difficult
A common use case is that an imported LF reactor requires an external library, such as the math library in C. Unfortunately, we currently have no good way for the imported file to be self contained and specify this requirement. Moreover, the preferred way we have currently requires that the user of the imported file create a math-include.cmake
file with this:
target_link_libraries( ${LF_MAIN_TARGET} m )
and then specify a target property:
cmake-include: "math-include.cmake”
Alternatively, if the user is using gcc or clang, then just the following target property will work:
flags: "-lm"
This falls pretty low on the usability scale.
I suggest a new target property, something like:
link-libraries: ["m"]
This could be a list of required libraries. This would be put in the imported file and would need to be translated into the appropriate lines in the generated cmake file or into compiler flags if not. If multiple imported files specify the same libraries, these would be consolidated.
Other (better) ideas?
link-libraries: ["m"]
sounds like a good solution to me.
However, we would still have the issue of imported .lf files not being self-contained because link-libraries
of imported files could potentially conflict with each other. As @cmnrd pointed out, I think we would still need the ability to separately compile imported .lf files into libraries and linking them together in order to have properly self-contained imported .lf files.
The proposed solution oversimplifies the problem and only works for C standard libraries (like math). Linking to libraries in C/C++ is complicated and messy, and there is no way around it (unfortunately).
Let's say we have a library foo
and want to link to it. It is not as simple as adding -lfoo
to the flags. We need to know: Where is foo
located? Are there dependent libraries? Do we need to add headers to the include path? Are there any macros that need to be defined? These are just the most important questions. Cmake provides various mechanisms to answer these questions specifically for the host system and to adjusts compiler flags accordingly. However, cmake still does not provide us with a standardized way for importing a library. How to find and link to libraries completely depends on the tools used and design decisions made by the library developer. In most cases, the cmake code for importing the library needs to be written specifically for this library and cannot (easily) be auto generated.
The cmake-include property is the most general solution that I can think of. And it shouldn't be difficult to use for C/C++ programmers. I completely understand the drive to provide a simpler mechanism, but this mechanism will either be very limited in functionality or overly complicated (i.e. a self-written C/C++ package manager).
If you ant to go with this property, I would suggest to rename it to link-standard-libraries
to reflect that it only works for standard libraries. Otherwise, we will have users wondering why they get weird compile errors when they try link-libraries: foo
.
If we are to go with a cmake solution instead, then we need to find a way to safely integrate cmake-include files specified in imported reactors.
I agree. A cheap but effective solution would be to just collect all cmake-include
s specified in all imported lf files and merge the list. This will not work correctly in all corner case, but it should work for most examples that we are currently considering.
As I outlined in my e-Mail, the "full" solution would be to compile each *.lf file as a library. Then we would only need to consider the build properties given for this specific *.lf file, and cmake could take care of all the rest for us when linking the resulting binary. For C++ this should be a relatively minor change, but for C it is a longer way, as we would first need to redesign the code generator to produce individual source and header files.
Actually, since the C generator puts all reactors in a single file, merging all the cmake-include
files is precisely the behavior we want. The resulting C file needs to be compiled with all the flags and libraries specified for any of the used reactors. If there are any problems resulting from merging these merged properties (for instance because of name conflicts between libraries), then we currently don't have a mechanism to work around this in C anyway.
Note that this technique will likely not work for extended reactors. This may be an issue when Cpp implements extends.
I agree with @cmnrd that if we have this feature it's scope should be limited to standard libraries. Maybe link-standard-libraries
is a bit long; I'd also be fine with link-std-libs
, but link-libraries
is too broad and will cause confusion.
I don't really understand this objection. When used with nonstandard libraries, it probably will not be in a context of something that is likely to be widely reused on multiple platforms, unlike the math library.
You might be right. But even if we call it link-libraries
, I'd like to make sure we can properly handle all standard libraries on all platforms before adding this feature just to handle math.h
.
@edwardalee Could you elaborate why you think there might be problems with extended reactors? As far as I can see, there should be no problems. A class defined in one library can easily extend a class defined in another one.
I don't really understand this objection. When used with nonstandard libraries, it probably will not be in a context of something that is likely to be widely reused on multiple platforms, unlike the math library.
There are many non-standarad libraries (as in: not part of the C standard) that are used cross-platform. However, even if an LF program is written specifically for Linux and uses Linux-only libraries, the name suggests that link-libraries
could just import and use those libraries, which will not work in many cases.