Exemplo n.º 1
0
def GetClangOptionsFromNinjaForFilename(chrome_root, filename):
    """Returns the Clang command line options needed for building |filename|.

  Command line options are based on the command used by ninja for building
  |filename|. If |filename| is a .h file, uses its companion .cc or .cpp file.
  If a suitable companion file can't be located or if ninja doesn't know about
  |filename|, then uses default source files in Blink and Chromium for
  determining the commandline.

  Args:
    chrome_root: (String) Path to src/.
    filename: (String) Absolute path to source file being edited.

  Returns:
    (List of Strings) The list of command line flags for this source file. Can
    be empty.
  """
    if not chrome_root:
        return []

    # Generally, everyone benefits from including Chromium's src/, because all of
    # Chromium's includes are relative to that.
    additional_flags = ['-I' + os.path.join(chrome_root)]

    # Version of Clang used to compile Chromium can be newer then version of
    # libclang that YCM uses for completion. So it's possible that YCM's libclang
    # doesn't know about some used warning options, which causes compilation
    # warnings (and errors, because of '-Werror');
    additional_flags.append('-Wno-unknown-warning-option')

    sys.path.append(os.path.join(chrome_root, 'tools', 'vim'))
    from ninja_output import GetNinjaOutputDirectory
    out_dir = os.path.realpath(GetNinjaOutputDirectory(chrome_root))

    clang_line = GetClangCommandLineFromNinjaForSource(
        out_dir, GetBuildableSourceFile(chrome_root, filename))
    if not clang_line:
        # If ninja didn't know about filename or it's companion files, then try a
        # default build target. It is possible that the file is new, or build.ninja
        # is stale.
        clang_line = GetClangCommandLineFromNinjaForSource(
            out_dir, GetDefaultSourceFile(chrome_root, filename))

    if not clang_line:
        return (additional_flags, [])

    return GetClangOptionsFromCommandLine(clang_line, out_dir,
                                          additional_flags)
Exemplo n.º 2
0
def GetClangCommandFromNinjaForFilename(v8_root, filename):
    """Returns the command line to build |filename|.

  Asks ninja how it would build the source file. If the specified file is a
  header, tries to find its companion source file first.

  Args:
    v8_root: (String) Path to v8/.
    filename: (String) Path to source file being edited.

  Returns:
    (List of Strings) Command line arguments for clang.
  """
    if not v8_root:
        return []

    # Generally, everyone benefits from including V8's root, because all of
    # V8's includes are relative to that.
    v8_flags = ['-I' + os.path.join(v8_root)]

    # Version of Clang used to compile V8 can be newer then version of
    # libclang that YCM uses for completion. So it's possible that YCM's libclang
    # doesn't know about some used warning options, which causes compilation
    # warnings (and errors, because of '-Werror');
    v8_flags.append('-Wno-unknown-warning-option')

    # Header files can't be built. Instead, try to match a header file to its
    # corresponding source file.
    if filename.endswith('.h'):
        alternates = ['.cc', '.cpp']
        for alt_extension in alternates:
            alt_name = filename[:-2] + alt_extension
            if os.path.exists(alt_name):
                filename = alt_name
                break
        else:
            if filename.endswith('-inl.h'):
                for alt_extension in alternates:
                    alt_name = filename[:-6] + alt_extension
                    if os.path.exists(alt_name):
                        filename = alt_name
                        break
                else:
                    # If this is a standalone -inl.h file with no source, the best we can
                    # do is try to use the default flags.
                    return v8_flags
            else:
                # If this is a standalone .h file with no source, the best we can do is
                # try to use the default flags.
                return v8_flags

    sys.path.append(os.path.join(v8_root, 'tools', 'ninja'))
    from ninja_output import GetNinjaOutputDirectory
    out_dir = os.path.realpath(GetNinjaOutputDirectory(v8_root))

    # Ninja needs the path to the source file relative to the output build
    # directory.
    rel_filename = os.path.relpath(os.path.realpath(filename), out_dir)

    # Ask ninja how it would build our source file.
    p = subprocess.Popen(
        ['ninja', '-v', '-C', out_dir, '-t', 'commands', rel_filename + '^'],
        stdout=subprocess.PIPE)
    stdout, stderr = p.communicate()
    if p.returncode:
        return v8_flags

    # Ninja might execute several commands to build something. We want the last
    # clang command.
    clang_line = None
    for line in reversed(stdout.split('\n')):
        if 'clang' in line:
            clang_line = line
            break
    else:
        return v8_flags

    # Parse flags that are important for YCM's purposes.
    for flag in clang_line.split(' '):
        if flag.startswith('-I'):
            # Relative paths need to be resolved, because they're relative to the
            # output dir, not the source.
            if flag[2] == '/':
                v8_flags.append(flag)
            else:
                abs_path = os.path.normpath(os.path.join(out_dir, flag[2:]))
                v8_flags.append('-I' + abs_path)
        elif flag.startswith('-std'):
            v8_flags.append(flag)
        elif flag.startswith('-') and flag[1] in 'DWFfmO':
            if flag == '-Wno-deprecated-register' or flag == '-Wno-header-guard':
                # These flags causes libclang (3.3) to crash. Remove it until things
                # are fixed.
                continue
            v8_flags.append(flag)

    return v8_flags
Exemplo n.º 3
0
def GetClangOptionsFromNinjaForFilename(webrtc_root, filename):
    """Returns the Clang command line options needed for building `filename`.

  Command line options are based on the command used by ninja for building
  `filename`. If `filename` is a .h file, uses its companion .cc or .cpp file.
  If a suitable companion file can't be located or if ninja doesn't know about
  `filename`, then uses default source files in WebRTC for determining the
  commandline.

  Args:
    webrtc_root: (String) Path to src/.
    filename: (String) Absolute path to source file being edited.

  Returns:
    (List of Strings) The list of command line flags for this source file. Can
    be empty.
  """
    if not webrtc_root:
        return []

    # Generally, everyone benefits from including WebRTC's src/, because all of
    # WebRTC's includes are relative to that.
    additional_flags = ['-I' + os.path.join(webrtc_root)]

    # Version of Clang used to compile WebRTC can be newer then version of
    # libclang that YCM uses for completion. So it's possible that YCM's
    # libclang doesn't know about some used warning options, which causes
    # compilation warnings (and errors, because of '-Werror');
    additional_flags.append('-Wno-unknown-warning-option')

    sys.path.append(os.path.join(webrtc_root, 'tools', 'vim'))
    from ninja_output import GetNinjaOutputDirectory
    out_dir = GetNinjaOutputDirectory(webrtc_root)

    basename, extension = os.path.splitext(filename)
    if extension == '.h':
        candidates = [basename + ext for ext in _HEADER_ALTERNATES]
    else:
        candidates = [filename]

    clang_line = None
    buildable_extension = extension
    for candidate in candidates:
        clang_line = GetClangCommandLineFromNinjaForSource(out_dir, candidate)
        if clang_line:
            buildable_extension = os.path.splitext(candidate)[1]
            break

    additional_flags += _EXTENSION_FLAGS.get(buildable_extension, [])

    if not clang_line:
        # If ninja didn't know about filename or it's companion files, then try
        # a default build target. It is possible that the file is new, or
        # build.ninja is stale.
        clang_line = GetClangCommandLineFromNinjaForSource(
            out_dir, GetDefaultSourceFile(webrtc_root, filename))

    if not clang_line:
        return additional_flags

    return GetClangOptionsFromCommandLine(clang_line, out_dir,
                                          additional_flags)
Exemplo n.º 4
0
def GetClangCommandFromNinjaForFilename(chrome_root, filename):
  """Returns the command line to build |filename|.

  Asks ninja how it would build the source file. If the specified file is a
  header, tries to find its companion source file first.

  Args:
    chrome_root: (String) Path to src/.
    filename: (String) Path to source file being edited.

  Returns:
    (List of Strings) Command line arguments for clang.
  """
  if not chrome_root:
    return []

  # Generally, everyone benefits from including Chromium's src/, because all of
  # Chromium's includes are relative to that.
  chrome_flags = ['-I' + os.path.join(chrome_root)]

  # Version of Clang used to compile Chromium can be newer then version of
  # libclang that YCM uses for completion. So it's possible that YCM's libclang
  # doesn't know about some used warning options, which causes compilation
  # warnings (and errors, because of '-Werror');
  chrome_flags.append('-Wno-unknown-warning-option')

  # Default file to get a reasonable approximation of the flags for a Blink
  # file.
  blink_root = os.path.join(chrome_root, 'third_party', 'WebKit')
  default_blink_file = os.path.join(blink_root, 'Source', 'core', 'Init.cpp')

  # Header files can't be built. Instead, try to match a header file to its
  # corresponding source file.
  if filename.endswith('.h'):
    # Add config.h to Blink headers, which won't have it by default.
    if filename.startswith(blink_root):
      chrome_flags.append('-include')
      chrome_flags.append(os.path.join(blink_root, 'Source', 'config.h'))

    alternates = ['.cc', '.cpp']
    for alt_extension in alternates:
      alt_name = filename[:-2] + alt_extension
      if os.path.exists(alt_name):
        filename = alt_name
        break
    else:
      if filename.startswith(blink_root):
        # If this is a Blink file, we can at least try to get a reasonable
        # approximation.
        filename = default_blink_file
      else:
        # If this is a standalone .h file with no source, the best we can do is
        # try to use the default flags.
        return chrome_flags

  sys.path.append(os.path.join(chrome_root, 'tools', 'vim'))
  from ninja_output import GetNinjaOutputDirectory
  out_dir = os.path.realpath(GetNinjaOutputDirectory(chrome_root))

  # Ninja needs the path to the source file relative to the output build
  # directory.
  rel_filename = os.path.relpath(os.path.realpath(filename), out_dir)

  # Ask ninja how it would build our source file.
  p = subprocess.Popen(['ninja', '-v', '-C', out_dir, '-t',
                        'commands', rel_filename + '^'],
                       stdout=subprocess.PIPE)
  stdout, stderr = p.communicate()
  if p.returncode:
    return chrome_flags

  # Ninja might execute several commands to build something. We want the last
  # clang command.
  clang_line = None
  for line in reversed(stdout.split('\n')):
    if 'clang' in line:
      clang_line = line
      break
  else:
    return chrome_flags

  # Parse flags that are important for YCM's purposes.
  clang_tokens = shlex.split(clang_line)
  for flag in clang_tokens:
    if flag.startswith('-I'):
      # Relative paths need to be resolved, because they're relative to the
      # output dir, not the source.
      if flag[2] == '/':
        chrome_flags.append(flag)
      else:
        abs_path = os.path.normpath(os.path.join(out_dir, flag[2:]))
        chrome_flags.append('-I' + abs_path)
    elif flag.startswith('-std'):
      chrome_flags.append(flag)
    elif flag.startswith('-') and flag[1] in 'DWFfmO':
      if flag == '-Wno-deprecated-register' or flag == '-Wno-header-guard':
        # These flags causes libclang (3.3) to crash. Remove it until things
        # are fixed.
        continue
      chrome_flags.append(flag)

  # Assume that the command for invoking clang++ looks like one of the
  # following:
  #   1) /path/to/clang/clang++ arguments
  #   2) /some/wrapper /path/to/clang++ arguments
  #
  # We'll look for a token that looks like Clang command within the first two
  # tokens of the command line and treat it as the clang++ binary. Using the
  # command line upto the Clang-like token isn't always feasible since the
  # wrapper may not like the invocation used by SystemIncludeDirectoryFlags()
  # although the real clang++ binary does.
  for command in clang_tokens[0:2]:
    if LooksLikeClangCommand(command):
      chrome_flags += SystemIncludeDirectoryFlags(command, chrome_flags)
      break

  return chrome_flags