Git Product home page Git Product logo

flexdll's Introduction

⚠️ CAUTION

The developer team released OCaml 5.0.0 in December 2022. This release sports a full rewrite of its runtime system for shared-memory parallel programming using domains and native support for concurrent programming using effect handlers.

Owing to the large number of changes, the initial 5.0 release is more experimental than usual. It is recommended that all users wanting a stable release use the 4.14 release which will continue to be supported and updated while 5.x reaches feature and stability parity. Similarly, if you need one of the ports not yet supported in the 5.0 release you must use the 4.14 release.

The initial release of OCaml 5.0 only supports the native compiler under ARM64 and x86-64 architectures under Linux, macOS and the BSDs. On Windows, only the MinGW-w64 port is supported in OCaml 5.0 and the Cygwin port is restored in 5.1. On Linux, native code support for RISC-V and s390x/IBM Z is available in OCaml 5.1 and in 5.2 for Power.

❗ From OCaml 5.0 onwards, native compilation is available only on 64-bit systems. Native compilation on 32-bit systems is no longer available, nor are there plans to bring it back. The bytecode compiler will continue to work on all architectures.

Branch trunk Branch 5.2 Branch 5.1 Branch 5.0 Branch 4.14

Github CI Build Status (trunk branch) Github CI Hygiene Status (trunk branch) AppVeyor Build Status (trunk branch)

Github CI Build Status (5.2 branch) AppVeyor Build Status (5.2 branch)

Github CI Build Status (5.1 branch) AppVeyor Build Status (5.1 branch)

Github CI Build Status (5.0 branch) AppVeyor Build Status (5.0 branch)

Github CI Build Status (4.14 branch) AppVeyor Build Status (4.14 branch)

README

Overview

OCaml is a functional, statically-typed programming language from the ML family, offering a powerful module system extending that of Standard ML and a feature-rich, class-based object system.

OCaml comprises two compilers. One generates bytecode which is then interpreted by a C program. This compiler runs quickly, generates compact code with moderate memory requirements, and is portable to many 32 or 64 bit platforms. Performance of generated programs is quite good for a bytecoded implementation. This compiler can be used either as a standalone, batch-oriented compiler that produces standalone programs, or as an interactive REPL system.

The other compiler generates high-performance native code for a number of processors. Compilation takes longer and generates bigger code, but the generated programs deliver excellent performance, while retaining the moderate memory requirements of the bytecode compiler. The native-code compiler currently runs on the following platforms:

Tier 1 (actively maintained) Tier 2 (maintained when possible)

x86 64 bits

Linux, macOS, Windows, FreeBSD

NetBSD, OpenBSD, OmniOS (Solaris)

ARM 64 bits

Linux, macOS

FreeBSD, OpenBSD, NetBSD

Power 64 bits

Linux (little-endian, ABIv2)

Linux (big-endian, ABIv2)

RISC-V 64 bits

Linux

IBM Z (s390x)

Linux

Other operating systems for the processors above have not been tested, but the compiler may work under other operating systems with little work.

All files marked "Copyright INRIA" in this distribution are Copyright © 1996-2023 Institut National de Recherche en Informatique et en Automatique (INRIA) and distributed under the conditions stated in file LICENSE.

Installation

See the file INSTALL.adoc for installation instructions on machines running Unix, Linux, macOS, WSL and Cygwin. For native Microsoft Windows, see README.win32.adoc.

Documentation

The OCaml manual is distributed in HTML, PDF, and Emacs Info files. It is available at

Availability

The complete OCaml distribution can be accessed at

Keeping in Touch with the Caml Community

There is an active and friendly discussion forum at

The OCaml mailing list is the longest-running forum for OCaml users. You can email it at

You can subscribe and access list archives via the Web interface at

There also exist other mailing lists, chat channels, and various other forums around the internet for getting in touch with the OCaml and ML family language community. These can be accessed at

In particular, the IRC channel #ocaml on Libera has a long history and welcomes questions.

Bug Reports and User Feedback

Please report bugs using the issue tracker at https://github.com/ocaml/ocaml/issues

To be effective, bug reports should include a complete program (preferably small) that exhibits the unexpected behavior, and the configuration you are using (machine type, etc).

For information on contributing to OCaml, see HACKING.adoc and CONTRIBUTING.md.

Separately maintained components

Some libraries and tools which used to be part of the OCaml distribution are now maintained separately and distributed as OPAM packages. Please use the issue trackers at their respective new homes:

Library Removed since OPAM package

The Stream and Genlex standard library modules

OCaml 5.0

camlp-streams

The Graphics library

OCaml 4.09

graphics

The Num library

OCaml 4.06

num

The OCamlbuild tool

OCaml 4.03

ocamlbuild

The camlp4 tool

OCaml 4.02

camlp4

The LablTk library

OCaml 4.02

labltk

The CamlDBM library

OCaml 4.00

dbm

The OCamlWinTop Windows toplevel

OCaml 4.00

none

flexdll's People

Contributors

alainfrisch avatar bryphe avatar bschommer avatar damiendoligez avatar db4 avatar dra27 avatar elfmimi avatar jonahbeckford avatar kanigsson avatar misterda avatar msoegtropimc avatar nevor avatar nojb avatar sbriais avatar shym avatar yakobowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flexdll's Issues

Implementing a less memory intensive read function

When building the ocaml bibindings for Z3, it attempts to allocate ~10GiB before an oom error. This exceedingly high memory usage occurs while reading the import library (libz3.dll.a), and before the actual linker is called.

I don't know if there's a more efficient way to store these strings, or if it's possible to implement it such as to save results to disk and continue reading if memory usage is becoming too high. It seems very improbable that 33 GiB of strings are needed to make ~500KiB to 1.3MiB libraries.

The most pertinent information from the ctf is likely:

1391 samples of 10.4 GB allocations

 5.9 GB (57.0%) at Stdlib__Bytes.sub (bytes.ml:68:12-22, 68:12-22)
      including:
     2.9 GB via Coff.Lib.read_lib.read_member (97% of this)

 4.4 GB (42.4%) at Stdlib__Buffer.resize (buffer.ml:87:19-40)
      including:
     4.1 GB via Coff.Lib.read_lib.obj (56% of this)
     4.1 GB via Stdlib__Printf.ksprintf.k' (93% of this)
     4.1 GB via CamlinternalFormat.strput_acc (93% of this)
     4.1 GB via Stdlib__Buffer.add_string (93% of this)

The CTF is here, if you'd like to view it, though.
https://gist.github.com/EmmaJaneBonestell/98fda00c93a8d09ea09bada08972761d

Edit: I used a GCP server, and it took about 33 GiB of RAM and a total of 46 GiB of allocations to build.

Edit 2: UCRT had nothing to do with it, but rather, it seems to have the excessive memory usage with any of the MSYS2 environments' built dlls. If the dll is built with Cygwin's MinGW toolchain, rather than MSYS2's MINGW toolchain, it doesn't have a problem. E.g. libz3.dll.a built with Cygwin's MinGW, vs MSYS2's, won't consume excessive RAM.

flexlink: simplify static linking with libstdc++

Currently with flexlink, if you have a C++ binding and want to link it statically in your executable to avoid having to carry the dll around the only option that works is to manually set the name for the archive file like this (with MinGW):

-l:libstdc++.a -l:libpthread.a -Wl,-static

It would be nice if something like -lstdc++ -static was a thing so that flexlink can find the correct archive file as by default -lstdc++ -Wl,-static will use libstdc++.dll.a which is the shared version of libstdc++ and not the static one.

Cannot relocate on OCaml 4.13.1 [Windows]

I'm working on porting the Binary Analysis Platform / BAP to Windows.

Unless I am misunderstanding, the mingw64 chain , >=OCaml 4.12.1, and >=Binutils 2.36 should no longer be experiencing runtime plugin/dll relocation failures with RELOC_REL32.

Using MSYS2's UCRT shell/toolchain (I have this same issue in Cygwin, too.), MinGW GCC 11.2, OCaml 4.13.1 + flambda, and the latest git source of flexdll.

However, the LLVM-backend plugin for BAP is erroring out here. If I get flexlink to pass --default-image-base-low when linking the main executable and the breaking plugin, it's fine. Decorating the symbol as a dllimport, in the plugin code, didn't appear to make a difference.

No other plugins seem to have this issue, even when they are left with a high base address & the executable is low.

Failed to load plugin "bap-plugin-llvm": Failed to load bap_llvm: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "(Failure\n \"flexdll error: cannot relocate _ZN3bap21register_disassemblerENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10shared_ptrINS_14disasm_factoryEE RELOC_REL32, target is too far: FFFFFFFCCE4E7D5B FFFFFFFFCE4E7D5B\")")

bap::register_disassembler(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<bap::disasm_factory>)

These are the instantiation of the register_disassembler function in the main executable:
https://github.com/BinaryAnalysisPlatform/bap/blob/master/lib/bap_disasm/disasm.hpp
https://github.com/BinaryAnalysisPlatform/bap/blob/master/lib/bap_disasm/disasm.cpp

And this is the plugin's usage of it:
https://github.com/BinaryAnalysisPlatform/bap/blob/master/lib/bap_llvm/llvm_disasm.cpp

I'll be honest and say that I'm only guessing that this problem lies with FlexDLL, but it could be in OCaml itself, BAP's source code, MinGW, etc.

If needed, I can provide a way to reproduce this; however, it's unfortunately not a quick process, and will require manual steps in the build process. At that, I could also provide the virtual machine image or the msys64 folder.

Compile ERROR with MSVC VS2019

I got 2 unresolved symbols during linking with MSVC VS2019:
static_symtable
reloctbl

I find that the two symbols are both extern declared in .c file but no any reference.
So, I change them to static declare and it can pass compiling and linking with my project.
However, when I try to load a DLL in windows, flexdll cannot fetch any symbols in my DLL, flexdll_dlsym API return NULL.
I try dumpbin.exe tool in widnows, and it truely got correct symbols.

Now, I begin getting confused, HOW can I use flexdll in my VS2019 project?

mingw64 (and presumably mingw) fails on French-language Windows 10

This is the output of x86_64-w64-mingw32-gcc -print-search-dirs on a French-configured windows 10:

installés: /usr/lib/gcc/x86_64-w64-mingw32/5.4.0/
programmes : =/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/:/usr/lib/gcc/x86_64-w64-mingw32/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/:/usr/lib/gcc/x86_64-w64-mingw32/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/../../../../x86_64-w64-mingw32/bin/x86_64-w64-mingw32/5.4.0/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/../../../../x86_64-w64-mingw32/bin/
libraries : =/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/../../../../x86_64-w64-mingw32/lib/x86_64-w64-mingw32/5.4.0/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/../../../../x86_64-w64-mingw32/lib/../lib/:/usr/x86_64-w64-mingw32/sys-root/mingw/lib/x86_64-w64-mingw32/5.4.0/:/usr/x86_64-w64-mingw32/sys-root/mingw/lib/../lib/:/usr/lib/gcc/x86_64-w64-mingw32/5.4.0/../../../../x86_64-w64-mingw32/lib/:/usr/x86_64-w64-mingw32/sys-root/mingw/lib/

flexlink fails to parse it because of the space between libraries and :

I don't know who had the bright idea of localizing this part of gcc but it looks like you'll need to adapt.

Upgrade from msvcrt.lib to ucrt.lib

With the minimum requirements for OCaml at Windows 10 (I think), we should consider moving off the legacy msvcrt.lib.

Here is the branch I have used for testing: https://github.com/jonahbeckford/flexdll/commits/0.43%2Bucrt

There are two blockers:

  1. #29 is probably related (I'm seeing this error only after upgrading to ucrt.lib.
  2. Some extra libraries are needed (not sure whether this belongs in ocaml/flexdll or ocaml/ocaml itself). I'll place each library in a separate comment below.

Issue with link order of archive files specified twice on the command line

I am currently in the process of moving the Coq Windows build from our old shell scripts to opam. Doing so, I have an issue with linking CoqIDE with flexlink. I (or ocamlfind) specify one archive twice on the command line like this:

-lpangocairo-1.0
: 
-llablgtk3_stubs
:
-lpangocairo-1.0

liblablgtk3_stubs needs symbols defined in lpangocairo-1.0 and the nm tool tells me that the symbols are there. Still I get an error that the symbols are undefined.

I looked into this with SysInternals ProcMon and all involved tools (flexlink, mingw gcc and ld) read the archives in the order libpangocairo and then lablgtk3_stubs. Notably pangocairo-1.0 is not read a second time although it is specified twice.
As far as I know at least ld does not use objects in an archive when they don't contain currently needed symbols, so in this order pangocairo-1.0 get's ignored.

Another interesting point is that the command line to gcc does not contain libpangocairo at all, although it does read it later - not sure what kind of magic this is (See line 9175 in the attached log).

I must admit I am not 100% sure what version of flexlink I have since it is supplied by opam and it doesn't seem to have an option to display this.

If this helps I can supply batch/shell scripts which install a fresh cygwin and bring you to the point of this error.

P.S.: I tried to attach the ProcMon log as txt or zip - it won't let me giving obscure errors. I will try again after creating the issue.

"Cannot relocate" error with flexdll in OCaml for Windows 4.11 (and older versions)

Hello,

I just installed OCaml for Windows 4.11.1 (4.11.1+mingw64c) and, as before, I tried to install and run the frama-c package, which uses dynamic loading for its plugins. Compilation worked fine, but trying to run it fails with:

[kernel] User Error: cannot load plug-in 'num.core': cannot load module
  Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"flexdll error: cannot relocate RELOC_REL32, target is too far: ffffffff6a110d73  000000006a110d73\")")
[kernel] User Error: cannot load plug-in 'zip': cannot load module
  Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"flexdll error: cannot relocate RELOC_REL32, target is too far: fffffffe488b648d  00000000488b648d\")")
[kernel] User Error: cannot load plug-in 'why3': cannot load module
  Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"Cannot resolve camlGzip\")")
[kernel] User Error: cannot load plug-in 'frama-c-wp': cannot load module
  Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"Cannot resolve camlWhy3__Ident\")")

I had never seen this issue before; frama-c worked with several previous versions of the OCaml compiler. After testing, I noticed it also happens with older versions of Frama-C, and with OCaml as old as 4.08.1 (I didn't have the time to test other versions; each compilation takes about 1 hour...). So I wonder if something changed on Windows or in flexdll. The same issue happened to one of our users, so it's not just my machine. I'm not sure what to do on the Frama-C side to debug it.

Are there any known issues issues related to the "flexdll error: cannot relocate RELOC_REL32, target is too far" message? Would you have any suggestions on how to proceed to debug this?

By the way, running flexlink -help displays FlexDLL version 0.38fdopen1; so I'm not sure I should contact fdopen directly to ask for help; sorry if the issue is unrelated to you.

flexlink should not use constant base address for Cygwin64

flexlink passes --image-base 0x10000 to the linker for Cygwin64 in order to ensure that relocations are always within a 32-bit range. This is causing problem when multiple DLLs are loaded by a single process (especially dllthreads.so and dllunix.so).

There is also the problem that nothing prevents Cygwin's rebaseall from re-setting the base address to something higher.

I think that two changes are ultimately required:

  • Some kind of DLL flag which Cygwin's rebase utility recognises as requiring a 32-bit compatible base address (this needs more detail - especially as regarding how the present Cygwin64 ocaml package gets around this)
  • flexlink needs to do whatever the linker would normally do to determine a "random" base address for the DLL, but with the added caveat of keeping it in a 32-bit range. Having done this, the change may as well be used for the MSVC64 and mingw64 ports, but it's not as critical.

No solutions so far, but this issue keeps cropping up from time-to-time and as far as I know it's not being tracked anywhere.

suggestion: detect obj wordsize mismatching chain type

I was just stumped for a while by a dumb mistake: I used -chain msvc to process x64 .obj files. The error that manifested was Unsupported relocation kind 0008; it would be nice if I had got .obj wordsize (64) mismatches selected chain wordsize (32) instead.

Maybe there's a technical reason for this check not being present, but I think it's more likely nobody's ever done anything as stupid as what I did before.

Option -custom-crt should not add MSVC linker option /nodefaultlib:LIBCMT

When one wants to use LIBCMT.lib in place of default CRT library MSVCRT.lib, it is not possible with FlexDLL v0.35, because option -custom-crt prevents both to use MSVCRT.lib and LIBCMT.lib.
It should only disable usage of MSVCRT.lib.

See reloc.ml lines 1005-1006:
if !custom_crt then "/nodefaultlib:LIBCMT /nodefaultlib:MSVCRT " ^ extra_args
else "msvcrt.lib " ^ extra_args
should be:
if !custom_crt then "/nodefaultlib:MSVCRT " ^ extra_args
else "msvcrt.lib " ^ extra_args

Thanks

flexlink produces an invalid dll when building lablgtk-2.18.3 on mingw64

Hi all,

I'm recently building lablgtk (a GTK2 wrapper for OCaml) using mingw64 toolchains provided by msys2. The package uses ocamlmklib (and thus flexlink) to create a dll library called dlllablgtk2.dll. Here are the version of the tools in my environment:

flexdll    0.34 (from http://alain.frisch.fr/flexdll.html; built from source)
ocaml    4.02.1 (built from source)

Flexlink generates the library without error, but the library is considered invalid by LoadLibraryEx:

Error: Error on dynamically loaded library: .\dlllablgtk2.dll: %1 is not a valid win32 application

The following toy program gives the same result.

$ cat testdll.c
#include <flexdll.h>
#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[]) {
    void *handle;
    printf("Try open: %s\n", argv[1]);
    handle = flexdll_dlopen(argv[1], FLEXDLL_RTLD_GLOBAL);
    printf("Handle: %p\n", handle);
    if (handle == NULL) {
            printf("Error code: %d\n", GetLastError());
            printf("Error message: %s\n", flexdll_dlerror());
    }
    return 0;
}

$ flexlink -chain mingw64 -exe -o testdll testdll.c
$ testdll.exe dlllablgtk2.dll
Try open: dlllablgtk2.dll
Handle: 0000000000000000
Error code: 193
Error message: %1 is not a valid win32 application

The library is created using 24 object files in addition to some system libraries. The command is:

flexlink -v -v -chain mingw64 -LD:/msys64/mingw64/x86_64-w64-mingw32/lib \
-o dlllablgtk2.dll -lpthread -LD:/msys64/mingw64/lib -lgtk-win32-2.0 \
-limm32 -lshell32 -lole32 -lpangocairo-1.0 -lpangoft2-1.0 -lpangowin32-1.0 -lgdi32 \
-lpango-1.0 -lm -latk-1.0 -lcairo -lpixman-1 -lfontconfig -lexpat -lfreetype -lexpat -lfreetype \
-lbz2 -lharfbuzz -lgdk_pixbuf-2.0 -lpng16 -lgio-2.0 -lz -lgmodule-2.0 -lgobject-2.0 -lffi \
-lglib-2.0 -lws2_32 -lole32 -lwinmm -lshlwapi -lintl \
ml_gobject.o ml_gpointer.o ml_gtk.o ml_gtkaction.o ml_gtkbin.o ml_gtkbroken.o ml_gtkbutton.o \
ml_gtkassistant.o ml_gtkedit.o ml_gtkfile.o ml_gtklist.o ml_gtkmenu.o ml_gtkmisc.o ml_gtkpack.o \
ml_gtkrange.o ml_gtkstock.o ml_gtktext.o ml_gtktree.o ml_gdkpixbuf.o ml_gdk.o ml_glib.o \
ml_pango.o ml_gvaluecaml.o wrappers.o

When I remove some of the objects (e.g. ml_gtktree.o), the generated library becomes valid.

$ testdll.exe dlllablgtk2.dll        # ml_gtktree.o removed from the command
Try open: dlllablgtk2.dll
Handle: 0000000000000000
Error code: 1114
Error message: Cannot resolve caml_failwith

It seems the issue is not raised by a single object. The library built without ml_gtktext.o (but with ml_gtktree.o) is also valid.

The binaries from https://github.com/shadinger/flexdll-win64 (version 0.26) does not suffer from this issue.

Here is the verbose log during linking.

** Use cygpath: true
** Search path:
D:/msys64/mingw64/lib
D:/msys64/mingw64/x86_64-w64-mingw32/lib
D:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2
/mingw/lib
/mingw64/x86_64-w64-mingw32/lib
** Default libraries:
dllcrt2.o
-lmingw32
-lgcc
-lmoldname
-lmingwex
-lmsvcrt
-luser32
-lkernel32
-ladvapi32
-lshell32
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\dllcrt2.o
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libmingw32.a
** open: D:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2\libgcc.a
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libmoldname.a
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libmingwex.a
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libmsvcrt.a
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libuser32.a
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libkernel32.a
** open: D:/msys64/mingw64/x86_64-w64-mingw32/lib\libadvapi32.a
+ x86_64-w64-mingw32-gcc -mconsole -shared -Wl,-eFlexDLLiniter  -L. -I"D:/msys64/mingw64/lib" -I"D:/msys64/mingw64/x86_64-w64-mingw32/lib" -L"D:/msys64/mingw64/lib" -L"D:/msys64/mingw64/x86_64-w64-mingw32/lib" -o "test.dll" "D:\msys64\tmp\dyndll3ef3ef.o" "D:\msys64\mingw64\bin\flexdll_initer_mingw64.o" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libpthread.dll.a" "D:/msys64/mingw64/lib\libgtk-win32-2.0.dll.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libimm32.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libshell32.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libole32.a" "D:/msys64/mingw64/lib\libpangocairo-1.0.dll.a" "D:/msys64/mingw64/lib\libpangoft2-1.0.dll.a" "D:/msys64/mingw64/lib\libpangowin32-1.0.dll.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libgdi32.a" "D:/msys64/mingw64/lib\libpango-1.0.dll.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libm.a" "D:/msys64/mingw64/lib\libatk-1.0.dll.a" "D:/msys64/mingw64/lib\libcairo.dll.a" "D:/msys64/mingw64/lib\libpixman-1.dll.a" "D:/msys64/mingw64/lib\libfontconfig.dll.a" "D:/msys64/mingw64/lib\libexpat.dll.a" "D:/msys64/mingw64/lib\libfreetype.dll.a" "D:/msys64/mingw64/lib\libbz2.dll.a" "D:/msys64/mingw64/lib\libharfbuzz.dll.a" "D:/msys64/mingw64/lib\libgdk_pixbuf-2.0.dll.a" "D:/msys64/mingw64/lib\libpng16.dll.a" "D:/msys64/mingw64/lib\libgio-2.0.dll.a" "D:/msys64/mingw64/lib\libz.dll.a" "D:/msys64/mingw64/lib\libgmodule-2.0.dll.a" "D:/msys64/mingw64/lib\libgobject-2.0.dll.a" "D:/msys64/mingw64/lib\libffi.dll.a" "D:/msys64/mingw64/lib\libglib-2.0.dll.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libws2_32.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libwinmm.a" "D:/msys64/mingw64/x86_64-w64-mingw32/lib\libshlwapi.a" "D:/msys64/mingw64/lib\libintl.dll.a" "D:\msys64\tmp\dyndll00be4c.o" "D:\msys64\tmp\dyndlle902c0.o" "D:\msys64\tmp\dyndll54d32d.o" "D:\msys64\tmp\dyndll2e0163.o" "ml_gtkbin.o" "D:\msys64\tmp\dyndll7ac0f6.o" "D:\msys64\tmp\dyndll3f46a1.o" "D:\msys64\tmp\dyndll6e7d00.o" "D:\msys64\tmp\dyndll709dae.o" "D:\msys64\tmp\dyndll4b5dee.o" "D:\msys64\tmp\dyndll027612.o" "D:\msys64\tmp\dyndll478b19.o" "D:\msys64\tmp\dyndll0fdffc.o" "D:\msys64\tmp\dyndll533488.o" "D:\msys64\tmp\dyndllc5412c.o" "D:\msys64\tmp\dyndllb81a8b.o" "D:\msys64\tmp\dyndll5f1731.o" "D:\msys64\tmp\dyndll4bc469.o" "D:\msys64\tmp\dyndlleed2db.o" "D:\msys64\tmp\dyndlla2929b.o" "D:\msys64\tmp\dyndll56c73c.o" "D:\msys64\tmp\dyndllde988f.o" "ml_gvaluecaml.o" "D:\msys64\tmp\dyndll049034.o" "D:\msys64\tmp\flexlink250fe6.def"
(call with bash: D:\msys64\tmp\longcmd233aa5)

reloc.ml: should not use String.lowercase_ascii

While investigating an issue related to ocaml/ocaml#1200, I noticed that there are several uses of String.lowercase_ascii applied to filenames in the module reloc.ml. It would be preferable not to use this function since those filenames may be UTF-8-encoded in the future.

Build against ocaml-4.08.0+beta3 fails

Build against ocaml-4.08.0+beta3 fails as Pervasives.compare is no longer available.

This fix worked for my specific situation:

--- reloc.ml.orig	2019-04-24 09:44:22.081768600 -0700
+++ reloc.ml	2019-04-24 09:46:11.136207400 -0700
@@ -498,7 +498,7 @@
   let strings = Buffer.create 1024 in
   let strsym = Symbol.intern sect 0l in
   obj.symbols <- strsym :: (Symbol.export symname sect 0l) :: obj.symbols;
-  let exports = List.sort Pervasives.compare exports in
+  let exports = List.sort compare exports in
   (* The runtime library assumes that names are sorted! *)
   int_to_buf data (List.length exports);
   List.iter

Fail to find a function in the executable (pg_query)

When compiling pg_query on Windows (patched to make it compiled), I have a pg_check command which fails:

Fatal error: exception Dl.DL_error("dlsym: no such symbol: \"pg_query_parse\"")

However, the pg_query_parse symbol is available:

$nm /cygdrive/c/Users/frede/AppData/Local/opam/default/bin/pg_check|grep pg_query_parse
00000001400c61c0 T pg_query_parse
00000001400c6250 T pg_query_parse_opts
00000001400c62e0 T pg_query_parse_protobuf
00000001400c6350 T pg_query_parse_protobuf_opts

Note, the pg_query library is based on ctypes.foreign. Then the issue may appear in other libraries.

Get rid of flexdll

It says in the notes that on Windows DLLs can't refer to symbols in the executable or previously loaded DLLs. The latter claim is not quite correct, it should say implicitly.

This is not actually a problem, it is correct behaviour and should NOT be fixed. Instead ocaml should be fixed. The issue is due to the historical development of Unix. Modern Unix linkers allow the archaic incorrect behaviour for compatibility but are moving away from it. OSX has moved well away and Linux is catching up with Windows too.

The correct way to link is to explicitly refer to a library. As mentioned, on Windows you have to link against a library to refer to its symbols because Windows actually uses a linker which has NO SUPPORT AT ALL for dynamic linkage. Windows always used a linker which could only do static linkage, so special import libraries are built which you link against instead. Calls to the symbols in the library trigger run time dynamic loading of a DLL and binding of the symbol at that time.

Linux and OSX also provide visibility control now and two level linkage, something that should have been enforced a long time ago. Unfortunately C and more recently C++ have impeded correcting the age old design fault. Still, it works right on OSX.

The question is: how can we build Ocaml correctly so we don't need flexdll? Currently I get the tiresome error "** Cannot resolve symbols for C:\ocaml\lib\libasmrun.lib(win32.obj): flexdll_wdlopen". I did have it working for Ocaml 4.02 but this is an upgrade someone built for Ocaml 4.06. "ocaml" works fine, the problem is only for ocamlopt.

MSYS2/ucrt64 support

By default MSYS2 doesn't have a prefixed windres tool in most of its environments (except for the mingw one which seems to fail due to unrelated reasons). When building flexdll vendored inside OCaml, the TOOLPREF variable gets set to x86_64-w64-mingw32-, which makes the compilation of flexdll fail under MSYS2 which doesn't have x86_64-w64-mingw32-windres but has windres

There is an issue upstream about the lack of prefixed windres tool here: msys2/MSYS2-packages#2595

However regardless of whether or not it is a good decision for such platform to have it or not, it would be nice for OCaml to compile without having to either patch the Makefile or create a custom windres binary/script/link.

While I'm not certain what this windres program is, maybe flexdll could do the following change:

version_res.o: version.rc
-        $(TOOLPREF)windres -i $< -o $@
+        $(TOOLPREF)windres -i $< -o $@ || windres -i $< -o $@

Relatedly there is also the following comment in configure.ac in ocaml/ocaml:

# Note: This is present for the flexdll bootstrap where it exposed as the old
# TOOLPREF variable. It would be better if flexdll where updated to require
# WINDRES instead.
AC_SUBST([ac_tool_prefix])

Side note: I remember talking with someone about this issue some months ago and I thought a ticket was opened somewhere but i couldn't find it anywhere so I'm creating it here to at least kickstart the discussion once more

Would a pull request allowing "__nm_" prefixes be accepted?

Working with https://github.com/ocaml-cross/opam-cross-windows which relies on flexdll, I hit a strange problem: for some C++ DLL I'm calling from OCaml, some symbols where prefixed with "__nm_". I do not know why?

I solved this by patching flexdll (see ocaml-cross/opam-cross-windows#108). I submitted this patch to https://github.com/ocaml-cross/opam-cross-windows, but if the solution to my problem is sane, it would be better to include it into flexdll.

This patch modifies aliases function (https://github.com/alainfrisch/flexdll/blob/master/coff.ml#L757-L766) for it to store both the whole symbol and the symbol without the "__nm_" prefix in the alias hash-table:

let aliases x =
    let a = ref [] in
    List.iter
      (fun s ->
         (match s.extra_info with
           | `Alias s' -> a := (s.sym_name,s'.sym_name) :: !a
           | _ -> ());
         if starts_with ~what:"__nm_" s.sym_name then
           a := (String.sub s.sym_name 5 (String.length s.sym_name - 5),
                s.sym_name) :: !a
      )
      x.symbols;
    !a

It works, but re-reading it, I think it should have been something like the following instead:

  let aliases x =
    let a = ref [] in
    List.iter
      (fun s ->
        match s.extra_info with
        | `Alias s' ->
            a := (s.sym_name, s'.sym_name) :: !a;
            if starts_with ~what:"__nm_" s.sym_name then
              a :=
                ( String.sub s.sym_name 5 (String.length s.sym_name - 5),
                  s'.sym_name )
                :: !a
        | _ -> () )
      x.symbols;
    !a

Anyway: after I would correct and test this, would such a PR be considered to be accepted in flexdll, or does it solve my problem the wrong way?

[Question] Linking MSVC libraries against MinGW

Can flexlink link MinGW and MSVC libraries to produce and exe/dll?

We are trying to write bindings for Skia (https://github.com/manuhornung/reason-skia)
and the it is recommended that we built Skia with MSVC on Windows (we are exploring mingw too)

Our first attempts were to compile the bindings with the mingw toolchain given the ecosystem support it has. To test these bindings we link the bindings into a test binary too (https://github.com/manuhornung/reason-skia/tree/master/bin_native)

Keeping in mind that the Skia library itself is an MSVC COFF, and that the bindings are being compiled with MinGW toolchain, I faced issues at two levels.

Compiling and linking the test binary with MinGW backed compiler, flexlink complained about unresolved MSVC symbols

** Cannot resolve symbols for C:\Users\manas\development\reason-skia\_esy\default\store\b\reason_skia-84a967d7\default\src\skia.lib(skia.obj):
 ??0SkFILEWStream@@QEAA@QEBD@Z
 ??0SkFont@@QEAA@V?$sk_sp@VSkTypeface@@@@MMM@Z
 ??0SkPaint@@QEAA@XZ
??0SkSurfaceProps@@QEAA@IW4SkPixelGeometry@@@Z

Those symbols are from skia.cpp stubs in reason-bindings

On trying to link with flexlink compiled with MSVC toolchain, I faced the following

** Cannot resolve symbols for C:\users\manas\development\flexdll\flexdll_msvc.obj:
 _memcpy
 _strcmp
 _strlen
** Cannot resolve symbols for C:\Users\manas\.esy\3_\i\ocaml-4.6.10-7ba95816\lib\ocaml\libasmrun.a(floats.o):
 __strtod
Fatal error: exception Failure("Unsupported relocation kind 0004 for __strtod in C:\\Users\\manas\\.esy\\3_\\i\\ocaml-4.6.10-7ba95816\\lib\\ocaml\\libasmrun.a(floats.o)")

I did so by cloning and checking out latest stable tag, and simply ran the linking subcommand that ocamlopt uses on Windows. Note that it is still the MinGW built OCaml compiler. So flexlink failed to link the MinGW archive against skia.lib (MSVC COFF)

  1. Does flexlink account for any kind of binary compatibility so that it can link the two libraries (from different compilers). I understand the chances are slim and MinGW itself very vaguely says yes.

  2. Is flexlink absolutely necessary for ocamlopt on Windows even for static linking?

  3. Is it wrong to expect flexlink to link MinGW and MSVC libraries together? And that we should have used a the compiler built with MSVC toolchain from the get-go?

Flexdll is incompatible with visual studio 2017.3

When compiling ocaml with visual studio 2017.3 I get the following error message during linking of the unix library:

Creating library C:\cygwin\tmp\dyndll_implib571fa3.lib and object 
 C:\cygwin\tmp\dyndll_implib571fa3.exp
 C:\cygwin\tmp\dyndll_implib571fa3.lib : fatal error LNK1136: invalid or corrupt file

contrib - visual studio 2015 integrated example

dlltest10.zip

Here I've made a visual studio 2015 integrated example of using flexdll.
Open the sln, set startup project to exe, and set debug working directory to $(ProjectDir).run

You will now get working builds for debug/release & x86/x64. A working example prints this:

in main
99
now: 0

The project includes the latest master flexlink.exe build as of now (needed for x64 debugging reloc fixes); as well, I've had to rebuild the flexdll_*.obj using vs2015 toolchain (scripts for doing this are provided)

The project also contains my program linkwrap which I think was required to get the nice VS/msbuild building semantics I wanted. Chiefly, it rips apart the response file provided to msvc's link.exe from VS and analyzes it to determine wordsize and lib/obj dependencies for passing to flexdll's flexlink.exe

The vcxprojs have been modified simply to incorporate flexdll as an improved linker, by setting these things in the project:

<PropertyGroup Label="Globals">
  <LinkToolPath>$(ProjectDir)flexdll</LinkToolPath>
  <LinkToolExe>linkwrap.exe</LinkToolExe>
</PropertyGroup>

Note: you cannot use link-time code generation with flexdll. It's on by default in vcxprojs; I have turned it off. This should come as no great surprise as it probably incorporates a great deal of inscrutable proprietary junk (the problem will manifest as some kind of a premature EOF error while reading a .obj input)

The test confirms the main functionality I was interested in:

  1. a dll can leave an unresolved external to a global variable in the main program
  2. the dll can export functions without dllexport
  3. the global variable is correctly shared between the modules
  4. I can debug from the main and into the dll and back out

TODO - I haven't tested this with additional library directories. I will probably need to update it for that. I just need to get a WIP committed, so that's what you're seeing here.

Temporary files not deleted on exit

After a full build of OCaml 5 with the MinGW toolchain, I see about 30 dyndllXXXXXX.o files left over in /tmp.

I suspect these files were created by flexlink.

On CI machines, after a few hundred builds, /tmp becomes so cluttered as to slow down builds noticeably and cause problems with ssh logins.

Support gcc "-Wl" linker pass through option

This is a follow up on the discussion on Coq PR 9729:

coq/coq#9279

If flexlink would support -Wl as synonym for -link, libraries which use -Wl options could be compiled without changes in the build instructions on Windows.

I will provide a PR, but only for simple cases of the -Wl syntax.

flexlink should cygpath %TEMP% before passing to bash

cd _boot && C:\ocamlmgw64\bin\ocamlopt.opt.exe -o ..\dune.exe -g -I +threads unix.cmxa threads.cmxa -no-alias-deps -w -49 fcntl_stubs.c -args mods_list
/bin/bash: C:UsersDRAAppDataLocalTemplongcmd7285c9: No such file or directory

Placeholder to check when I have more time, but changing TEMP to C:/Users/DRA/AppData/Local/Temp "fixed" the problem

** Fatal error: Cannot parse directive: -exclude-symbols:__alloca

I'm currently getting this error while trying to build an ocaml package. I have no idea where -exclude-symbols:__alloca is coming from but it seems like flexlink is not able to parse it.
I cannot share the source code but I'll do my best to provide whatever additional context needed.
Thank you in advance

Linking dlls?

I have two problems in trying to resurrect the wxwidgets ocaml binding.

  1. In trying to get flexdll to see a wx dll the -explain shows it not being visited at all.
    I'm too thick to understand whether flexdll is meant to only create a dll or whether it actually incorporates dependencies on others. It appears not though Gnu ld on my cygwin system does!

  2. Some missing symbol errors including:

__ZTVN10__cxxabiv117__class_type_infoE

Which should have been taken care of by -lstdc++
But -explain shows it picking up libstdc++.dll.a
which contains an indirection mark I for that symbol
but doesn't look at libstdc++.a which has an R mark for it, meaning in the read-only section.
What's going on?!

line in response file wrongly interpreted as option by MSVC linker

In win64 environment, a file to be linked may be of the form \server\path\to\obj

If the command line is too long, this is dumped into a response file, but the function build_diversion in reloc.ml, specifically converts file-paths to use "/" instead of "". As a result the above file is interpreted as an option to the "link" command then fails to link files.

There does not seem to be an easy workaround to this problem, as the option to use response file is not user-controllable

msvc linker response file should be UTF-16 encoded when possible

Currently we use a response file to pass arguments to the msvc linker when the command line is too long.

Supported encodings for the response file are ANSI (currently used) and UTF-16: see https://msdn.microsoft.com/en-us/library/xwy0e8f2(v=vs.140).aspx.

In order to make flexlink work with Unicode (cf ocaml/ocaml#1200) we need to use UTF-16 (here I am thinking about the situation when our OCaml strings are UTF-8). I made a quick proof of concept with a handwritten UTF-8 decoder and it fixed the problems I was seeing.

Ideally this functionality would be enabled as soon as flexlink is compiled with a Unicode-enabled ocamlc, but am not sure if this is easy to do.

Ideas ?

`-print-search-dirs` may return `;`-delimited mixed paths on MSYS2

Partially a TODO item to check, unless someone else can confirm/disprove in the meantime, as I don't have a relevantly-configured machine to hand.

in:
https://github.com/alainfrisch/flexdll/blob/3255266d71813572b771f4946ed932912c760a7c/reloc.ml#L1260-L1263
there are several assumptions:

  • get_lib_search_dirs assumes that the list is :-separated
  • normalize_path assumes Unix-style paths

Both of these assumptions are valid for Cygwin-compiled mingw compilers, but I'm not sure they are valid for MSYS2, where gcc is (can be?) a native Windows executable and returns ;-separated mixed-mode paths.

Compiling z3 ml's API with cygwin

It appears that can be a flexdll related issue. Could you guys confirm ? Maybe something related to elf lib file "libz3ml.a".

I'm using ocaml 4.03.0 and flexdll-0.35.

$ make
ocamlc  -i -I api/ml -c ../src/api/ml/z3enums.ml > api/ml/z3enums.mli
ocamlc  -I api/ml -o api/ml/z3enums.cmi -c api/ml/z3enums.mli
ocamlc  -I api/ml -o api/ml/z3enums.cmo -c ../src/api/ml/z3enums.ml
ocamlc  -i -I api/ml -c ../src/api/ml/z3native.ml > api/ml/z3native.mli
ocamlc  -I api/ml -o api/ml/z3native.cmi -c api/ml/z3native.mli
ocamlc  -I api/ml -o api/ml/z3native.cmo -c ../src/api/ml/z3native.ml
cp ../src/api/ml/z3.mli api/ml/z3.mli
ocamlc  -I api/ml -o api/ml/z3.cmi -c api/ml/z3.mli
ocamlc  -I api/ml -o api/ml/z3.cmo -c ../src/api/ml/z3.ml
ocamlc  -ccopt "-D_MP_INTERNAL -DNDEBUG -D_EXTERNAL_RELEASE -std=c++11 -fvisibility=hidden -c -mfpmath=sse -msse -msse2 -D_NO_OMP_ -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer -D_CYGWIN -fno-strict-aliasing -I /home/anmap/.opam/4.03.0/lib/ocaml -I ../src/api -I ../src/api/ml -o api/ml/z3native_stubs.o" -c ../src/api/ml/z3native_stubs.c
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
ocamlmklib -o api/ml/z3ml -I api/ml api/ml/z3native_stubs.o api/ml/z3enums.cmo api/ml/z3native.cmo api/ml/z3.cmo  libz3.dll
ocamlopt  -I api/ml -o api/ml/z3enums.cmx -c ../src/api/ml/z3enums.ml
ocamlopt  -I api/ml -o api/ml/z3native.cmx -c ../src/api/ml/z3native.ml
ocamlopt  -I api/ml -o api/ml/z3.cmx -c ../src/api/ml/z3.ml
ocamlmklib -o api/ml/z3ml -I api/ml api/ml/z3native_stubs.o  api/ml/z3enums.cmx api/ml/z3native.cmx api/ml/z3.cmx libz3.dll
ocamlopt  -shared -o api/ml/z3ml.cmxs -I api/ml api/ml/z3ml.cmxa
** Fatal error: Error while reading api/ml/libz3ml.a: Invalid_argument("String.create")
File "caml_startup", line 1:
Error: Error during linking
make: *** [Makefile:4370: api/ml/z3ml.cmxs] Error 2

[Question] How does Flexdll handling name mangling

As a follow up to #75, I'm using MSVC toolchain all through out, to compile Skia bindings.

  1. skia.lib is compiled with MSVC as described in the official docs
  2. Skia APIs are written in C++ and dont have extern C. So the stubs are written in C++ by hand (no ctypes) contain the extern C prefixes.
  3. I'm using fdopen's opam in cygwin with MSVC switch. OCaml 4.07.1

Flexlink complains of unresolved symbols from Skia. Looks like a name mangling issue.

** Cannot resolve symbols for src\libskia_stubs.lib(skia.obj):
 ?setStrokeJoin@SkPaint@@QEAAXW4Join@1@@Z
 ?setStrokeMiter@SkPaint@@QEAAXM@Z
 ?setStrokeWidth@SkPaint@@QEAAXM@Z
 ?setStyle@SkPaint@@QEAAXW4Style@1@@Z
 ?setSubpixel@SkFont@@QEAAX_N@Z
 ?sk_abort_no_print@@YAXXZ
 ?toSkColor@?$SkRGBA4f@$02@@QEBAIXZ
File "caml_startup", line 1:
Error: Error during linking

(truncated for brevity)

stubs.cpp (the bindings) is linked against skia.lib

@lib.exe /out:bindings.lib bindings.obj %esy_skia_install%/out/Release/skia.lib

And this library file is passed to ocamlmklib

ocamlmklib -o skia_stubs bindings.lib

Tiny visual aid

 libskia_stubs <- bindings.lib (contain extern C) <- skia.lib (no extern C)

Can flexlink handling name mangling correctly in this case? Alternatively, how we use flexlink to link to C++ APIs that don't ship with extern "C"

findlib sometimes cannot be built on Windows

I'm not sure if this is the right place to report this, but there seems to be a nondeterministic issue with the setup of OCaml/opam on Windows:

<><>Processing actions<><><><><><><><><><><><><><><><><><><><><><><><><><><><>
[ERROR] The compilation of ocamlfind failed at "D:\\cygwin\\bin\\make.exe opt".
-> installed conf-findutils.1
-> installed conf-gmp.4
-> installed dune.3.3.1
#===ERRORwhile compiling ocamlfind.1.9.5====================================#
#context     2.0.10 | win32/x86_64 | ocaml-variants.4.11.1+mingw64c | git+https://github.com/fdopen/opam-repository-mingw.git#opam2
#path        D:/a/fiat-crypto/fiat-crypto/_opam/.opam-switch/build/ocamlfind.1.9.5
#command     D:\cygwin\bin\make.exe opt
#exit-code   2
#env-file    D:/.opam/log/ocamlfind-1[38](https://github.com/mit-plv/fiat-crypto/runs/7199984869?check_suite_focus=true#step:14:39)4-03b1a4.env
#output-file D:/.opam/log/ocamlfind-1384-03b1a4.out
### output ###
# for p in findlib; do ( cd src/$p; /usr/bin/make opt ) || exit; done
# make[1]: Entering directory '/cygdrive/d/a/fiat-crypto/fiat-crypto/_opam/.opam-switch/build/ocamlfind.1.9.5/src/findlib'
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c findlib_config.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_split.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_metatoken.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_meta.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_metascanner.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_topo.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_package_base.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c findlib.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_args.ml
# ocamlopt -I +compiler-libs -g -opaque  -I +unix -I +dynlink -c fl_lint.ml
# ocamlopt -I +compiler-libs -g -a -o findlib.cmxa findlib_config.cmx fl_split.cmx fl_metatoken.cmx fl_meta.cmx fl_metascanner.cmx fl_topo.cmx fl_package_base.cmx findlib.cmx fl_args.cmx fl_lint.cmx
# if [ 1 -gt 0 ]; then \
#     ocamlopt -I +compiler-libs -g -shared -o findlib.cmxs findlib_config.cmx fl_split.cmx fl_metatoken.cmx fl_meta.cmx fl_metascanner.cmx fl_topo.cmx fl_package_base.cmx findlib.cmx fl_args.cmx fl_lint.cmx; \
# fi
# ** Fatal error: Cannot run cygpath -m findlib.cmxs
# File "caml_startup", line 1:
# Error: Error during linking (exit code 2)
# make[1]: *** [Makefile:71: findlib.cmxa] Error 2
# make[1]: Leaving directory '/cygdrive/d/a/fiat-crypto/fiat-crypto/_opam/.opam-switch/build/ocamlfind.1.9.5/src/findlib'
# make: *** [Makefile:18: opt] Error 2
<><>Error report<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
+- The following actions failed
| - build ocamlfind 1.9.5
+- 
+- The following changes have been performed (the rest was aborted)
| - install conf-findutils 1
| - install conf-gmp       4
| - install dune           3.3.1
+- 
[NOTE] Pinning command successful, but your installed packages may be out of sync.

https://github.com/mit-plv/fiat-crypto/runs/7199984869?check_suite_focus=true#step:14:68

Support for /alternatename: linker directive needed for x86

I can see the problem clearly in 32-bit code, although it doesn't look like it is limited to 32-bit code.

Here is the invocation of flexlink 0.42 (edited to split newlines):

flexlink.exe ^
-o src\ActorSystem\system.exe -U /out:src\ActorSystem\system.exe -implib ^
-L C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\lib\x86 ^
-L C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x86 ^
-L C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\ucrt\x86 ^
-L C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x86 ^
-L Z:\source\DkHelloWorldActor\build_community\DkSDKFiles\o\s\o\lib\ocaml ^
src\ActorSystem\DkHelloWorldActor_system.lib advapi32.lib ws2_32.lib version.lib -exe ^
-no-merge-manifest -custom-crt msvcrt.lib -chain msvc -stack 16777216 ^
-L Z:\source\DkHelloWorldActor\build_community\DkSDKFiles\o\s\o\lib\ocaml src\ActorSystem\DkHelloWorldActor_system.lib ^
advapi32.lib ws2_32.lib version.lib libasmrund.lib src\ActorSystem\CMakeFiles\system.dir\_main.c.obj ^
-- ^
/nologo /pdb:src\ActorSystem\system.pdb ^
/version:0.0 /ENTRY:wmainCRTStartup /machine:X86 /debug /INCREMENTAL /subsystem:console ^
/MANIFEST /MANIFESTFILE:src\ActorSystem\CMakeFiles\system.dir/intermediate.manifest ^
src\ActorSystem\CMakeFiles\system.dir/manifest.res

which gives:

failed (exit code 2) with the following output:
** Cannot resolve symbols for C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\lib\x86\msvcrt.lib(d:\agent\_work\2\s\Intermediate\vctools\msvcrt.nativeproj_110336922\objr\x86\chandler4gs.obj):
 __filter_x86_sse2_floating_point_exception

The root cause seems to be the Linker Directives:

dumpbin /all 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\lib\x86\msvcrt.lib' | grep -B100 -10 -E 'Archive member name|filter_x86_sse2'

...
   4950F4 __filter_x86_sse2_floating_point_exception_default
...
      4D6 __filter_x86_sse2_floating_point_exception_default
...
Archive member name at 65B67A: /124277         d:\agent\_work\2\s\Intermediate\vctools\msvcrt.nativeproj_110336922\objr\x86\chandler4gs.obj
5EA42E04 time/date Sat Apr 25 05:33:08 2020
         uid
         gid
  100666 mode
    54F8 size
correct header end

FILE HEADER VALUES
             14C machine (x86)
               7 number of sections
        5EA42E04 time date stamp Sat Apr 25 05:33:08 2020
            52C5 file pointer to symbol table
              16 number of symbols
               0 size of optional header
               0 characteristics

SECTION HEADER #1
.drectve name
       0 physical address
       0 virtual address
      70 size of raw data
     12C file pointer to raw data (0000012C to 0000019B)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
  100A00 flags
         Info
         Remove
         1 byte align

RAW DATA #1
  00000000: 20 20 20 2F 61 6C 74 65 72 6E 61 74 65 6E 61 6D     /alternatenam
  00000010: 65 3A 5F 5F 66 69 6C 74 65 72 5F 78 38 36 5F 73  e:__filter_x86_s
  00000020: 73 65 32 5F 66 6C 6F 61 74 69 6E 67 5F 70 6F 69  se2_floating_poi
  00000030: 6E 74 5F 65 78 63 65 70 74 69 6F 6E 3D 5F 5F 66  nt_exception=__f
  00000040: 69 6C 74 65 72 5F 78 38 36 5F 73 73 65 32 5F 66  ilter_x86_sse2_f
  00000050: 6C 6F 61 74 69 6E 67 5F 70 6F 69 6E 74 5F 65 78  loating_point_ex
  00000060: 63 65 70 74 69 6F 6E 5F 64 65 66 61 75 6C 74 20  ception_default

   Linker Directives
   -----------------
   /alternatename:__filter_x86_sse2_floating_point_exception=__filter_x86_sse2_floating_point_exception_default

...
COFF SYMBOL TABLE
...
00D 00000000 UNDEF  notype ()    External     | __filter_x86_sse2_floating_point_exception

Fatal Error: Cannot run cygpath -m - command - The command line is too long

Our esy build fails on Windows when running ocamlopt.exe w/ lots of includes.

The relevant portion is:

** Fatal error: Cannot run cygpath -m "libadvapi32" "libadvapi32.lib" "libadvapi32.dll.a" "libadvapi32.a" "C:/Users/bryph/.esy/3_/i/opam__slash__ocamlfind-1.8.0-12c842a0/lib/ocaml\libadvapi32" "C:/Users/bryph/.esy/3_/i/opam__slash__ocamlfind-1.8.0-12c842a0/lib/ocaml\libadvapi32.lib" 
...

Full log

This is running ocaml 4.6.0, with v0.37 of flexdll.

Command line too long

I'm using cygwin, the mingw64 toolchain and I get the error.
It comes from Reloc.cygpath, that in turns calls get_output with use_bash:false.
The quick hack was to force it to use bash, but what could be done (in the non use_bash case) is to use Unix.create_process instead of Sys.command, since the former does not use a shell (no cmd.exe, so more than 8k for argv). See for example sys_command in https://github.com/coq/coq/blob/trunk/lib/cUnix.ml

Best,

Fix parallel access to global symbol structures

The list of loaded units is defined globally in flexdll.c:

static dlunit *units = NULL;

and is accessed in parallel both by flexdll_*dlopen and flexdll_dlsym without using a lock. Adding locks around flexdll_*dlopen is straightforward, but symbol lookup operates a most-recently-used queue on the global, and the performance impact either of removing that or, worse, of putting a lock around flexdll_dlsym is less clear.

In the meantime, reverting ocaml/ocaml#11607 provides an easy test-case for demonstrating the failure (the test usually fails within a few runs)

Generate import library for exported function of the main executable file

There is a statement in your project home page:

Windows DLL cannot refer to symbols defined in the main application or in previously loaded DLLs.

Some usual solutions exist, but they are not very flexible. A notable exception is the edll library (its homepage also describes the usual solutions), which follows a rather drastic approach; indeed, edll implements a new dynamic linker which can directly load object files (without creating a Windows DLL).

While, it looks like I can do this with the tool gendef and dlltool.

The method I was using is like:

For example, the exe_export.exe has some code like:

#include <Windows.h>
#include <stdio.h>

#define MYDLL_EXPORTS

#include "interface_exe.h"

void appli_printf7777(void)
{
   printf("7777");
   return;
}

void appli_printf8888(void)
{
   printf("8888");
   return;
}


int main(void)
{
   HMODULE hModule = LoadLibrary("dll.dll");
   FARPROC pFunc = GetProcAddress(hModule, "dllFunction");

   ((DLL_FUNC)pFunc)();

   return 0;
}

The content of the interface_exe.h is like below:

#ifndef INTERFACE_EXE_H_INCLUDED
#define INTERFACE_EXE_H_INCLUDED


 #ifdef  MYDLL_EXPORTS
    /*Enabled as "export" while compiling the dll project*/
    #define DLLEXPORT __declspec(dllexport)
 #else
    /*Enabled as "import" in the Client side for using already created dll file*/
    #define DLLEXPORT __declspec(dllimport)
 #endif

#ifdef __cplusplus
extern "C"
{
#endif

typedef void(*DLL_FUNC)(void);

DLLEXPORT void appli_printf7777(void);

DLLEXPORT void appli_printf8888(void);


#ifdef __cplusplus
}
#endif

#endif // INTERFACE_EXE_H_INCLUDED

And I have another dll.cpp file which is used to generate the dll.

#include <Windows.h>
#include <stdio.h>

#include "interface_exe.h"


#ifdef __cplusplus
extern "C"
{
#endif

__declspec (dllexport) void dllFunction(void);

#ifdef __cplusplus
}
#endif




typedef void(*APPLI_PRINTF7)(void);

__declspec(dllexport) void dllFunction(void)
{
   //HMODULE hModule = LoadLibrary("exe_export.exe");
   FARPROC pFunc = GetProcAddress(0, "appli_printf7777");

   if(pFunc)
      ((APPLI_PRINTF7)pFunc)();
   else
      printf("error = %d\n", GetLastError());

   appli_printf7777();
   appli_printf8888();

   return;
}

I first build the exe_export.exe file, and later I use the commands below to generate the import .a file:

gendef exe_export.exe
dlltool --dllname exe_export.exe --def exe_export.def --output-lib libexe_export.a

Then later, I link the libexe_export.a file to generate the dll.

Now, when I run the exe file, I have two methods to call the methods in the dll.

One is using the GetProcAddress method.

   //HMODULE hModule = LoadLibrary("exe_export.exe");
   FARPROC pFunc = GetProcAddress(0, "appli_printf7777");

   if(pFunc)
      ((APPLI_PRINTF7)pFunc)();
   else
      printf("error = %d\n", GetLastError());

The other is using the imported method, which I can directly call

   appli_printf7777();
   appli_printf8888();

All works fine.

Here are some reference:
1, the method I use is described as the .def and .a method, see this discussion:
Enhanced DLL / Discussion / Help and FAQ: The .def and .a method mentioned in the home page

2, https://www.codeproject.com/Articles/17697/Plugin-System-an-alternative-to-GetProcAddress-and
The method mentioned in this link is using MSVC, and I think it is similar with the gendef and dlltool method.

3, my demo code was changed from the sample code in this discussion:
Exporting symbols in a .exe for external DLLs

Hope the above method can help others.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.