Re: Why do we test a build using g++?
[email protected] (Leon Timmermans) Tue, 30 Jun 2026 01:39:37 +0200
| Newsgroups | perl.perl5.porters |
|---|---|
| Message-ID | <CAHhgV8gBtFs3wcpjA1fUW+qHnwxnZ6EZZGrzBr21P9Z7RdZN7g@mail.gmail.com> |
--0000000000005ce07e06556cf9fb Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Jun 29, 2026 at 11:42=E2=80=AFPM Paul "LeoNerd" Evans < [email protected]> wrote: > TL;DR: We have some CI test builds that use -Dcc=3D'g++', to test if we c= an > build perl using g++ as the "C" compiler. I wonder - why do we do this? > Perl is written in C, not C++, which is a different language. Can we > please not? Actually, we have one file in Windows that uses C++ (on IMPLICIT_SYS builds at least). > I ask because it's increasingly annoying and getting in the way. Before > we added C99 (and thus were only using C89 features), this wasn't so > bad, but we introduced C99 specifically so we could use some features > that were introduced only 25 years ago, instead of having to stick to > features that are over 35 years old. > > One feature of C99 that I intend to use a lot is the ability to > initialise structures with named initialisers, and to be able to omit > fields to imply the compiler-assigned defaults of zero for integers or > NULL for pointers. This makes it nicely convenient to initialise > structures that, for example, have optional "flags" or other features > in them, or pointers that are rarely used, and so most of the time you > leave them as NULL. Not having to write lots of extra lines in the > source makes the code clearer. > > The default C99-and-not-C++ compiler is perfectly happy for me to write > code such as: > > static const struct MagicFunctions magicfuncs_customop_xop =3D { > .ver =3D 2, > .shape =3D MGv2s_BASE, > .debug_name =3D "customop_xop", > .free_mg =3D &customop_xop_free, > }; > > This is relatively easy on the human eye, because it draws attention to > only those fields that we're putting something interesting in, without > a lot of extra clutter. It's almost as nice as having named parameters > with optional defaults in them. ;) > > But g++ doesn't like this; it complains: > > op.c:16427:1: warning: missing initializer for member > =E2=80=98MagicFunctions::_v1_vtbl=E2=80=99 [-Wmissing-field-initial= izers] > 16427 | }; > | ^ > op.c:16427:1: warning: missing initializer for member > =E2=80=98MagicFunctions::flags=E2=80=99 [-Wmissing-field-initialize= rs] > op.c:16427:1: warning: missing initializer for member > =E2=80=98MagicFunctions::user_size=E2=80=99 [-Wmissing-field-initia= lizers] > op.c:16427:1: warning: missing initializer for member > =E2=80=98MagicFunctions::clone_mg=E2=80=99 [-Wmissing-field-initial= izers] > > In order to appease it, I tried just adding a bunch of zero/NULL/{} > fields at the end of the struct; but then it complains: > > op.c:16432:1: error: designator order for field =E2=80=98MagicFunctions= ::flags=E2=80=99 > does not match declaration order in =E2=80=98const MagicFunctions= =E2=80=99 > > It also still gets upset that initialisers that I have in fact written > aren't there, because it doesn't see them. Or something. I don't know, > I'm not a C++ programmer. I write in C. > > It seems the only way to make it happy is to write a lot more noisy > structure, that's far worse on the human reader: > > static const struct MagicFunctions magicfuncs_customop_xop =3D { > ._v1_vtbl =3D {}, > .ver =3D 2, > .shape =3D MGv2s_BASE, > .flags =3D 0, > .debug_name =3D "customop_xop", > .user_size =3D 0, > .free_mg =3D &customop_xop_free, > .clone_mg =3D NULL, > }; > > I find this quite a bit worse to look at, because of all those empty > junk lines being added. It makes it harder to see what's "interesting" > about this struct, as even the zeroes and the NULLs are in there. Plus > that leading ._v1_vtbl is even worse. It's present in the structure > definition itself in order to make a compatible hole with (version 1) > MAGIC structure, but shouldn't really be thought about or visible as > part of the v2 API. So having to add it in *every* struct > initialisation is very annoying indeed. > > Aside from being more cluttered and less clear to look at to the human > reader, I also find this worse for longterm maintainability. A key > selling point of C99's ability to imply zeroes/etc.. for fields you > don't name, is that if you later extend the struct definition by adding > more fields to it, you don't have to go around all your initialisers > everywhere to add more ".foo =3D 0" lines. You can just ignore them, > knowing they will default to zeroes if you don't need them. It makes it > easier and nicer to extend those data types later without breaking > existing source code. Plus, an actual C99 compiler doesn't care if the > named initialisers don't appear in the same order as the fields in the > struct. The whole point of naming them is that now order doesn't > matter. You can reorder the elements in the struct without upsetting > users of that struct, even in initialisers. Yes you'll still have to > recompile it - but that's fine for all the code within the source tree. > You just don't have to manually edit all your .c files. > > > I think therefore I have made a reasonable case for wanting to be able > to use this C99 named initialiser syntax. So now I want to understand > why we care if we can compile perl source using g++. > > I understand that historically we have used this as a test to see that > perl's *headers* are suitable for use by both a C compiler and a C++ > compiler, for those folks who want to write XS extensions in C++. That > made sense when we were only using C89, and the C++ compilers were > basically able to handle a superset of that anyway. But C99 and C++ > diverge a little, so that is no longer really true. > > I'm not aware of any direct reason why the source of the perl binary > itself needs to be compilable by a C++ compiler; especially not since > it gets in the way of us writing the code we want to write - in C99. > Yeah, that is an annoying issue. We also hit it in PR#24390 > I'd like to propose that (if there isn't another valid reason that is > stronger than our desire to use C99 features) we find another way to > test if the perl headers are compatible with C++. For example, could we > ship a tiny "helloworld.cpp" program that also pulls in <perl.h> and > <XSUB.h> or somesuch? Or maybe we write a tiny XS extension in C++ and > compiled with g++, to use for such testing purposes? > Well volunteered! ;-) Leon --0000000000005ce07e06556cf9fb Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr"><div dir=3D"ltr">On Mon, Jun 29, 2026 at = 11:42=E2=80=AFPM Paul "LeoNerd" Evans <<a href=3D"mailto:leone= [email protected]" target=3D"_blank">[email protected]</a>> wrote:<= /div><div dir=3D"ltr"><div class=3D"gmail_quote"><blockquote class=3D"gmail= _quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204= ,204);padding-left:1ex">TL;DR: We have some CI test builds that use -Dcc=3D= 'g++', to test if we can<br> =C2=A0 build perl using g++ as the "C" compiler. I wonder - why d= o we do this?<br> =C2=A0 Perl is written in C, not C++, which is a different language. Can we= <br> =C2=A0 please not?</blockquote><div><br></div><div>Actually, we have one fi= le in Windows that uses C++ (on IMPLICIT_SYS builds at least).</div><div>= =C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0= .8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> I ask because it's increasingly annoying and getting in the way. Before= <br> we added C99 (and thus were only using C89 features), this wasn't so<br= > bad, but we introduced C99 specifically so we could use some features<br> that were introduced only 25 years ago, instead of having to stick to<br> features that are over 35 years old.<br> <br> One feature of C99 that I intend to use a lot is the ability to<br> initialise structures with named initialisers, and to be able to omit<br> fields to imply the compiler-assigned defaults of zero for integers or<br> NULL for pointers. This makes it nicely convenient to initialise<br> structures that, for example, have optional "flags" or other feat= ures<br> in them, or pointers that are rarely used, and so most of the time you<br> leave them as NULL. Not having to write lots of extra lines in the<br> source makes the code clearer.<br> <br> The default C99-and-not-C++ compiler is perfectly happy for me to write<br> code such as:<br> <br> =C2=A0 static const struct MagicFunctions magicfuncs_customop_xop =3D {<br> =C2=A0 =C2=A0 =C2=A0 .ver=C2=A0 =C2=A0=3D 2,<br> =C2=A0 =C2=A0 =C2=A0 .shape =3D MGv2s_BASE,<br> =C2=A0 =C2=A0 =C2=A0 .debug_name =3D "customop_xop",<br> =C2=A0 =C2=A0 =C2=A0 .free_mg =3D &customop_xop_free,<br> =C2=A0 };<br> <br> This is relatively easy on the human eye, because it draws attention to<br> only those fields that we're putting something interesting in, without<= br> a lot of extra clutter. It's almost as nice as having named parameters<= br> with optional defaults in them. ;)<br> <br> But g++ doesn't like this; it complains:<br> <br> =C2=A0 op.c:16427:1: warning: missing initializer for member<br> =C2=A0 =C2=A0 =C2=A0 =E2=80=98MagicFunctions::_v1_vtbl=E2=80=99 [-Wmissing-= field-initializers]<br> =C2=A0 16427 | };<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 | ^<br> =C2=A0 op.c:16427:1: warning: missing initializer for member<br> =C2=A0 =C2=A0 =C2=A0 =E2=80=98MagicFunctions::flags=E2=80=99 [-Wmissing-fie= ld-initializers]<br> =C2=A0 op.c:16427:1: warning: missing initializer for member<br> =C2=A0 =C2=A0 =C2=A0 =E2=80=98MagicFunctions::user_size=E2=80=99 [-Wmissing= -field-initializers]<br> =C2=A0 op.c:16427:1: warning: missing initializer for member<br> =C2=A0 =C2=A0 =C2=A0 =E2=80=98MagicFunctions::clone_mg=E2=80=99 [-Wmissing-= field-initializers]<br> <br> In order to appease it, I tried just adding a bunch of zero/NULL/{}<br> fields at the end of the struct; but then it complains:<br> <br> =C2=A0 op.c:16432:1: error: designator order for field =E2=80=98MagicFuncti= ons::flags=E2=80=99<br> =C2=A0 =C2=A0 =C2=A0 does not match declaration order in =E2=80=98const Mag= icFunctions=E2=80=99<br> <br> It also still gets upset that initialisers that I have in fact written<br> aren't there, because it doesn't see them. Or something. I don'= t know,<br> I'm not a C++ programmer. I write in C.<br> <br> It seems the only way to make it happy is to write a lot more noisy<br> structure, that's far worse on the human reader:<br> <br> =C2=A0 static const struct MagicFunctions magicfuncs_customop_xop =3D {<br> =C2=A0 =C2=A0 =C2=A0 ._v1_vtbl =3D {},<br> =C2=A0 =C2=A0 =C2=A0 .ver=C2=A0 =C2=A0=3D 2,<br> =C2=A0 =C2=A0 =C2=A0 .shape =3D MGv2s_BASE,<br> =C2=A0 =C2=A0 =C2=A0 .flags =3D 0,<br> =C2=A0 =C2=A0 =C2=A0 .debug_name =3D "customop_xop",<br> =C2=A0 =C2=A0 =C2=A0 .user_size =3D 0,<br> =C2=A0 =C2=A0 =C2=A0 .free_mg =3D &customop_xop_free,<br> =C2=A0 =C2=A0 =C2=A0 .clone_mg =3D NULL,<br> =C2=A0 };<br> <br> I find this quite a bit worse to look at, because of all those empty<br> junk lines being added. It makes it harder to see what's "interest= ing"<br> about this struct, as even the zeroes and the NULLs are in there. Plus<br> that leading ._v1_vtbl is even worse. It's present in the structure<br> definition itself in order to make a compatible hole with (version 1)<br> MAGIC structure, but shouldn't really be thought about or visible as<br= > part of the v2 API. So having to add it in *every* struct<br> initialisation is very annoying indeed.<br> <br> Aside from being more cluttered and less clear to look at to the human<br> reader, I also find this worse for longterm maintainability. A key<br> selling point of C99's ability to imply zeroes/etc.. for fields you<br> don't name, is that if you later extend the struct definition by adding= <br> more fields to it, you don't have to go around all your initialisers<br= > everywhere to add more ".foo =3D 0" lines. You can just ignore th= em,<br> knowing they will default to zeroes if you don't need them. It makes it= <br> easier and nicer to extend those data types later without breaking<br> existing source code. Plus, an actual C99 compiler doesn't care if the<= br> named initialisers don't appear in the same order as the fields in the<= br> struct. The whole point of naming them is that now order doesn't<br> matter. You can reorder the elements in the struct without upsetting<br> users of that struct, even in initialisers. Yes you'll still have to<br= > recompile it - but that's fine for all the code within the source tree.= <br> You just don't have to manually edit all your .c files.<br> <br> <br> I think therefore I have made a reasonable case for wanting to be able<br> to use this C99 named initialiser syntax. So now I want to understand<br> why we care if we can compile perl source using g++.<br> <br> I understand that historically we have used this as a test to see that<br> perl's *headers* are suitable for use by both a C compiler and a C++<br= > compiler, for those folks who want to write XS extensions in C++. That<br> made sense when we were only using C89, and the C++ compilers were<br> basically able to handle a superset of that anyway. But C99 and C++<br> diverge a little, so that is no longer really true.<br> <br> I'm not aware of any direct reason why the source of the perl binary<br= > itself needs to be compilable by a C++ compiler; especially not since<br> it gets in the way of us writing the code we want to write - in C99.<br></b= lockquote><div><br></div><div>Yeah, that is an annoying issue. We also hit = it in PR#24390</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl= e=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddin= g-left:1ex"> I'd like to propose that (if there isn't another valid reason that = is<br> stronger than our desire to use C99 features) we find another way to<br> test if the perl headers are compatible with C++. For example, could we<br> ship a tiny "helloworld.cpp" program that also pulls in <perl.= h> and<br> <XSUB.h> or somesuch? Or maybe we write a tiny XS extension in C++ an= d<br> compiled with g++, to use for such testing purposes?<br></blockquote><div><= br></div><div>Well volunteered! ;-)</div><div><br></div><div>Leon</div></di= v></div> </div> </div> --0000000000005ce07e06556cf9fb--