Skip to content

Conversation

MartinNowak
Copy link
Member

  • avoids issues with versioned symbols on different platforms
  • lazy loading/initialization of curl library
  • quick unittests now also need $(LINKDL)

Issue 13324 – dynamically load libcurl at runtime

@MartinNowak MartinNowak force-pushed the loadCurlAtRuntime branch 3 times, most recently from 9d563d4 to fd5465e Compare February 20, 2015 04:03
@quickfur
Copy link
Member

Briefly looked over it, the overall implementation seems OK. Don't have time right now to look at it in detail, though. Hopefully other reviewers will chime in...

else
static assert(0, "unimplemented");

enforce!CurlException(handle !is null, "Failed to load libcurl.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried that this error will be thrown at people currently linking with curl libraries with non-standard or fringe names, and they won't know which names are tried without looking at the source code. Maybe it's a good idea to include the list of tried names in the exception message? If it's going to be a breaking change for them, we should at least make it as comfortable as possible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmh, I spent some effort trying to find all relevant names. How would someone rename their libcurl.
I might look through a few more implementations, e.g. perl to see what works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added one name libcurl-nss.so.4 which is one of the libcurl flavors on ubuntu, couldn't find anything relevant besides this.

@MartinNowak
Copy link
Member Author

I shortly enabled the std.net.curl tests to see whether I was missing something, but they pass on all platforms.
MartinNowak@090aaad
https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=3&pullid=3009

{
// initialize early to prevent thread races
enforce!CurlException(!curl_global_init(CurlGlobal.all),
"Couldn't initialize libcurl");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer call curl_global_init anywhere explicitly, is this OK?

It is called above: _api.global_init

@CyberShadow
Copy link
Member

Not 100% sure about this... this change means that it will be impossible to statically link libcurl by substituting the import library with a static one.

@MartinNowak
Copy link
Member Author

I could try to load the symbols from the binary itself, but for that to work, you need to use the export-dynamic switch, not sure if that works on windows.

@CyberShadow
Copy link
Member

lazy loading/initialization of curl library

Lazy loading has its disadvantages (sometimes it's better to fail fast).

avoids issues with versioned symbols on different platforms

This is the real reason for this change as far as I can see. Which platforms are affected?

@CyberShadow
Copy link
Member

but for that to work, you need to use the export-dynamic switch

Does this export all public symbols or something? If so, that would conflict with one of the use cases for why you'd want to statically link libcurl (self-contained closed-source application).

@MartinNowak
Copy link
Member Author

We could add weak undefined references to curl and check whether those are defined.
Do you think static linking of curl is an important enough use-case to warrant the effort?

@MartinNowak
Copy link
Member Author

I could try to use undefined weak references and initialize pointers from that when curl is statically linked, not sure if that'd work on Windows.
Do you really think it's worth the effort @CyberShadow?

@CyberShadow
Copy link
Member

I don't know.

How important is the versioned symbol problem?

Can we do this only for affected systems?

@MartinNowak
Copy link
Member Author

We also have a link order issue, because dmd currently doesn't allow to add libraries after phobos.
Let's try the weak ref stuff, shouldn't be too hard.

@MartinNowak
Copy link
Member Author

There is no easy way to get weakly linked but undefined symbols in D. Function declarations in templates are strong undefined. So we'll have to add a C file, hope that dmc supports weak linkage.

@CyberShadow CyberShadow mentioned this pull request Jun 11, 2015
@dnadlinger
Copy link
Contributor

Can we go ahead with this in the meantime? LDC is hit pretty hard with the linker order issue right now, and I'd rather not add -lcurl as a default dependency for every built executable. I might actually merge this into the LDC Phobos fork for the next release.

dnadlinger added a commit to dnadlinger/ldc that referenced this pull request Jun 14, 2015
This is the only sensible solution until e.g.
dlang/phobos#3009 is merged, which makes
Phobos load libcurl dynamically. The issue with the current
situation is is that the user cannot even manually link
libcurl if linker errors occur, because it will appear
before libphobos2-ldc in the linker command line.

GitHub: Fixes ldc-developers#906.
@DmitryOlshansky
Copy link
Member

ODBC will have the same issue once we have D version of std.db.odbc of some such.

@MartinNowak
Copy link
Member Author

Not sure if dmc actually supports weak symbols. I think the simpler solution is to try to dynamically load the curl symbols from the executable.
That way it's still possible to ship a single binary.

@MartinNowak
Copy link
Member Author

done, now also with support for linking curl
still waiting for the tests to pass

@MartinNowak MartinNowak force-pushed the loadCurlAtRuntime branch 2 times, most recently from da0e762 to 0e1a04e Compare August 20, 2015 09:34
@MartinNowak
Copy link
Member Author

ODBC will have the same issue once we have D version of std.db.odbc of some such.

Let's hope we can prevent the mistake to add ODBC.

@MartinNowak
Copy link
Member Author

std.net.curl tests pass though there is an unrelated and already existing 32-bit bug.
https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=3&pullid=3009

@DmitryOlshansky
Copy link
Member

@MartinNowak - what needs to be done to be able to import from the executable itself? Static linking wouldn't suffice I guess?

@MartinNowak
Copy link
Member Author

It should work right away when linking with an import library for a curl.dll or with libcurl.so on Posix, b/c loading a symbol from the exe does search for symbols in dependent libraries (not 100% sure if that works on Windows).

For linking with a static curl library you need the export declarations on Windows (either using a DEF file or using the static lib itself) and --export-dynamic on Posix.

@MartinNowak MartinNowak force-pushed the loadCurlAtRuntime branch 3 times, most recently from 8162aef to 30ec62a Compare August 22, 2015 11:29
@MartinNowak
Copy link
Member Author

Updated with detailed changelog entry and manual on how to statically link against curl.
Also improved the error message to list all the library names that were attempted.

@CyberShadow
Copy link
Member

Pretty cool solution to allow linking libcurl statically on Windows, wouldn't have thought of that. 👍

- avoids issues with versioned symbols on different platforms
- lazy loading/initialization of curl library
- fix Issue 13324
- try to load curl from the exe itself before loading a shared library
  thus allowing to link against a different or a static curl library
@MartinNowak
Copy link
Member Author

Pretty cool solution to allow linking libcurl statically on Windows, wouldn't have thought of that.

Well some very security focused people might not like it, but the weak references weren't an option with DMC.

@MartinNowak
Copy link
Member Author

The nice side effect is that you can link with any shared library on Posix, e.g. a hypothetical libcurl-botan.so and it will work, even without --export-dynamic.

@dnadlinger
Copy link
Contributor

Auto-merge toggled on

dnadlinger added a commit that referenced this pull request Aug 22, 2015
@dnadlinger dnadlinger merged commit de08b92 into dlang:master Aug 22, 2015
@MartinNowak MartinNowak deleted the loadCurlAtRuntime branch August 22, 2015 23:45
@MartinNowak
Copy link
Member Author

Finally

@s-ludwig
Copy link
Member

Is it intended that this now still requires to manually pass a library flag (-ldl) to the compiler? Wouldn't this just shift the issue, or is the idea that -ldl is simply always available and thus less likely to cause problems? There is currently dlang/dub#660 open, but if libdl stays as an additional required (manual) dependency, it will again break all builds for projects using std.net.curl.

@MartinNowak
Copy link
Member Author

Already fixed dlang/dmd#5084.

@s-ludwig
Copy link
Member

Okay, thanks, then the other guy probably just tested with a slightly older version of GIT master.

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

Successfully merging this pull request may close these issues.

7 participants