Skip to content

Conversation

jcfr
Copy link
Contributor

@jcfr jcfr commented Aug 26, 2025

This PR enhances simplecpp to support resolving headers from Apple-style Framework directories while preserving the left-to-right order of interleaved -I/-F/-iframework search paths, similar to GCC/Clang
on Darwin.

Key changes include:

  • Addition of DUI::SearchPath with PathKind {Include, Framework, SystemFramework}.
  • If DUI::searchPaths is non-empty, it is used verbatim, otherwise includePaths are mirrored as Include paths for backward compatibility.
  • openHeader() now consults typed paths and rewrites <Pkg/Hdr.h> to Pkg.framework/{Headers,PrivateHeaders}/Hdr.h only when a package prefix exists.
  • toAppleFrameworkRelatives() implemented to return prioritized candidates (Headers first, then PrivateHeaders).
  • CLI updated to support -F<dir> and -iframework<dir>, in addition to -I.
  • Tests updated to use PathKind::Framework for framework layout.

These changes bring simplecpp closer to GCC/Clang behavior on macOS and enable robust resolution of framework headers like Foundation/Foundation.h.


Supersedes the following pull request:

@jcfr
Copy link
Contributor Author

jcfr commented Aug 26, 2025

This should be further improved following guidance originally posted by @glankk in #448 (comment)

I suggest we emulate gcc's darwin-specific -F option, and possibly -iframework as well. See https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html. The -F paths are interleaved with -I and searched left-to-right, so the order of interleaved normal include paths and frameworks should be preserved. For this we could change the DUI::includePaths from being a vector of path strings to being a vector of structs with a path string and, on darwin, a framework flag that determines what search rules to use.

@firewave
Copy link
Collaborator

Looks like this is currently executed for all code even if there is no apple framework is available which seems excessive. I wonder if this behavior should be configurable via DUI or consider the __APPLE__ preprocessor define.

Even if it is available it might not be the files you are looking for (can there be conflicts?) as this behavior would be limited to the Apple compiler.

@jcfr
Copy link
Contributor Author

jcfr commented Aug 26, 2025

Looks like this is currently executed for all code even if there is no apple framework is available which seems excessive.

Indeed, this was a deliberate choice anticipating the use of the tool in the context of cross compilation. Adding an option to enable/disable the behavior may be best.

@jcfr jcfr force-pushed the apple-framework-header-support branch 2 times, most recently from c5a5cbe to cdd5fc2 Compare August 26, 2025 17:54
@jcfr
Copy link
Contributor Author

jcfr commented Aug 26, 2025

@glankk Thanks for the suggestion 🙏

All the review comments have been addressed. Once the GitHub workflow have been enabled and the test pass, I believe this will be ready for integration 🚀

we also included a comprehensive docstring explaining how to work with the DUI struct.

/**
 * Command line preprocessor settings.
 *
 * Mirrors typical compiler options:
 *   -D <name>=<value>       Add macro definition
 *   -U <name>               Undefine macro
 *   -I <dir>                Add include search directory
 *   -F <dir>                Add framework search directory (Darwin)
 *   -iframework <dir>       Add system framework search directory (Darwin)
 *   --include <file>        Force inclusion of a header
 *   -std=<version>          Select language standard (C++17, C23, etc.)
 *
 * Path search behavior:
 *   - If searchPaths is non-empty, it is used directly, preserving the
 *     left-to-right order and distinguishing between Include, Framework,
 *     and SystemFramework kinds.
 *   - If searchPaths is empty, legacy includePaths is used instead, and
 *     each entry is treated as a normal Include path (for backward
 *     compatibility).
 */

To improve the developer experience, we could also further extend the DUI API:

// Mirrors GCC/Clang -I <dir>
void addIncludePath(const std::string& p) {
    searchPaths.push_back({p, PathKind::Include});
}

// Mirrors GCC/Clang -F <dir>
void addFrameworkPath(const std::string& p) {
    searchPaths.push_back({p, PathKind::Framework});
}

// Mirrors GCC/Clang -iframework <dir>
void addSystemFrameworkPath(const std::string& p) {
    searchPaths.push_back({p, PathKind::SystemFramework});
}

If that sounds reasonable, I can amend the last commit and update the tests.

cc: @danmar

@jcfr
Copy link
Contributor Author

jcfr commented Aug 26, 2025

Waiting this is integrated, we will stage those changes into a fork and move forward with vendoring those into PythonQt.

Related:

@firewave
Copy link
Collaborator

#283 possibly needs to be addressed as prerequisite of this as the include directories are currently not differentiated between system and "local" ones.

@hjmjohnson
Copy link

@jcfr Thank you for the comprehensive solution. I am closing #448.

@jcfr
Copy link
Contributor Author

jcfr commented Aug 27, 2025

Thanks again @hjmjohnson for working on the initial patch and establishing the momentum 🙏

Hopefully our contributions will be integrated shortly 🤞

@jcfr

This comment was marked as outdated.

hjmjohnson and others added 3 commits August 29, 2025 01:02
Apple frameworks store headers under:
  <Pkg.framework/Headers/MyHdr.h>

This patch extends `openHeader(...)` so that
`__has_include(<Pkg/MyHdr.h>)` resolves to the framework
layout. A new test `appleFrameworkHasIncludeTest` verifies
the behavior.

Tests:
- Add dummy `Foundation.h` fixture under `testsuite/Foundation.framework/Headers/`.

Note: this applies only to `__has_include`; plain `#include`
still uses the existing lookup logic.

Co-authored-by: Jean-Christophe Fillion-Robin <[email protected]>
Follow-up to the earlier patch that added framework handling for
`__has_include`. This change updates `preprocess()` so that plain
`#include <Pkg/MyHdr.h>` also resolves to
`<Pkg.framework/Headers/MyHdr.h>` when present.

Tests:
- Add `appleFrameworkIncludeTest` to verify `#include` resolution.

Co-authored-by: Hans Johnson <[email protected]>
@jcfr jcfr force-pushed the apple-framework-header-support branch from e0ed0e3 to 3a900a2 Compare August 29, 2025 05:05
@jcfr jcfr changed the title Add Apple Framework header support for __has_include and #include feat: Add Darwin-style framework search with ordered path lookup Aug 29, 2025
…th lookup

This change teaches simplecpp to resolve headers from Apple-style Framework
directories while preserving the left-to-right order of interleaved
-I/-F/-iframework search paths (like GCC/Clang on Darwin).

- Add `DUI::SearchPath` with `PathKind {Include, Framework, SystemFramework}`.
- If `DUI::searchPaths` is non-empty, use it verbatim (interleaved -I/-F/-iframework).
  Otherwise preserve back-compat by mirroring `includePaths` as Include paths.
- Update `openHeader()` to consult typed paths, and only rewrite `<Pkg/Hdr.h>`
  to `Pkg.framework/{Headers,PrivateHeaders}/Hdr.h` when a package prefix exists.
- Implement `toAppleFrameworkRelatives()` returning prioritized candidates
  (Headers first, then PrivateHeaders).
- Update CLI: support `-F<dir>` and `-iframework<dir>` (and keep `-I` as before).
- Tests use `PathKind::Framework` when checking framework layout.

Behavior notes
- The order of -I/-F/-iframework is preserved exactly as provided.
- `Framework` vs `SystemFramework` differ only in diagnostic semantics (not lookup).
- Legacy users who only set `DUI::includePaths` see identical behavior.

This brings simplecpp closer to GCC/Clang behavior on macOS and enables
robust resolution of framework headers like `Foundation/Foundation.h`.

Suggested-by: [email protected]
@jcfr jcfr force-pushed the apple-framework-header-support branch from 3a900a2 to 6899f8e Compare August 29, 2025 05:25
Copy link
Owner

@danmar danmar left a comment

Choose a reason for hiding this comment

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

So if I understand it correctly.. if the command line only uses -I then behavior will be unchanged?

this looks pretty good to me. I would like a review by @glankk

To improve the developer experience, we could also further extend the DUI API:

please look at adding such helper functions. It sounds good to me.

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.

4 participants