Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -8298,6 +8298,11 @@ def internal_externc_isystem : Separate<["-"], "internal-externc-isystem">,
"implicit extern \"C\" semantics; these are assumed to not be "
"user-provided and are used to model system and standard headers' "
"paths.">;
def internal_iframework : Separate<["-"], "internal-iframework">,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we call this internal-externc-iframework since it more closely corresponds to internal-externc-isystem than internal-isystem? Especially its position in the search ordering system -> internal-system -> internal-externc-system

Copy link
Member Author

Choose a reason for hiding this comment

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

Is it really closer to internal-externc-isystem than internal-isystem though? My understanding is that all of these flags are simply taken (by CC1) in the order in which they appear in the command-line. Is that not what's happening?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, they get bucketed. e.g. internal-externc-isystem always comes after -isystem no matter which order the flags are on the command line.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see. But there is no notion of "extern C" for framework includes, so IMO it makes more sense to make -internal-iframework "equivalent" to -internal-isystem than to -internal-externc-isystem, would you agree?

More generally, I guess I am confused about the desired grouping for framework includes. Do we want them to be IncludeDirGroup::System, IncludeDirGroup::ExternCSystem or something else? IIUC, -iframework is already part of IncludeDirGroup::System. If that's correct, then why is it not sufficient to pass these system framework paths using -iframework directly in the first place (i.e. why do we even need to introduce -internal-iframework in the first place)?

Copy link
Member Author

Choose a reason for hiding this comment

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

(As a test to make sure I'm not crazy, I just committed e624fd8 which removes -internal-iframework - I expect that won't work as intended)

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry for the naive question, but where/how is that order determined?

Copy link
Contributor

Choose a reason for hiding this comment

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

That one I don't know, I've only empirically observed by taking a look at -v output.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

@ian-twilightcoder ian-twilightcoder Jan 9, 2025

Choose a reason for hiding this comment

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

But it's not as straightforward as the paths being added in the particular order, the group matters too. But only sometimes - After goes last, but ExternCSystem and System get mixed in together.

Copy link
Contributor

Choose a reason for hiding this comment

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

So I guess maybe it doesn't matter and internal-iframework is fine, we just need ParseHeaderSearchArgs to put it where we want?

MetaVarName<"<directory>">,
HelpText<"Add directory to the internal system framework include search path; these "
"are assumed to not be user-provided and are used to model system "
"and standard frameworks' paths.">;

} // let Visibility = [CC1Option]

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/Job.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
.Cases("-internal-externc-isystem", "-iprefix", true)
.Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
.Cases("-isysroot", "-I", "-F", "-resource-dir", true)
.Cases("-iframework", "-include-pch", true)
.Cases("-internal-iframework", "-iframework", "-include-pch", true)
.Default(false);
if (IsInclude)
return !HaveCrashVFS;
Expand Down
48 changes: 35 additions & 13 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,9 +800,15 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}

// Add non-standard, platform-specific search paths, e.g., for DriverKit:
// -L<sysroot>/System/DriverKit/usr/lib
// -F<sysroot>/System/DriverKit/System/Library/Framework
// Add framework include paths and library search paths.
// There are two flavors:
// 1. The "non-standard" paths, e.g. for DriverKit:
// -L<sysroot>/System/DriverKit/usr/lib
// -F<sysroot>/System/DriverKit/System/Library/Frameworks
// 2. The "standard" paths, e.g. for macOS and iOS:
// -F<sysroot>/System/Library/Frameworks
// -F<sysroot>/System/Library/SubFrameworks
// -F<sysroot>/Library/Frameworks
{
bool NonStandardSearchPath = false;
const auto &Triple = getToolChain().getTriple();
Expand All @@ -813,18 +819,23 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
(Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);
}

if (NonStandardSearchPath) {
if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
SmallString<128> P(Sysroot->getValue());
AppendPlatformPrefix(P, Triple);
llvm::sys::path::append(P, SearchPath);
if (getToolChain().getVFS().exists(P)) {
CmdArgs.push_back(Args.MakeArgString(Flag + P));
}
};
if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
SmallString<128> P(Sysroot->getValue());
AppendPlatformPrefix(P, Triple);
llvm::sys::path::append(P, SearchPath);
if (getToolChain().getVFS().exists(P)) {
CmdArgs.push_back(Args.MakeArgString(Flag + P));
}
};

if (NonStandardSearchPath) {
AddSearchPath("-L", "/usr/lib");
AddSearchPath("-F", "/System/Library/Frameworks");
} else if (!Triple.isDriverKit()) {
AddSearchPath("-F", "/System/Library/Frameworks");
AddSearchPath("-F", "/System/Library/SubFrameworks");
AddSearchPath("-F", "/Library/Frameworks");
}
}
}
Expand Down Expand Up @@ -2547,6 +2558,17 @@ void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs
llvm::sys::path::append(P, "usr", "include");
addExternCSystemInclude(DriverArgs, CC1Args, P.str());
}

// Add default framework search paths
auto AddFrameworkInclude = [&](StringRef Flag, StringRef SearchPath) {
SmallString<128> P(Sysroot);
llvm::sys::path::append(P, SearchPath);
CC1Args.push_back(DriverArgs.MakeArgString(Flag));
CC1Args.push_back(DriverArgs.MakeArgString(P));
};
AddFrameworkInclude("-internal-iframework", "/System/Library/Frameworks");
AddFrameworkInclude("-internal-iframework", "/System/Library/SubFrameworks");
AddFrameworkInclude("-internal-iframework", "/Library/Frameworks");
}

bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3436,11 +3436,14 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,

// Add the internal paths from a driver that detects standard include paths.
for (const auto *A :
Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem, OPT_internal_iframework)) {
frontend::IncludeDirGroup Group = frontend::System;
bool IsFramework = false;
if (A->getOption().matches(OPT_internal_externc_isystem))
Group = frontend::ExternCSystem;
Opts.AddPath(A->getValue(), Group, false, true);
if (A->getOption().matches(OPT_internal_iframework))
IsFramework = true;
Opts.AddPath(A->getValue(), Group, IsFramework, true);
}

// Add the path prefixes which are implicitly treated as being system headers.
Expand Down
19 changes: 3 additions & 16 deletions clang/lib/Lex/InitHeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
break;
}

if (triple.isOSDarwin())
return false;

return true; // Everything else uses AddDefaultIncludePaths().
}

Expand All @@ -335,22 +338,6 @@ void InitHeaderSearch::AddDefaultIncludePaths(
if (!ShouldAddDefaultIncludePaths(triple))
return;

// NOTE: some additional header search logic is handled in the driver for
// Darwin.
if (triple.isOSDarwin()) {
if (HSOpts.UseStandardSystemIncludes) {
// Add the default framework include paths on Darwin.
if (triple.isDriverKit()) {
AddPath("/System/DriverKit/System/Library/Frameworks", System, true);
} else {
AddPath("/System/Library/Frameworks", System, true);
AddPath("/System/Library/SubFrameworks", System, true);
AddPath("/Library/Frameworks", System, true);
}
}
return;
}

if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
if (HSOpts.UseLibcxx) {
Expand Down
26 changes: 26 additions & 0 deletions clang/test/Driver/darwin-framework-search-paths.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// UNSUPPORTED: system-windows
// Windows is unsupported because we use the Unix path separator `/` in the test.

// Add default directories before running clang to check default
// search paths.
// RUN: rm -rf %t && mkdir -p %t
// RUN: cp -R %S/Inputs/MacOSX15.1.sdk %t/
// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/Frameworks
// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/SubFrameworks
// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include

// RUN: %clang -xc %s -target arm64-apple-macosx15.1 -isysroot %t/MacOSX15.1.sdk -c -### 2>&1 \
// RUN: | FileCheck -DSDKROOT=%t/MacOSX15.1.sdk --check-prefix=CHECK-C %s
//
// CHECK-C: "-isysroot" "[[SDKROOT]]"
// CHECK-C: "-internal-externc-isystem" "[[SDKROOT]]/usr/include"
// CHECK-C: "-internal-iframework" "[[SDKROOT]]/System/Library/Frameworks"
// CHECK-C: "-internal-iframework" "[[SDKROOT]]/System/Library/SubFrameworks"

// RUN: %clang -xc++ %s -target arm64-apple-macosx15.1 -isysroot %t/MacOSX15.1.sdk -c -### 2>&1 \
// RUN: | FileCheck -DSDKROOT=%t/MacOSX15.1.sdk --check-prefix=CHECK-CXX %s
//
// CHECK-CXX: "-isysroot" "[[SDKROOT]]"
// CHECK-CXX: "-internal-externc-isystem" "[[SDKROOT]]/usr/include"
// CHECK-CXX: "-internal-iframework" "[[SDKROOT]]/System/Library/Frameworks"
// CHECK-CXX: "-internal-iframework" "[[SDKROOT]]/System/Library/SubFrameworks"
18 changes: 0 additions & 18 deletions clang/test/Driver/darwin-subframeworks.c

This file was deleted.

16 changes: 9 additions & 7 deletions clang/test/Driver/driverkit-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ int main() { return 0; }
// LD64-NEW: "-isysroot" "[[PATH:[^"]*]]Inputs/DriverKit19.0.sdk"
// LD64-NEW-NOT: "-L[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/usr/lib"
// LD64-NEW-NOT: "-F[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/Frameworks"
// LD64-NEW-NOT: "-F[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks"


// RUN: %clang %s -target x86_64-apple-driverkit19.0 -isysroot %S/Inputs/DriverKit19.0.sdk -E -v -x c++ 2>&1 | FileCheck %s --check-prefix=INC
// RUN: %clang %s -target x86_64-apple-driverkit19.0 -isysroot %S/Inputs/DriverKit19.0.sdk -x c++ -### 2>&1 \
// RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit19.0.sdk --check-prefix=INC
//
// INC: -isysroot [[PATH:[^ ]*/Inputs/DriverKit19.0.sdk]]
// INC-LABEL: #include <...> search starts here:
// INC: [[PATH]]/System/DriverKit/usr/local/include
// INC: /lib{{(64)?}}/clang/{{[^/ ]+}}/include
// INC: [[PATH]]/System/DriverKit/usr/include
// INC: [[PATH]]/System/DriverKit/System/Library/Frameworks (framework directory)
// INC: "-isysroot" "[[SDKROOT]]"
// INC: "-internal-isystem" "[[SDKROOT]]/System/DriverKit/usr/local/include"
// INC: "-internal-isystem" "{{.+}}/lib{{(64)?}}/clang/{{[^/ ]+}}/include"
// INC: "-internal-externc-isystem" "[[SDKROOT]]/System/DriverKit/usr/include"
// INC: "-internal-iframework" "[[SDKROOT]]/System/DriverKit/System/Library/Frameworks"
// INC: "-internal-iframework" "[[SDKROOT]]/System/DriverKit/System/Library/SubFrameworks"
13 changes: 0 additions & 13 deletions clang/test/Preprocessor/cuda-macos-includes.cu

This file was deleted.

Loading