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

[Request] cURL compile-time option #16

Closed
TurtleP opened this issue Apr 15, 2023 · 13 comments · Fixed by #30
Closed

[Request] cURL compile-time option #16

TurtleP opened this issue Apr 15, 2023 · 13 comments · Fixed by #30
Labels
enhancement New feature or request

Comments

@TurtleP
Copy link
Contributor

TurtleP commented Apr 15, 2023

Heya,

I spoke with @MikuAuahDark briefly about this on Discord. It would be nice if lua-https could be statically compiled instead of dynamically linked. It makes it a hassle to update my fork for homebrew usage. I'm hoping I can make a pull request at some point, but I'm not great at dealing with fixing something like this, unless I use a ton of #ifdef markings which can look ugly.

Statically linking would let me at least only need to update the config.h file (and rename main.cpp to https.cpp to not conflict names just as a safety measure).

@MikuAuahDark MikuAuahDark added the enhancement New feature or request label Apr 15, 2023
@slime73
Copy link
Member

slime73 commented Apr 15, 2023

As far as I know in order for the code to be statically linked to another dll/executable which uses it, nothing would need to change except the CMakeLists file. love already uses the unmodified code with its own build system to compile it into the rest of love's library (which itself is statically linked to the main executable on some platforms), for example.

@TurtleP
Copy link
Contributor Author

TurtleP commented Apr 15, 2023

Hm, I see. Although looking again, the init of the cURL struct does try to load the symbols from the DLL or shared library. If it can't load a handle from one of those, it will not load symbols.

@MikuAuahDark
Copy link
Contributor

I think she meant this part of the code.

CurlClient::Curl::Curl()
: handle(nullptr)
, loaded(false)
, global_cleanup(nullptr)
, easy_init(nullptr)
, easy_cleanup(nullptr)
, easy_setopt(nullptr)
, easy_perform(nullptr)
, easy_getinfo(nullptr)
, slist_append(nullptr)
, slist_free_all(nullptr)
{
#ifdef _WIN32
handle = (void *) LoadLibraryA("libcurl.dll");
#else
handle = dlopen("libcurl.so.4", RTLD_LAZY);
#endif
if (!handle)
return;
// Load symbols
decltype(&curl_global_init) global_init = nullptr;
if (!loadSymbol(global_init, handle, "curl_global_init"))
return;
if (!loadSymbol(global_cleanup, handle, "curl_global_cleanup"))
return;
if (!loadSymbol(easy_init, handle, "curl_easy_init"))
return;
if (!loadSymbol(easy_cleanup, handle, "curl_easy_cleanup"))
return;
if (!loadSymbol(easy_setopt, handle, "curl_easy_setopt"))
return;
if (!loadSymbol(easy_perform, handle, "curl_easy_perform"))
return;
if (!loadSymbol(easy_getinfo, handle, "curl_easy_getinfo"))
return;
if (!loadSymbol(slist_append, handle, "curl_slist_append"))
return;
if (!loadSymbol(slist_free_all, handle, "curl_slist_free_all"))
return;
global_init(CURL_GLOBAL_DEFAULT);
loaded = true;
}

Currently we're loading cURL dynamically so users doesn't have to install cURL for lua-https to work, in which case it will fall back to OpenSSL on Linux.

@slime73
Copy link
Member

slime73 commented Apr 15, 2023

Is dlsym not supported on your platform?

(I know there's a dlopen in the code as well, but that probably isn't really necessary and maybe we can remove the if (!handle) return in favour of also checking the global namespace, or something.)

@TurtleP
Copy link
Contributor Author

TurtleP commented Apr 15, 2023

No, dlsym is not supported. Homebrew does not support dynamically linking/opening of libraries (except on Wii U but I'm still linking statically on there).

@slime73
Copy link
Member

slime73 commented Apr 15, 2023

dlsym doesn't actually dynamically link with or open libraries itself, it just looks through already loaded symbols (which could be from a static library as long as they weren't stripped away as an optimization step). It can look through the global symbol list for the program rather than inside a specific library handle.

So it's much more likely to be supported on limited platforms compared to dlopen - for example iOS used to disallow dlopen entirely but still allowed dlsym, which let LuaJIT's FFI work even though dynamically loading a library did not.

@TurtleP
Copy link
Contributor Author

TurtleP commented Apr 15, 2023

Gotcha, but official comment from the homebrew toolchain maintainers is that dlsym is not supported. They also don't keep/maintain a symbol table at runtime either.

@bartbes
Copy link
Member

bartbes commented Apr 1, 2024

Whilst working on an OpenSSL3 backend, I once again had to duplicate the code to load symbols, and I thought of a solution that might work for you as well:

Instead of having 3 or 4 ad-hoc implementations of library loading (dlopen/dlsym/dlclose + loadSymbol), we could extract this to its own header and source files.
We could then make windows and unix version of this (GetProcAddress vs dlsym), abstracting that logic away from the implementation.
This would then also allow you to provide your own loader, which could no-op dlopen/dlclose, and just look up directly linked libraries in a string table for dlsym. Slightly more (and uglier) work on that side, but it means implementations are oblivious to the changes.

I've got a some of this work done already, in my local tree.

@MikuAuahDark
Copy link
Contributor

That's great idea. What do you think @TurtleP?

@TurtleP
Copy link
Contributor Author

TurtleP commented Apr 1, 2024

look up directly linked libraries in a string table for dlsym

Only question I have is if this requires dlsym, etc to exist. On the platforms I am working on (3DS, Switch, and Wii U) dlsym, dlopen, dlclose.. these don't exist. We don't have dynamic linking library support so I end up building this library statically linked against the binary. That's the main concern. If your solution allows me to keep doing that, then I am fine with the proposal, @bartbes.

@MikuAuahDark
Copy link
Contributor

The bartbes's idea is basically abstracting away that dlsym, dlopen, and dlclose function.

In your platform, you can implement dlopen that only return opaque handle when certain string is passed in (e.g. if it's "curl" then pass opaque pointer that denotes "curl" library). With the same opaque pointer, you implement dlsym such that it just return the function pointer directly based on string name lookup (e.g. dlsym(handle, "curl_easy_setopt") is as simple as return &curl_easy_setopt). You then can implement dlclose as no-op.

Note that the name dlopen, dlsym, and dlclose will be different depending how bartbes implement things. In overall it's a good idea though.

@TurtleP
Copy link
Contributor Author

TurtleP commented Apr 1, 2024

Seems reasonable, although I would prefer that upstream (this repo) be able to just set that up for me, rather than me needing to patch lua-https for static linking. This way I can set an option and be done.

@MikuAuahDark
Copy link
Contributor

Well, we can't do that because we don't really know how your platform behaves (and we don't have the toolchain and hardware to test it), so it's up to you to implement them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
4 participants