{"id":15061028,"url":"https://github.com/ocaml/flexdll","last_synced_at":"2025-04-05T01:08:27.786Z","repository":{"id":12471081,"uuid":"15137466","full_name":"ocaml/flexdll","owner":"ocaml","description":"a dlopen-like API for Windows","archived":false,"fork":false,"pushed_at":"2025-01-16T13:29:56.000Z","size":560,"stargazers_count":107,"open_issues_count":40,"forks_count":32,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-29T00:11:36.492Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ocaml.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-12-12T14:04:07.000Z","updated_at":"2025-01-22T16:07:19.000Z","dependencies_parsed_at":"2024-06-01T05:21:39.099Z","dependency_job_id":"a7e9d1e1-a9c9-4ee6-bfa5-98eb177a177b","html_url":"https://github.com/ocaml/flexdll","commit_stats":null,"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml%2Fflexdll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml%2Fflexdll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml%2Fflexdll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml%2Fflexdll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ocaml","download_url":"https://codeload.github.com/ocaml/flexdll/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247271532,"owners_count":20911587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T23:08:28.284Z","updated_at":"2025-04-05T01:08:27.779Z","avatar_url":"https://github.com/ocaml.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FlexDLL: an implementation of a dlopen-like API for Windows\n\n[![Build status](https://ci.appveyor.com/api/projects/status/github/ocaml/flexdll?svg=true)](https://ci.appveyor.com/project/dra27/flexdll-7sptc)\n\n## Introduction\n\nUnder Windows, DLL ([Dynamically-Linked Libraries][DLL]) are generally\nused to improve code modularity and sharing. A DLL can be loaded\nautomatically when the program is loaded (if it requires the DLL).\nThe program can also explicitly request Windows to load a DLL at any\nmoment during runtime, using the [`LoadLibrary`][LoadLibrary] function\nfrom the Win32 API.\n\nThis naturally suggests to use DLLs as a plugin mechanism. For instance,\na web server could load extensions modules stored in DLLs at runtime.\nBut Windows does not really make it easy to implement plugins that way.\nThe reason is that when you try to create a DLL from a set of object\nfiles, the linker needs to resolve all the symbols, which leads to the\nvery problem solved by FlexDLL:\n\n**Windows DLL cannot refer to symbols defined in the main application or\nin previously loaded DLLs.**\n\nSome usual solutions exist, but they are not very flexible. A notable\nexception is the [edll][] library (its homepage also describes the usual\nsolutions), which follows a rather drastic approach; indeed, edll\nimplements a new dynamic linker which can directly load object files\n(without creating a Windows DLL).\n\nFlexDLL is another solution to the same problem. Contrary to edll, it\nrelies on the native static and dynamic linkers. Also, it works both\nwith the Microsoft environment (MS linker, Visual Studio compilers) and\nwith Cygwin (GNU linker and compilers, in Cygwin or MinGW mode).\nActually, FlexDLL implements mostly the usual [`dlopen`][dlopen] POSIX\nAPI, without trying to be fully conformant though (e.g. it does not\nrespect the official priority ordering for symbol resolution).  This\nshould make it easy to port applications developed for Unix.\n\n[DLL]: https://en.wikipedia.org/wiki/Dynamic-link_library\n[LoadLibrary]: https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw\n[edll]: https://edll.sourceforge.net/\n[dlopen]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/dlopen.html\n\n## About\n\nFlexDLL is distributed under the terms of a zlib/libpng open source\n[license](LICENSE). The copyright holder is the Institut National de\nRecherche en Informatique et en Automatique (INRIA). The project was\nstarted when I (= Alain Frisch) was working at INRIA. I'm now working\nfor [LexiFi][], which is kind enough to let me continue my work on\nFlexDLL. My office mate at INRIA, Jean-Baptiste Tristan, coined the name\nFlexDLL.\n\nThe runtime support library is written in C. The `flexlink` wrapper is\nimplemented in the wonderful [OCaml][] language.\n\n[LexiFi]: https://www.lexifi.com\n[OCaml]: https://ocaml.org/\n\n## Supported toolchains\n\nMSVC: the 32-bit C compiler from Microsoft.\n\nMSVC64: the 64-bit C compiler from Microsoft.\n\nCYGWIN64: the 64-bit gcc compiler shipped with Cygwin.\n\nMINGW: the 32-bit gcc compiler from the MinGW-w64 project, packaged in\nCygwin (as i686-w64-mingw32-gcc).\n\nMINGW64: the 64-bit gcc compiler from the MinGW-w64 project, packaged in\nCygwin (as x86\\_64-w64-mingw32-gcc).\n\nLD: an internal linker to produce .dll (only).\n\n## Download\n\n- [Source and binary releases](https://github.com/ocaml/flexdll/releases).\n- [Development version](https://github.com/ocaml/flexdll).\n- [Changelog](CHANGES).\n\n**Installation instructions:** Simply run the installer and add the\nresulting directory (e.g. `C:\\Program Files\\flexdll` or\n`C:\\Program Files (x86)\\flexdll`) to the PATH. You can also create this\ndirectory by hand and unzip the .zip file in it.\n\n**Compiling from sources:** To compile the code from sources, you'll\nneed a working installation of OCaml, GNU Make, and a C toolchain\n(compiler + linker) either the one from Microsoft (any version of Visual\nStudio should work), Cygwin, or MinGW. It is probably a good idea to use\na native version of ocamlopt (not the Cygwin port) to compile flexlink.\nBy default, the `Makefile` will compile support objects for the\nsupported toolchains; you can choose a subset with the `CHAINS`\nvariable, e.g.: `make CHAINS=\"mingw msvc\"`.\n\n\n## Overview\n\nFlexDLL has two components: a wrapper around the static linker, and a\ntiny runtime library to be linked with the main application. The wrapper\nmust be called in place of the normal linker when you want to produce a\nDLL or to link the main application. The runtime library relies\ninternally on the native `LoadLibrary` API to implement a dlopen-like\ninterface.\n\nLet's see a simple example of a plugin. Here is the code for the main\nprogram (file `dump.c`):\n\n```c\n#include \u003cstdlib.h\u003e\n#include \"flexdll.h\"\n\ntypedef void torun(void);\n\nvoid api(char *msg){ printf(\"API: %s\\n\", msg); }\n\nint main(int argc, char **argv)\n{\n  void *sym;\n  void *handle;\n  int i;\n  torun *torun;\n\n  for (i = 1; i \u003c argc; i++) {\n    handle = flexdll_dlopen(argv[i], FLEXDLL_RTLD_GLOBAL);\n\n    if (NULL == handle) { printf(\"error: %s\\n\", flexdll_dlerror()); exit(2); }\n\n    torun = flexdll_dlsym(handle, \"torun\");\n    if (torun) torun();\n  }\n  exit(0);\n}\n```\n\nThis application opens in turn all the DLLs given on its command line,\nusing the FlexDLL function `flexdll_dlopen`. For each DLL, the program\nlooks for a symbol named `torun` (which is supposed to refer to a\nfunction) and if the symbol is available in the DLL, the function is\ncalled. The program also provides a very simple API to its plugin: the\n`api` function. The `FLEX_RTLD_GLOBAL` flag makes all the symbols\nexported by each DLL available for the DLL to be loaded later.\n\nThis main program can be compiled and linked like the commands below\n(the `[...]` refers to the directory where FlexDLL is installed).\n\n```sh\n# MSVC\ncl /nologo /MD -I[...] -c dump.c\nflexlink -chain msvc -exe -o dump.exe dump.obj\n\n# MINGW\ni686-w64-mingw32-gcc -I[...] -c dump.c\nflexlink -chain mingw -exe -o dump.exe dump.o\n\n# CYGWIN\ngcc -I[...] -c dump.c\nflexlink -chain cygwin64 -exe -o dump.exe dump.o\n```\n\nThe compilation step is completely standard, but in order to link the\nmain application, you must call the `flexlink` tool, which is the\nwrapper around the linker. The `-chain` command line switch selects\nwhich linker to use, and the `-exe` option tells the wrapper that it\nmust produce a stand-alone application (not a DLL).\n\nNow we can provide a first plugin (file `plug1.c`):\n\n```c\nint x = 3;\nvoid dump_x(void) { printf(\"x=%i\\n\", x); }\nvoid torun(void) { api(\"plug1.torun();\"); }\n```\n\nNote that the plugin uses the `api` symbol from the main application (it\nwould be cleaner to introduce it with an `extern` declaration). You can\ncompile and link this plugin (into a DLL) with the following commands:\n\n```sh\n# MSVC\ncl /nologo /MD -c plug1.c\nflexlink -chain msvc -o plug1.dll plug1.obj\n\n# MINGW\ni686-w64-mingw32-gcc -c plug1.c\nflexlink -chain mingw -o plug1.dll plug1.o\n\n# CYGWIN\ngcc -D_CYGWIN_  -c plug1.c\nflexlink -chain cygwin64 -o plug1.dll plug1.o\n```\n\nAnd now you can ask the main program to load the plugin:\n\n```console\n$ ./dump plug1.dll\nAPI: plug1.torun();\n```\n\nHere is the code for a second plugin (file `plug2.c`) that refers to\nsymbols (a function and a global variable) defined in the first plugin:\n\n```c\nextern int x;\n\nvoid torun(void) {\n  api(\"plug2.torun();\");\n\n  dump_x();\n  x = 100;\n  dump_x();\n}\n```\n\nSince the second plugin depends on the first one, you need to load both:\n\n```console\n$ ./dump plug2.dll\nerror: Cannot resolve dump_x\n$ ./dump plug1.dll plug2.dll;\nAPI: plug1.torun();\nAPI: plug2.torun();\nx=3\nx=100\n```\n\nSimple, isn't it? No `declspec` declaration, no import library to deal\nwith, …\n\n\n## How it works\n\nObject files (.obj/.o) contain relocation information that explain to\nthe linker how some addresses in their code or data sections have to be\npatched, using the value of some global symbols. When the static linker\nis invoked to produce a DLL from a set of object files, it assumes that\nall the relocations can be performed: all the symbols which are used in\nrelocations must be defined in some the objects linked together.\nFlexDLL drops this constraint following a very simple idea: when a\nrelocation refers to a symbol which is not available, the relocation is\nturned into a piece of data that will be passed to the runtime support\nlibrary.\n\nIn the example above, the `plug1.obj` object refers to a symbol\n`api`. When this object is turned into a DLL, FlexDLL produce a new\ntemporary object file derived from `plug1.obj` without the relocation\nthat mentions `api`. Instead, it adds an “import table”, which is just a\npiece of data that tells the FlexDLL support library which address has\nto be patched with the value of a symbol called `api` to be found\nsomewhere else. You can see the list of such imported symbols by adding\nthe `-show-imports` option to the `flexlink` command line:\n\n```console\n$ ../flexlink -chain msvc -o plug1.dll plug1.obj -show-imports\n** Imported symbols for plug1.obj:\n_api\n```\n\nWhen the `flexdll_dlopen` function opens this DLL, it will look for an\ninternal symbol that points to the import table, resolve the symbols and\npatch the code and data segments accordingly. The FlexDLL runtime\nlibrary must thus maintain a set of symbols together with their concrete\nvalues (addresses). In particular, it knows about the global symbols\ndefined in the main program. Indeed, when you link the main program with\n`flexlink -exe`, the wrapper produces a small fresh object file that\ncontains a symbol table, mapping symbol names to their addresses.\n\n```console\n$ ../flexlink -chain msvc -exe -o dump.exe dump.obj -show-exports\n** Exported symbols:\n_api\n_flexdll_dlclose\n_flexdll_dlerror\n_flexdll_dlopen\n_flexdll_dlsym\n_flexdll_dump_exports\n_flexdll_dump_relocations\n_main\n```\n\nAs you can see, all the global symbols (including those that comes from\nFlexDLL itself) appear in the global symbol table. FlexDLL knows not\nonly about symbols that comes from the main program, but also about\nsymbols exported by the DLL it loads. This is needed to implement the\n`flexdll_dlsym` function, but also to deal with import tables that\nmention symbols defined in previously loaded DLLs (for which the\n`FLEXDLL_RTLD_GLOBAL` was used). So the wrapper produces not only an\nimport table for DLLs, but also an export table:\n\n```console\n$ ../flexlink -chain msvc -o plug1.dll plug1.obj -show-imports -show-exports\n** Imported symbols for plug1.obj:\n_api\n** Exported symbols:\n_dump_x\n_torun\n_x\n\n$ ../flexlink -chain msvc -o plug2.dll plug2.obj -show-imports -show-exports\n** Imported symbols for plug2.obj:\n_api\n_dump_x\n_x\n** Exported symbols:\n_torun\n```\n\nHow does FlexDLL determine which symbols are imported or exported? It\nuses an algorithm similar to the linker itself. The command line\nmentions a number of object and library files. In a first pass, the\nwrapper computed which objects embedded in those libraries will be used.\nTo do that, it looks at which symbols are used, and where they are\ndefined. Then the wrapper considers that all the global (external)\nsymbols are exported. Note that the `/export` or `__declspec(dllexport)`\ndirectives are not used: all the symbols are exported. (In a future\nversion, FlexDLL will allow to control more precisely which symbols are\nexported). All the object files (given explicitly, or embedded in a\nlibrary) that need to import symbols must be rewritten. The `flexlink`\nwrapper will produce new temporary object files for them. If you want to\nunderstand better how FlexDLL works, you can use the `-v` and\n`-save-temps` command options to tell the wrapper to show you the linker\ncommand line and to preserve those temporary files alive (by default, they\nare removed automatically).\n\nSome object files can mention default libraries (they correspond to the\n`/defaultlib` linker flag, which is often embedded in the object\n`.drectve` section). FlexDLL will parse those libraries, but only to see\nwhich symbols they define. Those symbols are not considered as being\nimported by the DLL, but they won't be exported either. A typical case\nof default libraries are import libraries that behave as interfaces to\n(normal, non-FlexDLL) DLLs.\n\n\n## Advanced topic: `__declspec(dllimport)`\n\nC compilers under Windows support a special declaration of external\nsymbols. You can write:\n\n```c\n__declspec(dllimport) extern int mysymbol;\n```\n\nInternally, this declaration has the same effect as declaring:\n\n```c\nextern int *_imp__mysymbol;\n```\n\nand using `\u0026x` instead of `x` everywhere in the current unit. In other\nwords, even if your code seems to access `x` directly, each access\nactually goes through an extra indirection.\n\nFlexDLL knows about this convention. When a object refers to a symbol of\nthe form `_imp__XXX` which is not available in the objects that will\nform the DLL to be created, it resists the temptation of putting an\nentry for `_imp__XXX` in the import table. Instead, it adds the\nequivalent of the following declaration:\n\n```c\nvoid *_imp__XXX = \u0026XXX;\n```\n\nIf the symbol `XXX` itself is not available, this will in turn produce\nan entry for `XXX` in the import table. All these new declarations are\nput in the same object file that contain the export table, which is\nglobal for the DLL to be produced. So, if all the external symbols in a\ngiven object files are accessed through this convention, the object file\nneed not be patched at all.\n\nNote that you can define and use the `_imp__XXX` symbols by hand, you\ndon't have to use the `__declspec(dllimport)` notation (this is useful\nif you use a compiler that doesn't support this notation).\n\nThere *are* compelling reasons to adopt this style.\n\nA very small advantage might be that there will be fewer relocations at\nruntime and that more code pages can be shared amongst several instances\nof the same DLL used by different processes.\n\nA big advantage on x86_64 systems is to avoid relocation errors like:\n\n```text\nFatal error: cannot load shared library plug1\nReason: flexdll error: cannot relocate XXX\n  RELOC_REL32, target is too far: FFFFFFFF2EDEC956  000000002EDEC956\n```\n\nWithout `__declspec(dllimport)` your symbol (ex. `extern XXX`) generates\nthe following pseudo-assembly:\n\n```asm\nCALL XXX ; this is a 32-bit relative address\n```\n\nThese 32-bit relative addresses are restricted to 2GiB jumps, and there is\nno guarantee that your main programs and all its DLLs will reside in the same\n2GiB block of virtual memory. The more DLLs you have, and the bigger they\nare, the more likely you will encounter a `RELOC_REL32` error.\n\nflexdll will verify every 32-bit relative address `CALL` during\n`flexdll_dlopen` to ensure they are within 2GiB.\nHowever, the indirection introduced by `__declspec(dllimport) extern` makes\nthe pseudo-assembly instead:\n\n```asm\nvoid *_imp__XXX = \u0026XXX;\nCALL [_imp__XXX] ; this is a 64-bit indirect address\n```\n\nwhich works well with flexdll.\n\n## Advanced topic: static constructors and the entry point\n\nA Windows DLL can define an optional entry point. When the DLL is\nloaded, this function is automatically called. (The same function is\ncalled when the DLL is unloaded, or when threads are spawned or\ndestroyed.)\n\nUsually, the real entry point is provided by the C runtime library:\n`_cygwin_dll_entry` for Cygwin, `DllMainCRTStartup` for MinGW,\n`_DllMainCRTStartup` for MSVC. These functions perform various\ninitialization for the C runtime library, invoke the code that has to be\nrun automatically at load time (e.g for C++: constructors of static\nobjects, or right-hand sides of non-constant initializers for global\nvariables), and then call the function [`DllMain`][DllMain], which by\ndefault does nothing but can be overridden by the program to perform\ncustom initialization of the DLL.\n\nFlexDLL must take control before any custom code (static constructors,\n`DllMain`) so as to perform relocations (in case this code refers to\nsymbols found in the main program or previously loaded DLLs). As a\nconsequence, FlexDLL defines its own entry point, which first asks the\nmain program to perform relocations and then calls the regular entry\npoint of the C runtime library. This behavior is implemented in the\n`flexdll_initer.c` file, and the corresponding object file (whose name\ndepends on the toolchain) is automatically included by `flexlink`.\n\nIt is possible to completely disable the DLL entry point with the\n`-noentry` option passed to `flexlink`. In this case, FlexDLL will\nperform relocations after the DLL has been opened.\n\n[DllMain]: https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain\n\n## The API\n\nHere is the content of the `flexdll.h` file:\n\n```c\n#define FLEXDLL_RTLD_GLOBAL 0x0001\n#define FLEXDLL_RTLD_LOCAL  0x0000\n#define FLEXDLL_RTLD_NOEXEC 0x0002\n\nvoid *flexdll_dlopen(const char *, int);\n#ifndef CYGWIN\nvoid *flexdll_wdlopen(const wchar_t *, int);\n#endif\nvoid *flexdll_dlsym(void *, const char *);\nvoid flexdll_dlclose(void *);\nchar *flexdll_dlerror(void);\n\nvoid flexdll_dump_exports(void *);\nvoid flexdll_dump_relocations(void *);\n```\n\nThe `flexdll_dl*` functions are mostly compatible with their POSIX\ncounterparts. Here is a short explanation of their semantics.\n\nThe most important function is `flexdll_dlopen`. The first argument\ngives the filename of a DLL to be opened. This DLL must have been\nproduced by the `flexlink` wrapper. The function resolves the symbols\nmentioned in the DLL's import table and performs the relocations.\nThe second argument is a mode, made of flags that can be or'ed together.\nThe flag `FLEXDLL_RTLD_GLOBAL` means that the symbols exported by the\nopened DLL can be used to resolve relocations for DLLs to be opened\nlater on. The flag `FLEXDLL_RTLD_NOEXEC` opens the DLL is a special\nmode, disabling the automatic loading of dependencies and the FlexDLL\nresolution pass. This is useful if you want to open a DLL only to check\nwhether it defines some symbol.\n\nThe `flexdll_dlopen` function returns a pointer to an opaque handle that\ncan be used as an argument to the other API functions. If the filename\nis `NULL`, the function returns a special handle which refers to the\nglobal unit: it includes all the static symbols, plus the symbols from\nthe DLLs opened with the `FLEXDLL_RTLD_GLOBAL` flag. A given DLL will be\nopened only once, even if you call the function several times on the\nsame file. The `FLEXDLL_RTLD_GLOBAL` flag is sticky: if one of the calls\nmentions it, it will stay forever, even if the corresponding handle is\nthen passed to `dlclose` (this is because the same handle is actually\nreturned for all the calls). If an error occurs during the call to\n`flexdll_dlopen`, the functions returns `NULL` and the error message can\nbe retrieved using `flexdll_dlerror`.\n\nThe function `flexdll_wdlopen` is a wide-character version of\n`flexdll_dlopen`. The filename argument to `flexdll_wdlopen` is a\nwide-character string. `flexdll_wdlopen` and `flexdll_dlopen` behave\nidentically otherwise.\n\nThe second most important function is `flexdll_dlsym` which looks for a\nsymbol whose name is the second argument. The first argument can be\neither a regular handle returned by `flexdll_dlopen` (the symbol is\nsearched only in the corresponding DLL), the special handle for the\nglobal unit as return by a call to `flexdll_dlopen(NULL,...)` (the\nsymbol is searched amongst the static symbols plus the ones in the DLL\nopened with the flag `FLEXDLL_RTLD_GLOBAL`), or `NULL` (the symbol is\nsearched only amongst the static symbols). If the symbol cannot be\nfound, the function returns `NULL`.\n\nThe same symbol name can be defined several times. The policy used to\nchoose amongst the various definitions is not specified. This applies\nboth to the automatic resolution that happens when you open a DLL and to\nthe explicit resolution performed by `dlsym`.\n\nThe function `flexdll_dlclose` must be used with caution. It decrements\nthe reference counter for the given handle and releases the DLL from memory\nwhen the counter reaches 0. After that time, symbols defined in this DLL\nare no longer used for resolution. You most probably don't want to close\na DLL if you still hold pointers to some of its symbols.\n\nThe two functions `flexdll_dump_exports` and `flexdll_dump_relocations`\nare used to display (to the standard output) the internal tables\nassociated with a given DLL handle.\n\n\n## Command line for the flexlink wrapper\n\n```\nUsage:\n  flexlink -o \u003cresult.dll/exe\u003e file1.obj file2.obj ... -- \u003cextra linker arguments\u003e\n\n  -o                  Choose the name of the output file\n  -exe                Link the main program as an exe file\n  -maindll            Link the main program as a dll file\n  -noflexdllobj       Do not add the Flexdll runtime object (for exe)\n  -noentry            Do not use the Flexdll entry point (for dll)\n  -noexport           Do not export any symbol\n  -norelrelocs        Ensure that no relative relocation is generated\n  -base               Specify base address (Win64 only)\n  -pthread            Pass -pthread to the linker\n  -I \u003cdir\u003e            Add a directory where to search for files\n  -L \u003cdir\u003e            Add a directory where to search for files\n  -l \u003clib\u003e            Library file\n  -chain {msvc|msvc64|cygwin64|mingw|mingw64|gnat|gnat64|ld}\n                      Choose which linker to use\n  -use-linker \u003ccmd\u003e   Choose an alternative linker to use\n  -use-mt \u003ccmd\u003e       Choose an alternative manifest tool to use\n  -x64                (Deprecated)\n  -defaultlib \u003cobj\u003e   External object (no export, no import)\n  -save-temps         Do not delete intermediate files\n  -implib             Do not delete the generated import library\n  -outdef             Produce a def file with exported symbols\n  -v                  Increment verbosity (can be repeated)\n  -show-exports       Show exported symbols\n  -show-imports       Show imported symbols\n  -dry                Show the linker command line, do not actually run it\n  -dump               Only dump the content of object files\n  -patch              Only patch the target image (to be used with -stack)\n  -nocygpath          Do not use cygpath (default for msvc, mingw)\n  -cygpath            Use cygpath (default for cygwin)\n  -no-merge-manifest  Do not merge the manifest (takes precedence over -merge-manifest)\n  -merge-manifest     Merge manifest to the dll or exe (if generated)\n  -real-manifest      Use the generated manifest (default behavior)\n  -default-manifest   Use the default manifest (default.manifest/default_amd64.manifest)\n  -export \u003csym\u003e       Explicitly export a symbol\n  -noreexport         Do not reexport symbols imported from import libraries\n  -where              Show the FlexDLL directory\n  -nounderscore       Normal symbols are not prefixed with an underscore\n  -nodefaultlibs      Do not assume any default library\n  -builtin            Use built-in linker to produce a dll\n  -explain            Explain why library objects are linked\n  -subsystem \u003cid\u003e     Set the subsystem (default: console)\n  -custom-crt         Use a custom CRT\n  -stack \u003cint\u003e        Set the stack reserve in the resulting image\n  -link \u003coption\u003e      Next argument is passed verbatim to the linker\n  -g                  (Ignored)\n  -D \u003csymbol\u003e         (Ignored)\n  -U \u003csymbol\u003e         (Ignored)\n  --                  Following arguments are passed verbatim to the linker\n  -version            Print linker version and FlexDLL directory and exit\n  -vnum               Print linker version number and exit\n  -help               Display this list of options\n  --help              Display this list of options\n```\n\nThe files given on the command line can be object files (.obj/.o),\nlibrary files (.a/.lib), or C files (.c). C files will be compiled using\nthe toolchain's C compiler and the resulting object will be used for the\nactual linking.\n\nThe argument for the `-l`, `-I` and `-L` options does not need to be\nseparated by whitespace from the option (i.e. `-LXXX` is equivalent to\n`-L XXX`).\n\nThere is a single set of search directories for all kinds of files.\nThe `-I` and `-L` options are synonyms.\n\nAs usual, object files included in libraries are linked in only if one\nof the symbol they export is needed.\n\nThe `-export` option explicitly exports a symbol. If this symbols is\nfound in a library, it will force the corresponding object file to be\nincluded.\n\nThe `-defaultlib` option is used to tell `flexlink` that some object\n(usually, a library) does not need any relocations (that is, all the\nsymbols it refers to are defined in one of the objects being linked) and\nthat we don't want to re-export the symbols exported by this object.\nThis is usually used for system libraries.\n\nThe `-cygpath` and `-nocygpath` options control whether `flexlink` uses\nthe `cygpath` command or not (default is: no under MSVC, yes under\nCygwin/MinGW if cygpath can be found in the PATH). When it uses\n`cygpath`, `flexlink` tries to resolve file names directly and otherwise\ncalls `cygpath -m` (to produce Windows paths from Cygwin paths) if\n`cygpath` is available in the path.\n\nThe `-maindll` option is used to build a DLL that behaves as the main\nprogram from the point of view of FlexDLL. It cannot have unresolved\nsymbols.\n\nBy default, `flexlink` looks for FlexDLL's object files in the same\ndirectory as `flexlink.exe` itself. It is possible to specify another\ndirectory with the `FLEXDIR` environment variable.\n\nExtra arguments can be passed to `flexlink.exe` through the environment\nvariable `FLEXLINKFLAGS`. The arguments coming from this variable are\nparsed before those coming from the command line.\n\n\n## Performance\n\nFlexDLL performs relocations at runtime in the code of the DLL. The good\nconsequence is that there is no indirection: a function call or a\nreference to a global variable where the target symbol is not in the\ncurrent DLL be compiled as if it were. This might improve performance,\nespecially because an indirection would consume a register that might be\nbetter used for something more interesting. The bad consequence is that\nthe memory pages that contains relocations cannot be shared between\ndifferent processes.\n\n\n## Bugs, limitations\n\nFlexDLL relies on a parser and generator for COFF files. However, some\nfeatures are not very well specified, and some well specified features\nhave not been fully implemented. Normally, you should get some assertion\nfailure in these cases. Please report them, so that I can improve\nFlexDLL.\n\nFlexDLL works for 32 and 64 bits version of Windows. The 32 bits version\nhas been tested under XP and Vista, with the three supported toolchains.\nThe 64 bits version has been tested under Windows Vista x64 with the\nMicrosoft Platform SDK and under Windows 7 64-bit with the Win7 SDK\ntoolchain (no Cygwin).\n\n\n## Real-world examples\n\nPlease let me know if you use FlexDLL!\n\n### Dynamic loading for OCaml\n\nThe initial motivation for FlexDLL was to add dynamic linking of native\ncode to Windows ports of [OCaml][] (Cygwin, MinGW, MSVC). A side-effect\nwas to simplify the dynamic loading of C libraries (e.g. for the\ntoplevel) and to make it work under the Cygwin port, to simplify\nMakefiles of libraries (now shared between Unix and Windows ports), and\nto create a native toplevel.\n\n\n## Links\n\n- [Microsoft Portable Executable and Common Object File Format Specification](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format).\n- [Enhanced Dynamic Linking Library for MinGW under MS-Windows (edll)][edll].\n- [`dlopen` (POSIX)][dlopen].\n- [`DllMain`][DllMain].\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Focaml%2Fflexdll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Focaml%2Fflexdll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Focaml%2Fflexdll/lists"}