Skip to content

Fix undefined symbol errors with Ruby 2.7+#2

Open
aashutosh-sahni wants to merge 2 commits intomasterfrom
fix/iso646-function-names
Open

Fix undefined symbol errors with Ruby 2.7+#2
aashutosh-sahni wants to merge 2 commits intomasterfrom
fix/iso646-function-names

Conversation

@aashutosh-sahni
Copy link
Copy Markdown
Collaborator

@aashutosh-sahni aashutosh-sahni commented May 4, 2026

⚠️ DO NOT MERGE — tagged directly as v1.2.2

This branch has been tagged as v1.2.2 and is already in use via tag: "v1.2.2" in the bookingbug app Gemfile. Do not merge to master — it is not needed and could affect other environments that depend on the default branch.

This PR remains open for documentation/review purposes only.


Summary

  • Rename C functions and, or, xor, difference to bitset_and, bitset_or, bitset_xor, bitset_difference
  • Change inline to static (C99 inline doesn't guarantee symbol emission; taking function pointers fails at link time)
  • Rename pointer references (&and&bitset_and, etc.)
  • Ruby method aliases ("and", "or", "xor") are unchanged — no API change

Why

and and or are ISO C95 alternative operator tokens defined in <iso646.h> as #define and && / #define or ||. Ruby 2.7+ headers include this header, so the preprocessor replaces the function names with operators during compilation. The .so compiles but the symbols are mangled/missing, resulting in:

LoadError: .../bitset.so: undefined symbol: and

Additionally, C99 inline without static or extern does not guarantee the compiler emits a standalone symbol. When function pointers are taken (&bitset_or), the linker fails with undefined symbol: bitset_or. Using static ensures symbols are always emitted.

Tagged as v1.2.2

git tag v1.2.2  →  b95d1c420d799d5f8902ca8031bde73058e54683

Usage in bookingbug Gemfile:

gem "bitset", git: "https://github.com/BookingBug/bitset.git", tag: "v1.2.2"

Test plan

  • Verified diff only touches internal C function names (4 definitions + 4 pointer refs)
  • Tagged as v1.2.2, Gemfile updated in DEV-6939
  • Deploy to DEV05 under Ruby 2.7.8 — confirm db:migrate passes

🤖 Generated with Claude Code

Rename and/or/xor/difference to bitset_and/bitset_or/bitset_xor/bitset_difference.
These names are ISO C95 alternative operator tokens (<iso646.h>), and Ruby 2.7+
headers pull in that header, causing the preprocessor to replace the function
names with operators. Result: 'undefined symbol: and' at runtime.

Ruby method aliases ("and", "or", "xor") are unchanged -- only the internal
C function names and their pointer references are renamed.
@aashutosh-sahni aashutosh-sahni requested a review from richkettle May 4, 2026 14:21
inline alone does not guarantee symbol emission in C99 -- the compiler
may inline at call sites and omit the standalone symbol. When the code
takes function pointers (&bitset_or etc), the linker fails with
'undefined symbol: bitset_or'. Change to static to ensure symbols are
always available in the translation unit.
@richkettle
Copy link
Copy Markdown

I assume we checked upstream for ruby 2.7 compatibility changes?

@aashutosh-sahni
Copy link
Copy Markdown
Collaborator Author

Yes — upstream is ericboesch/bitset, last commit 2018. Still has the same inline uint64_t and(...) functions. No Ruby 2.7 compatibility fix exists upstream. The repo appears abandoned.

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.

2 participants