Commit 5f107215 authored by Kirill Smelkov's avatar Kirill Smelkov

pyx.build: Adjust compile flags if we are on Windows/MSVC

MSVC does not accept -std=c++11 but instead accepts /std:c++11. We cannot
use that however because with /std:c++11 compilation fails with

    .\golang/libgolang.h(280): error C7555: use of designated initializers requires at least '/std:c++20'
    .\golang/libgolang.h(294): error C7555: use of designated initializers requires at least '/std:c++20'
    .\golang/libgolang.h(308): error C7555: use of designated initializers requires at least '/std:c++20'

for

    276 // _selsend creates `_chansend(ch, ptx)` case for _chanselect.
    277 static inline
    278 _selcase _selsend(_chan *ch, const void *ptx) {
    279     _selcase _ = {
    280         .ch     = ch,			<-- NOTE
    281         .op     = _CHANSEND,
    282         .flags  = (enum _selflags)0,
    283         .user   = 0xff,
    284     };

and similar places.

-> Use /std:c++20 instead as MSVC advices  (WOW designated initializers are C99
and it took 21 years for C++ to catch up).

We also need to adjust exception handling mode into "fully conformant" instead
of "assume extern C cannot throw" setuptools default so that `panic` and other
extern C libgolang functions generate exceptions that could be caught
instead of crashing programs.

For C vs C++ flags we also need to adjust our build_ext, because the way
setuptools/distutils organize compilation for MSVC is different from
UNIX compilers.
parent b5bd136c
...@@ -73,8 +73,10 @@ _dso_build_ext = setuptools_dso.build_ext ...@@ -73,8 +73,10 @@ _dso_build_ext = setuptools_dso.build_ext
class build_ext(_dso_build_ext): class build_ext(_dso_build_ext):
def build_extension(self, ext): def build_extension(self, ext):
# wrap _compiler <src> -> <obj> with our code # wrap _compiler <src> -> <obj> with our code
# ._compile is used on gcc/clang but not with msvc
_compile = self.compiler._compile _compile = self.compiler._compile
def _(obj, src, ext, cc_args, extra_postargs, pp_opts): def xcompile(obj, src, ext, cc_args, extra_postargs, pp_opts):
# filter_out removes arguments that start with argprefix # filter_out removes arguments that start with argprefix
cc_args = cc_args[:] cc_args = cc_args[:]
extra_postargs = extra_postargs[:] extra_postargs = extra_postargs[:]
...@@ -101,11 +103,30 @@ class build_ext(_dso_build_ext): ...@@ -101,11 +103,30 @@ class build_ext(_dso_build_ext):
filter_out('-std=gnu++') filter_out('-std=gnu++')
_compile(obj, src, ext, cc_args, extra_postargs, pp_opts) _compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
self.compiler._compile = _
# msvc handles all sources directly in the loop in .compile and we can
# do per-source adjustsment only in .spawn .
spawn = self.compiler.spawn
def xspawn(argv):
c = False
for arg in argv:
if arg.startswith('/Tc'):
c = True
if c:
argv = argv[:]
for i in range(len(argv)):
if argv[i] == '/std:c++20':
argv[i] = '/std:c11'
return spawn(argv)
self.compiler._compile = xcompile
self.compiler.spawn = xspawn
try: try:
_dso_build_ext.build_extension(self, ext) # super doesn't work for _dso_build_ext _dso_build_ext.build_extension(self, ext) # super doesn't work for _dso_build_ext
finally: finally:
self.compiler._compile = _compile self.compiler._compile = _compile
self.compiler.spawn = spawn
# setup should be used instead of setuptools.setup # setup should be used instead of setuptools.setup
...@@ -144,6 +165,10 @@ def _with_build_defaults(name, kw): # -> (pygo, kw') ...@@ -144,6 +165,10 @@ def _with_build_defaults(name, kw): # -> (pygo, kw')
kw = kw.copy() kw = kw.copy()
sysname = platform.system().lower()
win = (sysname == 'windows')
msvc = win # TODO also support mingw ?
# prepend -I<pygolang> so that e.g. golang/libgolang.h is found # prepend -I<pygolang> so that e.g. golang/libgolang.h is found
incv = kw.get('include_dirs', [])[:] incv = kw.get('include_dirs', [])[:]
incv.insert(0, pygo) incv.insert(0, pygo)
...@@ -161,13 +186,20 @@ def _with_build_defaults(name, kw): # -> (pygo, kw') ...@@ -161,13 +186,20 @@ def _with_build_defaults(name, kw): # -> (pygo, kw')
# default to C++11 (chan[T] & co require C++11 features) # default to C++11 (chan[T] & co require C++11 features)
ccdefault = [] ccdefault = []
if lang == 'c++': if lang == 'c++':
if not msvc:
if name == 'golang.runtime.libgolang': if name == 'golang.runtime.libgolang':
ccdefault.append('-std=gnu++11') # not c++11 as linux/list.h uses typeof ccdefault.append('-std=gnu++11') # not c++11 as linux/list.h uses typeof
else: else:
ccdefault.append('-std=c++11') ccdefault.append('-std=c++11')
else:
# MSVC requries C++20 for designated struct initializers
ccdefault.append('/std:c++20')
# and make exception handling: "fully conformant", so that e.g. extern "C" `panic` works
ccdefault.extend(['/EHc-', '/EHsr'])
# default to no strict-aliasing # default to no strict-aliasing
ccdefault.append('-fno-strict-aliasing') if not msvc:
ccdefault.append('-fno-strict-aliasing') # use only on gcc/clang - msvc does it by default
_ = kw.get('extra_compile_args', [])[:] _ = kw.get('extra_compile_args', [])[:]
_[0:0] = ccdefault # if another e.g. -std=... was already there - _[0:0] = ccdefault # if another e.g. -std=... was already there -
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment