Skip to content

Add native macOS/AppleClang support with CI workflow#2630

Open
tanmay-9 wants to merge 60 commits intoad-freiburg:masterfrom
tanmay-9:apple-native-build
Open

Add native macOS/AppleClang support with CI workflow#2630
tanmay-9 wants to merge 60 commits intoad-freiburg:masterfrom
tanmay-9:apple-native-build

Conversation

@tanmay-9
Copy link
Member

@tanmay-9 tanmay-9 commented Jan 7, 2026

Adds native AppleClang/macOS compatibility and a GitHub Actions workflow for CI on macOS. Additionally, add project version to the logs generated when executing qlever-index or qlever-server.

Changes

Build System

  • CMakeLists.txt: Dynamically detect Homebrew prefix on macOS to locate dependencies (Boost, ICU, OpenSSL, etc.).

Code Fixes

AppleClang enforces stricter C++ standard compliance than GCC, requiring several fixes:

  • Template disambiguation: Added template keyword for dependent template member calls.

  • Range adaptor compatibility: Wrapped range arguments in allView() before passing to transform_view to ensure proper view semantics across implementations.

  • Non-copyable types in zip_view: Use ql::ranges::ref_view to avoid copying element types (with a deleted copy constructor) on AppleClang.

  • packaged_task + Boost.Asio: Use a named variable to work around AppleClang compiler crash when passing a temporary packaged_task directly to net::post.

@codecov
Copy link

codecov bot commented Jan 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.60%. Comparing base (cca3768) to head (5601763).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2630   +/-   ##
=======================================
  Coverage   91.60%   91.60%           
=======================================
  Files         483      483           
  Lines       41360    41362    +2     
  Branches     5493     5493           
=======================================
+ Hits        37886    37888    +2     
  Misses       1897     1897           
  Partials     1577     1577           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tanmay-9 tanmay-9 marked this pull request as ready for review January 30, 2026 13:14
@tanmay-9 tanmay-9 changed the title Apple native build Add native macOS/AppleClang support with CI workflow Jan 30, 2026
@hannahbast hannahbast requested review from RobinTF, Copilot and joka921 and removed request for joka921 January 30, 2026 15:06
Copy link
Collaborator

@RobinTF RobinTF left a comment

Choose a reason for hiding this comment

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

Looks good, mostly some minor comments or thoughts.

blockStart, blockEnd,
&currentLocalVocab_, groupByCols_);
// This processes the whole block in batches if possible.
// Note: Use `template` keyword for dependent template name.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The note is a little bit redundant. That's what the template keyword is for in this scenario.


AD_LOG_INFO << EMPH_ON << "QLever index builder, compiled on "
AD_LOG_INFO << EMPH_ON << "QLever index builder "
<< qlever::version::ProjectVersion << ", compiled on "
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems to be an unrelated change, I assume this is intentional?

promise->set_exception(std::current_exception());
}
});
return fut;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is why we can't have nice things. If it's an compiler crash, did you try just assigning the packaged task to an extra variable, or playing around with scopes? Sometimes this helps. Otherwise your workaround is also fine, but I'd like to avoid the verbosity if possible.

Comment on lines 241 to 243
// Use index-based iteration instead of ranges::zip_view to avoid
// copying RowReference (which has a deleted copy constructor) on
// AppleClang.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems ... odd. zip view shouldn't copy anything. Did you try wrapping stuff in ql::ranges::ref_view? This should let you explicitly avoid copies.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Collaborator

@RobinTF RobinTF left a comment

Choose a reason for hiding this comment

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

Thank you very much for your changes, I still have 2 questions for you.

for (const auto& [rightId, leftCol] :
::ranges::zip_view(rightRow, leftColumns)) {
::ranges::views::zip(ql::ranges::ref_view{rightRow},
ql::ranges::ref_view{leftColumns})) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If I understand your comment correctly, it's only the rightRow that needs the wrapper? leftColumns should be a span, which is cheap to copy regardless.

Comment on lines 40 to 42
auto fut = task.get_future();
net::post(*ioContext, std::move(task));
return fut;
Copy link
Collaborator

Choose a reason for hiding this comment

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

So just to be sure, as soon as you turn this into

Suggested change
auto fut = task.get_future();
net::post(*ioContext, std::move(task));
return fut;
return net::post(*ioContext, std::move(task));

or

Suggested change
auto fut = task.get_future();
net::post(*ioContext, std::move(task));
return fut;
auto fut = net::post(*ioContext, std::move(task));
return fut;

The compiler crashes again, right? If not, both of these options would be more desirable.

@sparql-conformance
Copy link

Overview

Number of Tests Passed ✅ Intended ✅ Failed ❌ Not tested
547 449 73 25 0

Conformance check failed ❌

Test Status Changes 📊

Number of Tests Previous Status Current Status
1 Passed Failed

Details: https://qlever.dev/sparql-conformance-ui?cur=5601763c0729498a1280c576a69b4d75c9655437&prev=cca37689eb8be289bc51bcb675030d05dd10f671

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 3, 2026

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