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

No way to depend on existing shared library by exact path #8756

Open
AMDmi3 opened this issue May 10, 2021 · 10 comments
Open

No way to depend on existing shared library by exact path #8756

AMDmi3 opened this issue May 10, 2021 · 10 comments

Comments

@AMDmi3
Copy link

AMDmi3 commented May 10, 2021

I'm building a software which uses OpenSSL on FreeBSD. The thing with OpenSSL on FreeBSD is that there may be two versions, one from base system (/usr/lib/libcrypto.so) and optional one from the ports (/usr/local/lib/libcrypto.so). Which one should be used is dictated by the Ports framework, so what I need is to specify in meson dependency on a shared library given EXACT library .so path and include path.

Note that

  • I cannot use dependency() because system openssl does not have pkgconfig file or other means of detection
  • I cannot use cc.find_library() because there's no control on which library it would pick up if both are present

So I don't need any form of detection, I need to specify exact library path.

I believe before the following construct worked:

declare_dependency(link_with:shared_library(get_option('OPENSSLLIB') + '/libcrypto.so'), include_directories:include_directories(get_option('OPENSSLINC')))

where OPENSSLLIB and OPENSSLINC are paths provided by the Ports framework which lead to the right version of the library (e.g. /usr/lib + /usr/include or /usr/local/lib + /usr/local/include)

But now it doesn't work:

WARNING: Target "/usr/lib/libcrypto.so" has a path separator in its name.
This is not supported, it can cause unexpected failures and will become
a hard error in the future.

and the library doesn't get into link args.

Is there a way to implement this in modern meson?

@xclaesse
Copy link
Member

I think it should work with cc.find_library('crypto', dirs: '/usr/local/lib'), no?

@AMDmi3
Copy link
Author

AMDmi3 commented May 11, 2021

Looks feasible, but now I need to specify exact include directory for it, is there a way to do it?

@xclaesse
Copy link
Member

You can add the cflag manually I guess... c_args: '-I/usr/local/include'

@eli-schwartz
Copy link
Member

eli-schwartz commented May 11, 2021

system openssl does not have pkgconfig file or other means of detection

Sounds like a BSD bug.

Since I guess your ports policy means you actually need to have a meson_options.txt option e.g. "use-ports-openssl" to allow using the system one or the ports one... maybe you could use that option to select between dependency() which selects the one preferred by pkg-config and isn't the system one, and cc.find_library(..., dirs: '/usr/lib').

@AMDmi3
Copy link
Author

AMDmi3 commented May 12, 2021

You can add the cflag manually I guess... c_args: '-I/usr/local/include'

Where should I put this? And is there a way with include_directories, that is where I don't need to mention compiler-specific flags and to interfere with meson's handling of include paths (which usually needs to be somewhat clever, as in using correct order and -I vs. -isystem, and would be just ruined by random manual -I)?

Sounds like a BSD bug.

Well, yes, but that's not strictly related. I'd say that FreeBSD 'base system' concept is a bug by itself, and it leads to all kinds of problems including this one. In fact some cases are not possible to fix (such as when both versions of OpenSSL installed, but when framework is set to uses system one - even if correct library and includes are passed to the build, it will still likely pick up wrong includes (depending on -I order, -I vs -isystem etc.)), but I'm trying to do in correct way and make sure meson is flexible enough for this.

However even if we forget about FreeBSD, in our diverse world a case where one needs to manually specify EXACT locations for a library and its includes is more than probable (e.g. upstream not supporting pkgconfig, multiple versions of a library, installed to unusual locations, bundled etc.). I've got the part about specifying the path to library, but not yet sure how to tie include paths to it.

@xclaesse
Copy link
Member

You can add the cflag manually I guess... c_args: '-I/usr/local/include'

Where should I put this? And is there a way with include_directories, that is where I don't need to mention compiler-specific flags and to interfere with meson's handling of include paths (which usually needs to be somewhat clever, as in using correct order and -I vs. -isystem, and would be just ruined by random manual -I)?

globally with add_project_arguments('-I/usr/local/include', language: 'c') or just for a target with library(..., c_args: '-I/usr/local/include'). But yes that could mess up ordering. You really should be using pkgconfig....

@AMDmi3
Copy link
Author

AMDmi3 commented May 13, 2021

You really should be using pkgconfig....

I'll repeat, there's no choice of using pkgconfig or not as availability of pkgconfig files depends on third parties (authors of library used as dependency in generic case).

IMO we see here a problem (or regression, if my above mentioned construct with declare_dependency has worked as intended before) in meson which does allow to specify include_directories for en explicit dependency without hacks.

@eli-schwartz
Copy link
Member

eli-schwartz commented May 13, 2021

Using shared_library() to BUILD a shared library and place it in /usr/lib is obviously pure madness, should never have worked, hopefully didn't work even if you think it did, and shall not work now or in the future. It generates a build rule to build it, why would you EVER think it's a good idea to use here... This is such horrid intentional abuse and mangling of the basic meaning of the public documentation that I object to calling it a regression.

And it's completely pointless too as the correct solution was always cc.find_library('crypto', dirs: get_option('OPENSSLLIB'). This is completely unrelated to how you formulate the relevant include directory. Just do not ever ever use shared_library() as some monstrously abusive perversion of cc.find_library(..., dirs: ...) as it directly contradicts what the docs say shall be possible.

@eli-schwartz
Copy link
Member

eli-schwartz commented May 13, 2021

As per the cc.has_header() documentation if you don't have a dependency() object you need to use manually specified -I flags.
EDIT: but include_directories() does accept and use absolute paths to /usr/local which makes a lot more sense since this is not supposed to build them... but cc.has_header() doesn't support useful kwargs here...

As far as ordering goes... I think ordering should presumably work if you add it to a declare_dependency together with the cc.find_library() output?

@eli-schwartz
Copy link
Member

eli-schwartz commented May 13, 2021

Another solution would be to have your ports system generate a custom .pc file in the workdir and then invoke meson with PKG_CONFIG_PATH pointing at the locally generated .pc file describing the system openssl (which does not have pkg-config support) and which overrides the ports version of OpenSSL.

Autotools would let you override any pkg-config dependency via $NAME_CFLAGS and $NAME_LIBS.

IIRC there is an open meson issue to allow a similar style override, but via a section in a native/cross machine file.

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

3 participants