Skip to content

Build the Cython extensions under GCC 14: declare the functions charm.h lacks - #313

Merged
ritvikrao merged 2 commits into
mainfrom
setup-gcc14
Nov 6, 2026
Merged

ritvikrao merged 2 commits into
mainfrom
setup-gcc14

Conversation

@AdvaitTahilyani

@AdvaitTahilyani AdvaitTahilyani commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

On Linux with GCC 14, the default compiler on NCSA Delta, pip install of charm4py fails while compiling the Cython extensions. GCC 14 turns two warnings into errors by default:

  • incompatible-pointer-types, from the generated Cython code;
  • implicit-function-declaration, because charm4py calls functions that charm's exported headers don't declare.

The darwin branch of setup.py already sets -Wno-error=implicit-function-declaration, but Linux gets nothing.

Change

Instead of turning the two errors into warnings, this fixes what triggers them (commit c1d22ca, which replaces the first commit's setup.py flags, so setup.py is unchanged from main):

  • Implicit declarations (6): LBTurnInstrumentOn, LBTurnInstrumentOff and CkExtContributeTo{Chare,Group,Array,Section} are defined in libcharm with C linkage but not declared in charm.h, so the generated C called them with no prototype. ccharm.pxd now declares them in a C block of its own.
  • Pointer types (5): the entry-method name arrays passed to the five CkRegister*Ext functions were char ** where charm.h takes const char **; they are now const char **.

Keeping the errors as warnings would also hide the next call made without a declaration, including one that returns a pointer, which the implicit int return truncates to 32 bits.

Testing

-fsyntax-only on the generated charmlib_cython.c, with no extra flags, on macOS:

Headers main, GCC 15 (errors) this PR, GCC 15 (errors) this PR, clang -Werror=implicit-function-declaration (errors)
classic Charm++ (main, netlrts-darwin-arm8) 11 0 0
recharm Reconverse, configured for charm4py 11 0 0

GCC 15 has the same two errors on by default as GCC 14. c_object_store (C++) compiles with g++ 15 without any flags. CI runs the test suite on this branch.

Still to do before this leaves draft: build on Delta (GCC 14.2) without the CFLAGS workaround.

🤖 Generated with Claude Code

…n extensions

GCC 14 turns incompatible-pointer-types and implicit-function-declaration
into errors by default; the generated Cython code and charm4py's calls to
functions charm's exported headers do not declare trigger them, so the
extension build fails on Linux with GCC 14 (e.g. NCSA Delta). The darwin
branch already sets -Wno-error=implicit-function-declaration via CPPFLAGS;
this passes both flags to the two extensions on every non-Windows build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@ritvikrao ritvikrao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reproduced the failure and checked the fix on macOS with Homebrew GCC 15, which turns on the same two errors by default as GCC 14. I compiled the generated charmlib_cython.c with -fsyntax-only against the headers of a classic Charm++ build (charm main, netlrts-darwin-arm8):

Extra compile flags Compiler errors (count)
none 11
this PR's two flags 0

The 11 errors:

  • 6 × implicit-function-declaration: LBTurnInstrumentOn, LBTurnInstrumentOff, CkExtContributeToChare, CkExtContributeToGroup, CkExtContributeToArray, CkExtContributeToSection. ccharm.pxd lists them under cdef extern from "charm.h", but charm.h doesn't declare them (they are defined with C linkage in ckreduction.C and LBManager.C), so Cython emits the calls with no prototype in scope.
  • 5 × incompatible-pointer-types: argument 2 of CkRegisterMainChareExt, CkRegisterGroupExt, CkRegisterSectionManagerExt, CkRegisterArrayExt and CkRegisterArrayMapExt. The pyx passes char ** where charm.h expects const char **.

Against a Reconverse build older than reconverse 599798b (Oct 15) there is a 12th, CcsRegisterHandlerExt. Reconverse has declared it in conv-ccs.h since then.

The flags are safe for today's code. All six undeclared functions return void and take only int and pointer arguments, so the implicit int f() declaration calls them correctly on x86-64 and arm64. The five pointer errors differ only in const. Fine to merge as it is once it builds on Delta.

Suggestion, non-blocking (here or in a follow-up): fix the two causes instead of turning the errors off. With the flags on, the next function charm4py calls without a declaration also compiles without complaint. If that function returns a pointer, the implicit int return truncates it to 32 bits on 64-bit machines, which is the main reason GCC 14 made this an error. The fix is two small edits:

diff --git a/charm4py/charmlib/ccharm.pxd b/charm4py/charmlib/ccharm.pxd
index da873e1..2759265 100644
--- a/charm4py/charmlib/ccharm.pxd
+++ b/charm4py/charmlib/ccharm.pxd
@@ -10,8 +10,6 @@ cdef extern from "charm.h":
     void realCkExit(int exitcode);
     void CmiAbort(const char *, ...);
     void CmiPrintf(const char *, ...);
-    void LBTurnInstrumentOn();
-    void LBTurnInstrumentOff();
 
     int CmiPeOnSamePhysicalNode(int pe1, int pe2);
     int CmiNumPhysicalNodes();
@@ -60,10 +58,6 @@ cdef extern from "charm.h":
     void registerPyReductionExtCallback(int (*cb)(char**, int*, int, char**));
     void registerArrayMapProcNumExtCallback(int (*cb)(int, int, const int *));
 
-    void CkExtContributeToChare(void* contribute_params, int onPE, void* objPtr);
-    void CkExtContributeToGroup(void* contribute_params, int gid, int pe);
-    void CkExtContributeToArray(void* contribute_params, int aid, int* idx, int ndims);
-    void CkExtContributeToSection(void* contribute_params, int sid_pe, int sid_cnt, int rootPE);
     void CkStartQDExt_ChareCallback(int onPE, void* objPtr, int epIdx, int fid);
     void CkStartQDExt_GroupCallback(int gid, int pe, int epIdx, int fid);
     void CkStartQDExt_ArrayCallback(int aid, int* idx, int ndims, int epIdx, int fid);
@@ -76,6 +70,24 @@ cdef extern from "charm.h":
     void CkTraceBeginUserBracketEvent(int eventID);
     void CkTraceEndUserBracketEvent(int eventID);
 
+# Defined in libcharm with C linkage but not declared in charm.h (C compilers
+# from GCC 14 on reject the implicit declarations), so declare them here.
+cdef extern from *:
+    """
+    void LBTurnInstrumentOn(void);
+    void LBTurnInstrumentOff(void);
+    void CkExtContributeToChare(void *contribute_params, int onPE, void *objPtr);
+    void CkExtContributeToGroup(void *contribute_params, int gid, int pe);
+    void CkExtContributeToArray(void *contribute_params, int aid, int *idx, int ndims);
+    void CkExtContributeToSection(void *contribute_params, int sid_pe, int sid_cnt, int rootPE);
+    """
+    void LBTurnInstrumentOn();
+    void LBTurnInstrumentOff();
+    void CkExtContributeToChare(void* contribute_params, int onPE, void* objPtr);
+    void CkExtContributeToGroup(void* contribute_params, int gid, int pe);
+    void CkExtContributeToArray(void* contribute_params, int aid, int* idx, int ndims);
+    void CkExtContributeToSection(void* contribute_params, int sid_pe, int sid_cnt, int rootPE);
+
 cdef extern from "converse.h":
     ctypedef void (*CmiHandler)(void* )
     cdef const int CmiReservedHeaderSize
diff --git a/charm4py/charmlib/charmlib_cython.pyx b/charm4py/charmlib/charmlib_cython.pyx
index 8b2f37d..7d7a23b 100644
--- a/charm4py/charmlib/charmlib_cython.pyx
+++ b/charm4py/charmlib/charmlib_cython.pyx
@@ -525,7 +525,7 @@ class CharmLib(object):
     cdef int chareIdx, startEpIdx
     self.emNames += [name.encode() for name in entryMethodNames]
     # TODO: do we want to track/free these pointers?
-    cdef char** c1 = to_cstring_array(self.emNames)
+    cdef const char** c1 = <const char**>to_cstring_array(self.emNames)
     CkRegisterMainChareExt(self.chareNames[-1], c1, self.emStart, numEntryMethods, &chareIdx, &startEpIdx)
     self.emStart = len(self.emNames)
     return chareIdx, startEpIdx
@@ -534,7 +534,7 @@ class CharmLib(object):
     self.chareNames.append(name.encode())
     cdef int chareIdx, startEpIdx
     self.emNames += [name.encode() for name in entryMethodNames]
-    cdef char** c1 = to_cstring_array(self.emNames)
+    cdef const char** c1 = <const char**>to_cstring_array(self.emNames)
     CkRegisterGroupExt(self.chareNames[-1], c1, self.emStart, numEntryMethods, &chareIdx, &startEpIdx)
     self.emStart = len(self.emNames)
     return chareIdx, startEpIdx
@@ -543,7 +543,7 @@ class CharmLib(object):
     self.chareNames.append(name.encode())
     cdef int chareIdx, startEpIdx
     self.emNames += [name.encode() for name in entryMethodNames]
-    cdef char** c1 = to_cstring_array(self.emNames)
+    cdef const char** c1 = <const char**>to_cstring_array(self.emNames)
 
     CkRegisterSectionManagerExt(self.chareNames[-1], c1, self.emStart, numEntryMethods, &chareIdx, &startEpIdx)
     self.emStart = len(self.emNames)
@@ -553,7 +553,7 @@ class CharmLib(object):
     self.chareNames.append(name.encode())
     cdef int chareIdx, startEpIdx
     self.emNames += [name.encode() for name in entryMethodNames]
-    cdef char** c1 = to_cstring_array(self.emNames)
+    cdef const char** c1 = <const char**>to_cstring_array(self.emNames)
     CkRegisterArrayMapExt(self.chareNames[-1], c1, self.emStart, numEntryMethods, &chareIdx, &startEpIdx)
     self.emStart = len(self.emNames)
     return chareIdx, startEpIdx
@@ -562,7 +562,7 @@ class CharmLib(object):
     self.chareNames.append(name.encode())
     cdef int chareIdx, startEpIdx
     self.emNames += [name.encode() for name in entryMethodNames]
-    cdef char** c1 = to_cstring_array(self.emNames)
+    cdef const char** c1 = <const char**>to_cstring_array(self.emNames)
     CkRegisterArrayExt(self.chareNames[-1], c1, self.emStart, numEntryMethods, &chareIdx, &startEpIdx)
     self.emStart = len(self.emNames)
     return chareIdx, startEpIdx

With these edits, GCC 15 compiles the generated C with no extra flags (0 errors). Clang with -Werror=implicit-function-declaration builds and links it, and libcharm4py exports all six symbols. I only compile- and link-checked it; I didn't run the test suite with it, because my local libcharm is older than these headers. It works with any charm version because charm.h doesn't have to change. If charm.h ever declares these functions, its declarations need the same void * first argument, or C will report conflicting types. With this in, the -Wno-error=implicit-function-declaration that setup.py adds to CPPFLAGS on macOS (line 86) could go too.

Minor: c_object_store is C++ (# distutils: language=c++), and both options are C-only in GCC, so they have no effect on that extension. g++ 15 compiles it without them and accepts them silently, so this is harmless.

…ut flags

GCC 14 makes implicit-function-declaration and incompatible-pointer-types
errors by default. Compiling charmlib_cython.c hit 11 of them:

- Six functions charm4py calls (LBTurnInstrumentOn/Off and
  CkExtContributeTo{Chare,Group,Array,Section}) are defined in libcharm
  with C linkage but not declared in charm.h, so the generated C called
  them with no prototype. ccharm.pxd now declares them in a C block.
- The entry-method name arrays passed to the five CkRegister*Ext
  functions were char ** where charm.h takes const char **.

This replaces the -Wno-error flags of the previous commit, which would
also hide the next call made without a declaration, including one that
returns a pointer (the implicit int return truncates it to 32 bits).
setup.py is back to main.

Checked with GCC 15 (same defaults as 14) and clang with
-Werror=implicit-function-declaration, -fsyntax-only on the generated C:
0 errors against classic Charm++ headers and against recharm's
Reconverse headers configured for charm4py; main gives 11 with GCC 15.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ritvikrao ritvikrao changed the title setup.py: build the Cython extensions under GCC 14 (keep two new errors as warnings) Build the Cython extensions under GCC 14: declare the functions charm.h lacks Nov 4, 2026
@ritvikrao

Copy link
Copy Markdown
Collaborator

I pushed c1d22ca to this branch. It applies the fix from my review: the six missing prototypes are declared in ccharm.pxd and the five name arrays are now const char **, and setup.py is back to main. I updated the title and description to match. With GCC 15 it compiles with 0 errors against both classic and Reconverse headers, but it still needs the Delta build (GCC 14.2, without the CFLAGS workaround) before it leaves draft.

@AdvaitTahilyani

Copy link
Copy Markdown
Collaborator Author

Built c1d22ca on NCSA Delta: GCC 14.2.1, Python 3.13.5, with CFLAGS and CPPFLAGS unset, against Charm++ recharm 5e3f7e4 (reconverse charm4py build).

  • Build: pip install --no-build-isolation -e . succeeds with 0 errors and no implicit-declaration or incompatible-pointer warnings. Both charm4py.charmlib.charmlib_cython and charm4py.c_object_store import.

  • Control: main fails on the same setup with passing argument 2 of 'CkRegisterMainChareExt' from incompatible pointer type and similar.

  • Runtime: since you only compile-checked it, I also ran charm4py's own tests on Delta (srun -n 4 -c 1, +pe 4, job 23533157). All exit 0:

    • reductions/{array,group,section,future,custom}_reduction.py
    • qd/qd.py
    • sections/simple.py

    Those cover the CkExtContributeTo{Chare,Group,Array,Section} paths and the const char ** registration calls.

So it's good to leave draft from my side.

(Reply written by Claude in Advait's session and posted at his request.)

@AdvaitTahilyani
AdvaitTahilyani marked this pull request as ready for review November 4, 2026 22:47

@lvkale lvkale left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ritvik's rewrite (c1d22ca) fixes the causes rather than silencing the errors, and Advait built and ran the reduction, QD and section tests on Delta with GCC 14.2 and no CFLAGS workaround. Rebuilt and ran here too (macOS arm64, Python 3.13, Charm++ classic 917de4953): array/group/section/future/custom reductions, qd and sections/simple all pass on 4 PEs. Compiling the generated charmlib_cython.c directly with clang and -Werror=implicit-function-declaration placed last: main fails with the same 6 undeclared functions, this branch compiles clean.

One more thing found on the way, which this PR could take since it is in the same file: arrayMapProcNum(int gid, int ndims, const int *arrayIndex) (charmlib_cython.pyx line 1003) passes a const int * to cdef inline object array_index_to_tuple(int ndims, int *arrayIndex) (line 293). clang reports it under -Wincompatible-pointer-types (discards qualifiers), so a clang build with that warning as an error still fails; GCC files it under -Wdiscarded-qualifiers, which GCC 14 keeps as a warning. Adding const to the array_index_to_tuple parameter fixes it. Main has the same code, so it is not blocking.

Note for the darwin branch of setup.py: it appends -Wno-error=implicit-function-declaration through CPPFLAGS, after CFLAGS, so a user's CFLAGS=-Werror=... is cancelled on macOS. With this PR in, that flag can go in a follow-up.

Follow-up for the charm repository: declare LBTurnInstrumentOn/Off and the four CkExtContributeTo* functions in charm.h with the same void * first argument, so the private prototypes in ccharm.pxd can go.

(Review written by Claude in Kale's session and posted at his request.)

@lvkale lvkale left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved (local build, tests and review in the comment above).

@ritvikrao
ritvikrao merged commit 922a8a9 into main Nov 6, 2026
13 checks passed
@ritvikrao
ritvikrao deleted the setup-gcc14 branch November 6, 2026 22:13
lvkale added a commit that referenced this pull request Nov 7, 2026
Merge queue for PRs #310-#313, stale PR and issue triage, release 1.2,
the live-tools and runtime lines, a survey of what charm4py can use of
Charm++'s GPU support (device-resident data, device-to-device messaging,
the GPU-aware load balancer), docs and ownership.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Ritvik Rao <rsrao2@illinois.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants