Module: ExtconfCompileCommandsJson

Defined in:
lib/extconf_compile_commands_json.rb

Class Method Summary collapse

Class Method Details

.generate!Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/extconf_compile_commands_json.rb', line 9

def self.generate!
  # Start by expanding what's in our magic variables
  mkmf_cflags = [$INCFLAGS, $CPPFLAGS, $CFLAGS, $COUTFLAGS].map { |flag|
    # expand that with the contents of the ruby options
    (flag || "")
      .gsub("$(arch_hdrdir)", $arch_hdrdir || "")
      .gsub("$(hdrdir)", $hdrdir || "")
      .gsub("$(srcdir)", $srcdir || "")
      .gsub("$(cppflags)", RbConfig::CONFIG["cppflags"] || "")
      .gsub("$(DEFS)", RbConfig::CONFIG["DEFS"] || "")
      .gsub("$(cflags)", RbConfig::CONFIG["cflags"] || "")
      .gsub("$(cxxflags)", RbConfig::CONFIG["cxxflags"] || "")
      .gsub("$(optflags)", RbConfig::CONFIG["optflags"] || "")
      .gsub("$(debugflags)", RbConfig::CONFIG["debugflags"] || "")
      .gsub("$(warnflags)", RbConfig::CONFIG["warnflags"] || "")
      .gsub("$(empty)", "")
  }.flat_map { |flags|
    # Need to shellwords expand them (_after_ doing the $() subst's)
    Shellwords.split(flags)
  }.reject { |flag|
    flag.empty?
  }
  # This makes sure that #include "extconf.h" works
  mkmf_cflags = ["-iquote#{File.realpath(Dir.pwd)}"] + mkmf_cflags
  compile_commands = $srcs.map do |src|
    {
      directory: File.realpath(Dir.pwd),
      # Set the C compiler to "clang", always, since the whole point
      # of this file is to make clangd work.
      arguments: ["clang"] + mkmf_cflags + [src],
      file: src
    }
  end
  File.write("compile_commands.json", compile_commands.to_json)
end

.symlink!Object

generate will put the compile_commands.json in the same folder as the compiled output (and Makefile); symlink will create a symlink in the same folder as the extconf.rb, so that clangd can find it.



48
49
50
51
52
53
54
55
56
# File 'lib/extconf_compile_commands_json.rb', line 48

def self.symlink!
  # This is the same check mkmf does for deciding whether to spew errors onto your
  # terminal, so I figure it'll do for spewing symlinks into your directory too.
  return unless !$extmk && (/\A(extconf|makefile).rb\z/ =~ File.basename($0))
  extconf_dir = File.dirname $0
  compile_commands_file = File.realpath("./compile_commands.json")
  return unless File.exist? compile_commands_file
  FileUtils.ln_sf compile_commands_file, File.join(extconf_dir, "compile_commands.json")
end