bpo-11410: Standardize and use symbol visibility attributes across POSIX and Windows.#16347
bpo-11410: Standardize and use symbol visibility attributes across POSIX and Windows.#16347vsajip merged 7 commits intopython:masterfrom vsajip:visibility
Conversation
| #include "exports.h" | ||
| #include "grammar.h" | ||
| grammar _PyParser_Grammar; | ||
| Py_EXPORTED_SYMBOL grammar _PyParser_Grammar; |
There was a problem hiding this comment.
I would prefer to not export private symbols (names starting with "_Py"). Or is there a good reason to export that one?
There was a problem hiding this comment.
If you don't export it, e.g. by using just plain extern, the parser module fails to build:
building 'parser' extension
gcc -pthread -fPIC -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I./Include -I/home/vinay/.local/include -I. -I/usr/include/x86_64-linux-gnu -I/usr/local/include -I/home/vinay/projects/python/master/Include -I/home/vinay/projects/python/master -c /home/vinay/projects/python/master/Modules/parsermodule.c -o build/temp.linux-x86_64-3.9/home/vinay/projects/python/master/Modules/parsermodule.o
gcc -pthread -shared build/temp.linux-x86_64-3.9/home/vinay/projects/python/master/Modules/parsermodule.o -L/home/vinay/.local/lib -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib -o build/lib.linux-x86_64-3.9/parser.cpython-39-x86_64-linux-gnu.so
*** WARNING: renaming "parser" since importing it failed: build/lib.linux-x86_64-3.9/parser.cpython-39-x86_64-linux-gnu.so: undefined symbol: _PyParser_Grammar
|
|
||
| int | ||
| PyAPI_FUNC(int) | ||
| _PyArg_Parse_SizeT(PyObject *args, const char *format, ...) |
There was a problem hiding this comment.
Why do we have to export _PyArg symbols in specific? Can't we only configure the visibility in header files?
There was a problem hiding this comment.
The problem here is that these aren't declared in any header file - there are forward declarations at the top of Python/getargs.c with PyAPI_FUNC (example), but the actual definitions didn't have PyAPI_FUNC, with the end result that the symbols weren't exported. Adding PyAPI_FUNC to the definitions fixed that.
To add to the fun, Include/modsupport.h contains definitions like
#define PyArg_Parse _PyArg_Parse_SizeT
if PY_SSIZE_T_CLEAN is defined. So a public API is aliased in a common case to what looks like a private API through a #define! Of course, Include/modsupport.h is included in Include/Python.h, so these are used in a lot of places.
| extern PyObject *_PyIO_empty_bytes; | ||
|
|
||
| extern PyTypeObject _PyBytesIOBuffer_Type; | ||
| extern Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type; |
There was a problem hiding this comment.
Why do you export these _io types, they should be private, no?
There was a problem hiding this comment.
Even if I remove Py_EXPORTED_SYMBOL here in the header, it's exported via the definition in /Modules/_io/bytesio.c. If I remove it there too, the _testcapi module fails to build:
running build
running build_ext
INFO: Can't locate Tcl/Tk libs and/or headers
*** WARNING: renaming "_testcapi" since importing it failed: build/lib.linux-x86_64-3.9/_testcapi.cpython-39-x86_64-linux-gnu.so: undefined symbol: _PyBytesIOBuffer_Type
| @@ -0,0 +1,20 @@ | |||
| #ifndef Py_EXPORTS_H | |||
| #define Py_EXPORTS_H | |||
There was a problem hiding this comment.
I would prefer to restrict the number of header files: why not reusing pyport.h?
There was a problem hiding this comment.
Because exporting symbols is orthogonal to other things. Consider graminit.c - it's a very low-level module which needs to export a symbol, but doesn't really use any other Python-specific or system-specific stuff. If you replace "exports.h" with "pyport.h" in graminit.c, you get an error when compiling:
gcc -pthread -c -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I. -I./Include -DPy_BUILD_CORE -o Python/graminit.o Python/graminit.c
In file included from Python/graminit.c:3:0:
./Include/pyport.h:105:9: error: unknown type name ‘ssize_t’
typedef ssize_t Py_ssize_t;
^
./Include/pyport.h:117:9: error: unknown type name ‘size_t’
typedef size_t Py_uhash_t;
^
Makefile:1711: recipe for target 'Python/graminit.o' failed
Including <stddef.h> before "pyport.h" doesn't fix things:
gcc -pthread -c -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I. -I./Include -DPy_BUILD_CORE -o Python/graminit.o Python/graminit.c
In file included from Python/graminit.c:3:0:
./Include/pyport.h:105:9: error: unknown type name ‘ssize_t’
typedef ssize_t Py_ssize_t;
^
Makefile:1711: recipe for target 'Python/graminit.o' failed
So you end up having to include "Python.h" instead, which appears to be overkill as it exposes a lot of things to code in graminit.c which aren't needed by that code.
|
When you're done making the requested changes, leave the comment: |
|
I have made the requested changes; please review again. |
|
Thanks for making the requested changes! @vstinner: please review the changes made to this pull request. |
|
BTW I've no idea why GitHub thinks I've started a review of my own PR - I was only replying to Victor's comments, so it's not clear what happened. I can't seem to cancel my spurious review, either. |
|
OK, refreshing the page seems to have got rid of my spurious review :-) |
Include/exports.h
Outdated
| #define Py_EXPORTED_SYMBOL __declspec(dllexport) | ||
| #define Py_LOCAL_SYMBOL | ||
| #else | ||
| #if __GNUC__ >= 4 |
There was a problem hiding this comment.
clang also supports this attribute.
Using #if __has_attribute(visibility) should work with both clang and gcc without hardcoding compiler names. This does require GCC 5 or later though.
There was a problem hiding this comment.
Some versions of e.g. Ubuntu and CentOS are still on GCC 4.8. I'll try to generalise it.
visibility attribute is available.
|
I'd like to merge this - I believe I've adequately addressed comments by both @vstinner and @ronaldoussoren - if there are any objections to merging, please let me know! |
|
I would suggest checking with the buildbots before merging, as the pr is changing the autotools scripts. |
|
Pushed this branch to |
|
@vsajip Thanks for checking! |
https://bugs.python.org/issue11410