From ae98755ec59478e277f9b01d532607c57c08a49e Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Wed, 16 Jul 2025 15:39:20 -0500 Subject: [PATCH 1/2] ENH: Add support to find Headers in Apple Frameworks The header locations in apple frameworks require manipulation of the directory name in a '' include defintion. The header file is located at in a framework. --- simplecpp.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/simplecpp.cpp b/simplecpp.cpp index 721bbdeb..ccb71ad6 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3006,6 +3006,34 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const if (!path.empty()) return path; } +#ifdef __APPLE__ + // a named lambda function to insert the ".framework/Headers" part for apple frameworks + auto get_apple_framework_relative_path= [](std::string appleFrameworkHeader) -> std::string + { + // try the Framework path on apple OS, if there is a path in front + const size_t slashPos = appleFrameworkHeader.find('/'); + if (slashPos != std::string::npos) + { + constexpr auto framework_separator{ ".framework/Headers" }; + appleFrameworkHeader.insert(slashPos, framework_separator); + } + return appleFrameworkHeader; + }; + + // on Apple, try to find the header in the framework path + // Convert /PKGNAME/myHeader -> /PKGNAME.framework/Headers/myHeader + const std::string appleFrameworkHeader = get_apple_framework_relative_path(header); + if (appleFrameworkHeader != header) + { + for (const auto & includePath: dui.includePaths) + { + const std::string frameworkCandidatePath = includePath + '/' + appleFrameworkHeader; + std::string simplePath = openHeaderDirect(f, simplecpp::simplifyPath(frameworkCandidatePath )); + if (!simplePath.empty()) + return simplePath; + } + } +#endif // __APPLE__ return ""; } From de9d233f691a655e789c4ecc3ec8a00f2421b6d0 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Wed, 16 Jul 2025 16:39:42 -0500 Subject: [PATCH 2/2] ENH: Add test outline for Apple framework include handling This is an outline of a test. The test currently fails. I could not figure out how these tests are working. I would greatly appreciate a little help to understand how to use the test framework. --- test.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test.cpp b/test.cpp index a7578823..ed5ac7d4 100644 --- a/test.cpp +++ b/test.cpp @@ -2084,6 +2084,32 @@ static void systemInclude() ASSERT_EQUALS("", toString(outputList)); } +#if 0 // Disabled until the test can be written properly +#ifdef __APPLE__ +static void appleFrameworkIncludeTest() +{ + // This test is for the Apple framework include handling. + // If -I /Library/Developer/CommandLineTools/SDKs/MacOSX14.5.sdk/System/Library/Frameworks + // then: + const char code[] = "#include \n"; + // should find the include file: + // /Library/Developer/CommandLineTools/SDKs/MacOSX14.5.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h + std::vector files; + const simplecpp::TokenList rawtokens = makeTokenList(code,files,"sourcecode.cpp"); + simplecpp::FileDataCache cache; + cache.insert({"Foundation/Foundation.h", simplecpp::TokenList(files)}); + + simplecpp::TokenList tokens2(files); + simplecpp::DUI dui; + dui.includePaths.push_back("/Library/Developer/CommandLineTools/SDKs/MacOSX14.5.sdk/System/Library/Frameworks"); + + simplecpp::OutputList outputList; + simplecpp::preprocess(tokens2, rawtokens, files, cache, dui, &outputList); + ASSERT_EQUALS("", toString(outputList)); +} +#endif +#endif + static void multiline1() { const char code[] = "#define A \\\n" @@ -3388,6 +3414,11 @@ int main(int argc, char **argv) TEST_CASE(preprocess_files); TEST_CASE(fuzz_crash); - +#if 0 // Disabled until the test can be written properly +#ifdef __APPLE__ + // Apple-specific test cases + TEST_CASE(appleFrameworkIncludeTest); +#endif +#endif return numberOfFailedAssertions > 0 ? EXIT_FAILURE : EXIT_SUCCESS; }