Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Another static linking issue #541

Closed
imeckler opened this issue Aug 26, 2017 · 3 comments
Closed

Another static linking issue #541

imeckler opened this issue Aug 26, 2017 · 3 comments

Comments

@imeckler
Copy link

imeckler commented Aug 26, 2017

I'm on ubuntu, trying to link in a static library (a .a file.) It's a bit unclear what command is being executed since I'm using oasis, but the relevant part of my _oasis file looks like

  CCLib:  -LPATH_TO_LIBARAY -lmylib
  CCOpt: -static -LPATH_TO_LIBRARY

When I run my program I get

Uncaught exception:
  
  Dl.DL_error("./main.native: undefined symbol: field_delete")

Raised at file "src/ctypes-foreign-base/dl.ml", line 42, characters 20-44
Called from file "src/ctypes-foreign-base/ctypes_foreign_basis.ml", line 47, characters 19-47
Re-raised at file "src/ctypes-foreign-base/ctypes_foreign_basis.ml", line 49, characters 50-59
Called from file "src/test1.ml", line 23, characters 4-67

I also tried adding the flags -Wl,-E and -Wl,-no-as-needed which I got from reading other issues, but they didn't help. Any help would be greatly appreciated!

@imeckler
Copy link
Author

I finally got the library to get linked in statically, so that the compiled binary does contain the symbol field_delete (provided by mylib.a), but I still get the same error when I run the compiled binary. Can I somehow tell ctypes that the symbol of interest is in the binary?

@imeckler
Copy link
Author

Got it figured out. For posterity my _oasis file now looks like

  CCLib: -Wl,-E -LPATH_TO_LIBRARY -lstdc++ -Wl,-whole-archive -l:libmylib.a -Wl,-no-whole-archive
  CCOpt: -x c++

@constfun
Copy link

constfun commented Feb 9, 2018

The following is a (simple) hack (see bottom of post), but it worked for me. I'm using jbuilder/dune in my case, but I don't think it matters. (-Wl,-E didn't work for me either.)

My setup/problem, for posterity

My use case is writing bindings for a library that is shipped as a single C file. The library doesn't have any additional dependencies. Simple enough one would think...

I have these files:

thelib.c
thebindings.ml
jbuild

cat jbuild:

(jbuild_version 1)

(library
 ((name thebindings)
  (libraries (ctypes.foreign))
  (c_names (thelib))
  (c_flags (-pedantic -std=c89))))

c_flags matter for my target library, but not in general.

I then use these bindings in another project as normal:

(jbuild_version 1)

(executable
 ((name cli)
  (libraries (thebindings))
 ))

This compiles fine with jbuilder build cli.exe, but when I run the executable I get the same error, undefined symbol. Looking at the binary with nm I can see that thelib symbols are indeed not present. Looking at thebindings .a and .dylib artifacts the symbols are there. This leads me to think that the bindings are linked into the library correctly, but are dropped/optimized away when linking the cli executable (setting -linkall for the executable doesn't help).

The hack

Then there is this helpful bit from @pqwy in #167:

Binding it via:

external foo : unit -> int = "foo"

... picks it up, however.

All I want is to force thelib.o to be linked in, any time thebindings is linked in. Using the external keyword and referencing some symbol from thelib.o seems to do the job.

All I did is put the following at the top of thebindings.ml file, before the normal foreign Ctypes definitions.

external _force_link_ : unit -> unit = "thelib_some_function_from_there"

open Ctypes
open Foreign
...

I don't think it matter which symbol you reference, and you can still bind using Ctypes to the same symbol. The external simply forces the linker to carry the thelib.o symbols through to the final executable.

I'm sure there is a more sane way to do this, but I have to move on at this point. I hope this is helpful to someone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants