ocaml build system

I have an issue with the OCaml build system and the ExecutionEngine.

PR2128 has a patch to change the Interpreter to use libffi. This breaks test/Bindings/Ocaml/executionengine.ml because OCaml doesn't try to link with libffi, even though llvm-config knows that we should:

   $ Debug/bin/llvm-config --ldflags interpreter
   -L/home/nicholas/llvm-commit/Debug/lib -lpthread -lffi -ldl -lm -lelf

If I run 'ocamlc' by hand and pass it '-cclib -lffi', the test succeeds, so this is the only remaining problem. Is anyone familiar with how Ocaml knows what libraries to link against? We can't just pass `llvm-config --ldflags interpreter` to ocamlc because it doesn't support the -L argument.

Does anyone have any ideas how this ought to work?

Nick

PS. why is it Bindings/Ocaml and not Bindings/OCaml?

I have an issue with the OCaml build system and the ExecutionEngine.

PR2128 has a patch to change the Interpreter to use libffi. This breaks test/Bindings/Ocaml/executionengine.ml because OCaml doesn’t try to link with libffi, even though llvm-config knows that we should:

$ Debug/bin/llvm-config --ldflags interpreter
-L/home/nicholas/llvm-commit/Debug/lib -lpthread -lffi -ldl -lm -lelf

If I run ‘ocamlc’ by hand and pass it ‘-cclib -lffi’, the test succeeds, so this is the only remaining problem. Is anyone familiar with how Ocaml knows what libraries to link against? We can’t just pass llvm-config --ldflags interpreter to ocamlc because it doesn’t support the -L argument.

Does anyone have any ideas how this ought to work?

The linker flags for each .cma (ocaml library) are baked in by ocaml. Here’s the relevant section from Makefile.ocaml:

Info from llvm-config and similar

ifdef UsedComponents
UsedLibs = $(shell $(LLVM_CONFIG) --libs $(UsedComponents))
UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents))
endif

Tools

OCAMLCFLAGS += -I $(OcamlDir) -I $(ObjDir)
ifneq ($(ObjectsO),)
OCAMLAFLAGS += $(patsubst %,-cclib %,
$(filter-out -L$(LibDir),-l$(LIBRARYNAME)
$(shell $(LLVM_CONFIG) --ldflags))
$(UsedLibs))
else
OCAMLAFLAGS += $(patsubst %,-cclib %,
$(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags))
$(UsedLibs))
endif

This transforms “x y z” from llvm-config into “-cclib x -cclib y -cclib z”, which instructs ocaml to pass “x y z” down to the linker when creating an executable. The UsedComponents variable originates in this case from bindings/ocaml/executionengine/Makefile:

LEVEL := …/…/…
LIBRARYNAME := llvm_executionengine
DONT_BUILD_RELINKED := 1
UsedComponents := executionengine jit interpreter native
UsedOcamlInterfaces := llvm llvm_target

include …/Makefile.ocaml

I don’t see anything obviously wrong here; it seems that llvm-config -ldflags executionengine jit interpreter native should be invoked, which should give you the -cclib -lffi you seek. make VERBOSE=1 and/or TOO_VERBOSE=1 should show you the full ocaml command lines; maybe that’ll show where -lffi is getting dropped on the floor.

— Gordon

Gordon Henriksen wrote:

I have an issue with the OCaml build system and the ExecutionEngine.

PR2128 has a patch to change the Interpreter to use libffi. This breaks test/Bindings/Ocaml/executionengine.ml because OCaml doesn't try to link with libffi, even though llvm-config knows that we should:

$ Debug/bin/llvm-config --ldflags interpreter
-L/home/nicholas/llvm-commit/Debug/lib -lpthread -lffi -ldl -lm -lelf

If I run 'ocamlc' by hand and pass it '-cclib -lffi', the test succeeds, so this is the only remaining problem. Is anyone familiar with how Ocaml knows what libraries to link against? We can't just pass `llvm-config --ldflags interpreter` to ocamlc because it doesn't support the -L argument.

Does anyone have any ideas how this ought to work?

The linker flags for each .cma (ocaml library) are baked in by ocaml. Here's the relevant section from Makefile.ocaml:

    # Info from llvm-config and similar
    ifdef UsedComponents
    UsedLibs = $(shell $(LLVM_CONFIG) --libs $(UsedComponents))
    UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents))
    endif

    # Tools
    OCAMLCFLAGS += -I $(OcamlDir) -I $(ObjDir)
    ifneq ($(ObjectsO),)
    OCAMLAFLAGS += $(patsubst %,-cclib %, \
                     $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \
                                              $(shell $(LLVM_CONFIG)
    --ldflags)) \
                                              $(UsedLibs))
    else
    OCAMLAFLAGS += $(patsubst %,-cclib %, \
                     $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG)
    --ldflags)) \
                                              $(UsedLibs))
    endif

This transforms "x y z" from llvm-config into "-cclib x -cclib y -cclib z", which instructs ocaml to pass "x y z" down to the linker when creating an executable. The UsedComponents variable originates in this case from bindings/ocaml/executionengine/Makefile:

    LEVEL := ../../..
    LIBRARYNAME := llvm_executionengine
    DONT_BUILD_RELINKED := 1
    * UsedComponents := executionengine jit interpreter native *
    UsedOcamlInterfaces := llvm llvm_target

    include ../Makefile.ocaml

I don't see anything obviously wrong here; it seems that llvm-config -ldflags executionengine jit interpreter native should be invoked, which should give you the -cclib -lffi you seek. make VERBOSE=1 and/or TOO_VERBOSE=1 should show you the full ocaml command lines; maybe that'll show where -lffi is getting dropped on the floor.

Thanks for the explanation. It looks like what really happened is that the .cma files weren't regenerated when llvm-config changed. After refreshing bindings/ocaml and rebuilding LLVM, the test passes.

Nick