Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clang doesn't add builtins directory (LLVM-292) #83

Closed
aykevl opened this issue Oct 24, 2023 · 1 comment
Closed

Clang doesn't add builtins directory (LLVM-292) #83

aykevl opened this issue Oct 24, 2023 · 1 comment
Assignees
Labels
Resolution: NA Status: Done Issue is done internally

Comments

@aykevl
Copy link

aykevl commented Oct 24, 2023

Clang has multiple flags for controlling the include path. From the documentation:

-nostdinc
Do not search the standard system directories or compiler builtin directories for include files.

-nostdlibinc
Do not search the standard system directories for include files, but do search compiler builtin include directories.

-nobuiltininc
Do not search clang’s builtin directory for include files.

So in effect, -nostdinc implies -nostdlibinc and -nobuiltininc. But to control the standard system include dir and the builtins include dir separately, we have -nostdlibinc and -nobuiltininc to control those two kinds of include dirs separately.

You can see the logic here for the RISCV toolchain:

void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                               ArgStringList &CC1Args) const {
  if (DriverArgs.hasArg(options::OPT_nostdinc))
    return;

  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
    SmallString<128> Dir(getDriver().ResourceDir);
    llvm::sys::path::append(Dir, "include");
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
  }

  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
    SmallString<128> Dir(computeSysRoot());
    llvm::sys::path::append(Dir, "include");
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
  }
}

For BareMetal it's similar, with the addition of multilib:

void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                          ArgStringList &CC1Args) const {
  if (DriverArgs.hasArg(options::OPT_nostdinc))
    return;

  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
    SmallString<128> Dir(getDriver().ResourceDir);
    llvm::sys::path::append(Dir, "include");
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
  }

  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
    const SmallString<128> SysRoot(computeSysRoot());
    if (!SysRoot.empty()) {
      for (const Multilib &M : getOrderedMultilibs()) {
        SmallString<128> Dir(SysRoot);
        llvm::sys::path::append(Dir, M.includeSuffix());
        llvm::sys::path::append(Dir, "include");
        addSystemInclude(DriverArgs, CC1Args, Dir.str());
      }
    }
  }
}

Unfortunately, it seems that Xtensa ignores the builtins include directory unless a GCC installation has been found. In fact, if the -nostdlibinc flag is passed, it exits early without adding the builtins directory at all!

void XtensaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                                ArgStringList &CC1Args) const {
  if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) ||
      DriverArgs.hasArg(options::OPT_nostdlibinc))
    return;

  if (!getDriver().SysRoot.empty()) {
    SmallString<128> Dir(getDriver().SysRoot);
    llvm::sys::path::append(Dir, "include");
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
  } else if (GCCInstallation.isValid()) {
    SmallString<128> Path1(getDriver().ResourceDir);
    llvm::sys::path::append(Path1, "include");
    SmallString<128> Path2(GCCToolchainDir);
    llvm::sys::path::append(Path2, GCCToolchainName, "sys-include");
    SmallString<128> Path3(GCCToolchainDir);
    llvm::sys::path::append(Path3, GCCToolchainName, "include");

    const StringRef Paths[] = {Path1, Path2, Path3};
    addSystemIncludes(DriverArgs, CC1Args, Paths);
  } else {
    SmallString<128> Dir(computeSysRoot());
    llvm::sys::path::append(Dir, "include");
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
  }
}

This makes no sense to me, since the resources directory is specific to Clang. On Linux, it's the /usr/lib/clang/<version>/include/ directory.

In TinyGo, we're not using a GCC installation. We use picolibc as the libc, and otherwise use LLVM native tools. Therefore, there is no GCC installation. To better control this, we pass -nostdlibinc to ignore the system libc, with the expectation that the builtins directory is still added. Xtensa is the only platform where this is not the case.

Somehow this still works when using Clang as-is (hence why I don't have an easy reproducer) because Clang seems to add this directory again somewhere else, but when I use it with libclang and specify the resource directory manually, the builtins directory doesn't get added.

@github-actions github-actions bot changed the title Clang doesn't add builtins directory Clang doesn't add builtins directory (LLVM-292) Oct 24, 2023
@gerekon
Copy link
Collaborator

gerekon commented Oct 26, 2023

Hi @aykevl
Thanks for the findings. Will fix this.

@espressif-bot espressif-bot added Status: In Progress work is in progress and removed Status: Opened labels Oct 26, 2023
yamt pushed a commit to yamt/llvm-project that referenced this issue May 12, 2024
This fixes espressif#83

In short, it adjusts the include path logic to include the builtins
directory as long as `-nostdinc` or `-nobuiltininc` isn't specified.
Previously, the builtins directory would not be included if either the
GCC installation wasn't found, or `-nostdlibinc` was specified (both of
which aren't related to the builtins directory).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: NA Status: Done Issue is done internally
Projects
None yet
Development

No branches or pull requests

3 participants