Python clang不搜索系统包含路径

时间:2014-10-18 14:37:47

标签: python c++ clang libclang

当使用Python的libclang时,它似乎不会自动搜索系统的包含路径。

有没有可靠的方法来获得这些路径?我不喜欢硬编码路径,因为我正在编写将在各种UNIX系统上运行的代码。

例如,给定test.cpp

#include <stdio.h>

int main()
{
  puts("Hello, world!");
}

和test.py

from clang.cindex import Index

tu = Index.create().parse(None, ["test.cpp"])
print(list(tu.diagnostics))

正在运行python test.py将打印:

[<Diagnostic severity 4, location <SourceLocation file 'test.cpp', line 1, 
 column 10>, spelling "'stdio.h' file not found">]

当然,我可以通过

找到系统包含路径
$ clang -v -E test.cpp

并将"-Isome/path"添加到parse参数列表,即

args = ["-I/Applications/[...]", "test.cpp"]

这实际上有效并且不会产生任何错误。

然而,这不是可移植的,如果我能以编程方式让clang自动使用它们,那将是非常好的。

1 个答案:

答案 0 :(得分:2)

这个问题已经有一段时间了,所以我会尝试自己回答。

似乎即使是Clang本身也主要使用硬编码路径。

它枚举候选路径并添加适合当前上下文的路径。这可以在clang/lib/Frontend/InitHeaderSearch.cpp中看到。如,

uses
  System.Classes, Winapi.Windows;

type
  PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
  PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;

function ImageNtHeader(Base: Pointer): PIMAGE_NT_HEADERS; stdcall; external 'dbghelp.dll';
function ImageRvaToVa(NtHeaders: Pointer; Base: Pointer; Rva: ULONG; LastRvaSection: Pointer): Pointer; stdcall; external 'dbghelp.dll';

procedure EnumerateImageExportedFunctionNames(const ImageName: string; NamesList: TStrings);
var
  i: Integer;
  FileHandle: THandle;
  ImageHandle: THandle;
  ImagePointer: Pointer;
  Header: PIMAGE_NT_HEADERS;
  ExportTable: PIMAGE_EXPORT_DIRECTORY;
  NamesPointer: Pointer;
  NamesPtr: PCardinal;
  NamePtr: PAnsiChar;
begin
  //NOTE: our policy in this procedure is to exit upon any failure and return and empty list

  NamesList.Clear;

  FileHandle := CreateFile(
    PChar(ImageName),
    GENERIC_READ,
    FILE_SHARE_READ,
    nil,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    0
  );
  if FileHandle=INVALID_HANDLE_VALUE then begin
    exit;
  end;
  Try
    ImageHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
    if ImageHandle=0 then begin
      exit;
    end;
    Try
      ImagePointer := MapViewOfFile(ImageHandle, FILE_MAP_READ, 0, 0, 0);
      if not Assigned(ImagePointer) then begin
        exit;
      end;

      Try
        Header := ImageNtHeader(ImagePointer);
        if not Assigned(Header) then begin
          exit;
        end;
        if Header.Signature<>$00004550 then begin // "PE\0\0" as a DWORD.
          exit;
        end;

        ExportTable := ImageRvaToVa(Header, ImagePointer, Header.OptionalHeader.DataDirectory[0].VirtualAddress, nil);
        if not Assigned(ExportTable) then begin
          exit;
        end;

        NamesPtr := ImageRvaToVa(Header, ImagePointer, Cardinal(ExportTable.AddressOfNames), nil);
        if not Assigned(NamesPtr) then begin
          exit;
        end;

        for i := 0 to ExportTable.NumberOfNames-1 do begin
          NamePtr := ImageRvaToVa(Header, ImagePointer, NamesPtr^, nil);
          if not Assigned(NamePtr) then begin
            exit;
          end;

          NamesList.Add(NamePtr);
          inc(NamesPtr);
        end;
      Finally
        UnmapViewOfFile(ImagePointer); // Ignore error as there is not much we could do.
      End;
    Finally
      CloseHandle(ImageHandle);
    End;
  Finally
    CloseHandle(FileHandle);
  End;
end;

对于Linux,此代码有通知:

AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
                           "i686-apple-darwin10", "", "x86_64", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
                           "i686-apple-darwin8", "", "", triple);

// ...

llvm_unreachable("Include management is handled in the driver."); 下,我们可以在clang/lib/Driver/ToolChains.cppCrossWindowsToolChain.cpp等文件中找到更多这些路径。

我希望的是MinGWToolChain.cpp中的代码将通过libclang向Python公开。