-
Notifications
You must be signed in to change notification settings - Fork 1.7k
export http_exception for non Windows builds #1577
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
export http_exception for non Windows builds #1577
Conversation
What error are you trying to resolve that required exporting this class. For what it's worth we don't recommend ever exporting an entire class, instead export the individual methods that you require. This will likely resolve the warnings as well |
Summary of what we did and how we figured out the issue was this: We have been using CppRest for a couple of years now, and did so with the default visibility on MacOS (apple-clang). After a small research project on security, we found that all of our symbols were readable on MacOS while parsing them with tools like Radare, while they weren't visible on Windows (MSVC). We also had a fair amount of complaints about Mac developers not exporting the symbols, and thus breaking our Windows builds. We thus decided to turn on the After we managed to fix all compiler issues, we still had some other runtime issues, and one of our integration tests (network timeout handling) didn't finish, and was idling until our timelimit mechanism killed it. After some research we learned that we didn't get a After some research from our Mac experts, we learned that apple-clang (also clang and gcc) needs to export (default visibility) their exception classes if they are caught in a different binary, in our case the test application. https://gcc.gnu.org/wiki/Visibility see "Problems with C++ exceptions (please read!)". Since we use Conan to build our 3rd party libraries, including CppRest, we decided to append the following test to verify that the supplied test works (be sure to use
Regarding the exporting of a full class. My initial thought is that you really need the class symbol to be exported, rather than one or more members, but I could be wrong. |
The reason we (the vclibs team) discourage exporting entire classes on windows is just that it tends to lead to exporting more than you intended, and that's a big problem if you want to provide any kind of controlled ABI. I'll ask around on the exception catching issue tomorrow. I suspect we won't end up needing to export the entire class. |
on windows there is no class symbol, it's just symbols for any static data members and any methods. There's also RTTI data but that's not affected by __declspec(dllexport) as far as I know (and does not result in a symbol in the DLL's export table anywaays) |
Thinking about this some more I'd prefer a new macro that's just for exporting type infos and is always disabled on windows. Clang does this and it's more clear, more searchable, and less likely to screw up doxygen. maybe |
I updated by PR with your suggestion. It builds and works on our end (MSVC and apple-clang) |
#ifdef __clang__ | ||
#define _ASYNCRTIMP_TYPEINFO __attribute__((visibility("default"))) | ||
#else // ^^^ __clang__ ^^^ // vvv !__clang__ vvv | ||
#define _ASYNCRTIMP_TYPEINFO | ||
#endif // __clang__ |
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.
I don't think clang is the correct thing to use here, it should be
"if _NO_ASYNCRTIMP is not defined and we're not building for windows"
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.
I was thinking about that, but since the clang compiler can also be used on Windows, I thought __clang__
would be better for cross compiler compatibility.
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.
ah, but the thing is you actually don't want to export the "class" when clang is running in msvc ABI mode (in this case it will define __clang__
and _WIN32
.
If a project compiled with clang for macos links to CppRest, and the -fvisibility=hidden compiler option is used, the http_exception is used as std::exception. The clang compiler requires it to be exported in order to know about the symbols. Since the Visual Studio compiler throws warnings regarding the export of a class that inherits from a non-exported class, std::exception in this case, this export is only defined for clang.
#if defined(_WIN32) | ||
#define _ASYNCRTIMP_TYPEINFO | ||
#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv | ||
#define _ASYNCRTIMP_TYPEINFO __attribute__((visibility("default"))) | ||
#endif // _WIN32 |
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.
Does this work when _NO_ASYNCRTIMP is defined, it seems to me it might result in a duplicate definition. Also if you do define _NO_ASYNCRTIMP you should probably not define _ASYNCRTIMP_TYPEINFO on any platform
Sorry this has gone back and forth so much, I know it's annoying.
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.
If you considered this case and have a reason for structuring it this way that's fine, I just need to know why.
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.
The TYPEINFO define is within the !_NO_ASYNCTRIMP block. In the _NO_ASYNCTRIMP block I defined the empty case for all compilers, like _ASYNCTRIMP.
Since _ASYNCRTIMP_TYPEINFO needs to be defined for the compiler, I also defined an empty for WIN32 within the !_NO_ASYNCRTIMP block. I could move it out of the _NO_ASYNCRTIMP block and do something like:
#if !_NO_ASYNCRTIMP && !defined(_WIN32)
attribute
#else
empty
#endif
But my initial thought was that the ASYNCRTIMP_TYPEINFO should be defined within the _NO_ASYNCRTIMP block for easier maintenance, as the developers then see that it is tightly linked to the export/no-export configuration.
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.
oh I'm sorry I missed the structure because of the whitespace, whoops
Merged, sorry for the trouble with the macro placement. |
@JvdGlind I'm wondering why does this only apply to |
@garethsb We don't catch these exceptions explicitly in our codebase or testcases, so I don't know if it only applies to |
If a project compiled with clang for macos links to CppRest, and the
-fvisibility=hidden compiler option is used, the http_exception is used
as std::exception. The clang compiler requires it to be exported in
order to know about the symbols.
Since the Visual Studio compiler throws warnings regarding the export of
a class that inherits from a non-exported class, std::exception in this
case, the WIN32 define check is added to omit this export.