-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[llvm-c] Guard include of llvm-config in Visibility.h #154229
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please extract the __has_include check separately. I don't think that this should be guarded by #if defined(__has_include).
What about the alternative: we install llvm-config.h? I think that makes sense as we don't know what the configuration of the library is (is it shared or static?).
Sorry, I'm not sure I understand. Are you suggesting using
I'd like to avoid pulling in more dependencies if possible. We don't actually need Visibility.h either, since it's not currently necessary or advantageous for us to have these annotated in the preexisting APIs with This is specifically regarding for how the llvm-c headers get installed and then used by specific clients, not to build LLVM/compilers themselves. |
I'm suggesting that we do something like: #if !defined(__has_include)
#define __has_include(include) 0
#endifBut, we should also guard it with
I don't think it is pulling in more dependencies. The header is a single standalone header that gives very specific information that the user must provide or the build is invalid (aka, we can invoke UB). You need to indicate if you are building against a static version of the library or not because that impacts code generation on some platforms. If we don't simply add the single CMake generated header, we should provide default values for the provided macros in the configuration. |
|
I don't think it is correct to have llvm-c header to include llvm header, even though you can argue that config can be an exception. Maybe the better fix is just always define LLVM_ABI in c header? I don't know if anyone building C API will argue against exporting them by default. |
I had suggested that we avoid that dependency, but it was difficult to split it apart.
I don't think that you can simply define That would require 3 macros: #if defined(LLVMSupport_STATIC)
# define LLVMSupport_ABI /**/
#else
# if defined(_WIN32)
# if defined(LLVMSupport_EXPORTS)
# define LLVMSupport_ABI __declspec(dllexport)
# else
# define LLVMSupport_ABI __declspec(dllimport)
# endif
# else
# if defined(__linux__)
# if defined(LLVMSupport_EXPORTS)
# define LLVMSupport_ABI __attribute__((__visibility__("protected")))
# else
# define LLVMSupport_ABI __attribute__((__visibility__("default")))
# endif
# else
# define LLVMSupport_ABI __attribute__((__visibility__("default")))
# endif
#endif
#if defined(LLVM_STATIC)
# define LLVM_ABI /**/
#else
# if defined(_WIN32)
# if defined(LLVM_EXPORTS)
# define LLVM_ABI __declspec(dllexport)
# else
# define LLVM_ABI __declspec(dllimport)
# endif
# else
# if defined(__linux__)
# if defined(LLVM_EXPORTS)
# define LLVM_ABI __attribute__((__visibility__("protected")))
# else
# define LLVM_ABI __attribute__((__visibility__("default")))
# endif
# else
# define LLVM_ABI __attribute__((__visibility__("default")))
# endif
#endif
#if defined(LLVMBackend_STATIC)
# define LLVMBackend_ABI /**/
#else
# if defined(_WIN32)
# if defined(LLVMBackend_EXPORTS)
# define LLVMBackend_ABI __declspec(dllexport)
# else
# define LLVMBackend_ABI __declspec(dllimport)
# endif
# else
# if defined(__linux__)
# if defined(LLVMBackend_EXPORTS)
# define LLVMBackend_ABI __attribute__((__visibility__("protected")))
# else
# define LLVMBackend_ABI __attribute__((__visibility__("default")))
# endif
# else
# define LLVMBackend_ABI __attribute__((__visibility__("default")))
# endif
#endifThis requires that |
I am not sure why exporting C interface requires exporting c++ interface on Windows... I guess the other alternative is that we can preprocess the headers when installing them so the installed C headers don't need to have dependency on config? |
Oh, that is easy to answer: because it does! There is no true C API to LLVM. The C API is bit just a shim over the C++ interfaces. The configuration here is required to actually import the C++ interface. We could completely sink the implementation into a
Hmm, do you have a portable mechanism for doing this? Remember that we should only rely on tools that are available on Windows natively rather than grow a new dependency. |
I was thinking just using |
|
The problem is that the configuration is not LLVMC, but LLVM itself. You need the configuration for the target libraries that it is creating bindings for. |
I think you are trying to solve a bigger problem than the one trying to fix here. For this PR, just want to achieve the same visibility granularity as I don't know how people usually use llvm-c headers. I don't assume people will use c++ and c header together. I might consider split out all the functions that implements C interface into a separate lib |
I think that you are misunderstanding the code. The C++ header dependency is a requirement because the C interfaces call into the C++ interfaces.
The llvm-c headers are used to actually use the C++ API from C. The C bindings are the only officially supported stable ABI. Separating the inline definitions this way would allow you to also remove the |
I am not misunderstanding the code, just don't quite sure what are all the build configurations LLVM_ABI trying to support. Visibility only matters across binary boundaries. If C APIs is in the same .dll as the C++ APIs, it can be whatever visibility it wants because c++ APIs can be inlined. The dependencies on C++ LLVM_ABI annotation only matters when C APIs lives in a different .dll from the c++ APIs like I proposed. Is my understanding correct? |
|
For what it's worth, I am hoping for a solution where we (as in maintainers for a platform's toolchain) can continue to ship a limited set of
Having
Ah I see, thanks for explaining. |
I agree with this goal. I think that the easiest way to achieve this goal is to simply ship the one extra header. This particular header is not modular, it is a textual header (though could be a standalone module I suppose),
The interspersed implementation really complicates this. It would be ideal to not require the header (I had the same concerns when this change went in). |
It already is modular, https://github.com/llvm/llvm-project/blob/main/llvm/include/module.modulemap.build |
Are you asking how to make it easy to consume standalone downstream or how to avoid the header downstream entirely? The module has no dependencies, the content of the file is simply the configuration that was passed to cmake (i.e., it is just a series of If the question is to how to avoid the dependency on |
Visibility.hdefines common macro for being explicit about symbol visibility, instead of relying on defaults that may not be the same on a given platform/toolchain set, and is installed withllvm-cAPI headers.However, it checks against configuration macros defined by a separate header not installed with
llvm-c, to support distribution without this dependency, add an include guard.