[MLton] MLton import headers

Wesley W. Terpstra wesley at terpstra.ca
Fri Oct 3 06:04:22 PDT 2008


On Fri, Oct 3, 2008 at 10:01 AM, Vesa Karvonen > In C and C++, and
particularly on Windows, one often uses macros in
> library headers and source files to insert appropriate compiler
> specific declarations to mark symbols ...

Yes, this is what MLton/svn does in the generated C import header.
However, in some cases a programmer still needs to specify how he
links a library. The MLton import headers do this with a macro:

#define STATIC_LINK_FOOBAR
#include <foobar.h>

> One thing that comes to mind from this is that it would be nice to be
> able to switch between static and dynamic linking easily without using
> a complicated mechanism at the source level. In fact, I think that
> ideally code that uses a library should really be exactly the same
> regardless of whether the library is linked statically or
> (unoptionally) dynamically. I'm not saying that it isn't possible with
> the above format (you need to bind one of the modules, STATIC_LINK_M1
> or DYNAMIC_LINK_M1, to a  module that you use in the client code), but
> rather that you might want to consider this from that perspective.

I agree this would be nice, but unfortunately it isn't. The assembly/C
generated by MLton to use a library must know whether those symbols
are imported from a dynamically or statically linked library. MLton
does not know this. When we pass '-lfoo' to the linker, it picks some
library out of paths we know nothing about.

> One alternative that comes to mind would be to specify as a
> command-line option whether one wishes to link statically or
> dynamically and MLton would then generate only one set of imports and
> the module name would be the same (e.g. just M1) in either case.

I am not sure where these options are to be passed, but it sounds like
you mean at library creation. What I think you've overlooked is that
the same library can be linked three different ways.

Consider a PIC archive library foo.

During compilation of C that will be included in the final PIC library
you have access to private symbols and shouldn't import symbols that
will be in the final foo product.

A shared library built against foo will statically link foo in. This
means it no longer has access to private symbols, but shouldn't be
importing the symbols either as they will be in the same final DSO.
MLton import headers call this PART_OF_LIBNAME.

A user of the resulting shared library wants to call functions that
were in foo. He has no access to private symbols and needs to import
the public ones. MLton import headers call this STATIC_LINK_LIBNAME

Each of these three uses are distinct and if you try to coflate any of
them I can present you with a platform where your solution breaks.
MLton import headers call this DYNAMIC_LINK_LIBNAME.

While it's certainly true that for many libraries there is a sane
default, sometimes there isn't. In MLton/svn terminology, we have four
output formats. The generated header access modes are described below:

executable -- only ever makes sense to use PART_OF_LIBNAME linkage
archive -- currently defaults to STATIC_LINK_LIBNAME, but if C is
included into the resulting library, PART_OF_LIBNAME should be defined
to override this default.
library -- currently defaults to DYNAMIC_LINK_LIBNAME, but override to
PART_OF_LIBNAME makes sense.
libarchive -- the case I detailed above, the import header has no
default and you have to specify the linkage.

I imagine we would output ML import files in the same way, eg: default
M1 = STATIC_LINK_M1 for archive, M1 = DYNAMIC_LINK_M1 for library. No
default for libarchive. Happily, there is no PART_OF_M1 case. At any
rate, this is what I am proposing: an automatic M1 that "does the
right thing" when it can, but includes both options in case you need
them.

Another problem on my mind, is that it's fairly common (on linux) for
libraries to be shipped as both dynamic (PIC .so) and static (non-PIC
archive), with only one header file. Sometimes important libraries
also include a PIC archive. This works because happily on ELF systems
public/external end up being the same. I'm not sure how to support
this model and at the same time also support platforms like windows
where public/external are critically different.



More information about the MLton mailing list