Created
November 14, 2022 21:59
-
-
Save ryukoposting/24cba4eda0f691dad9daa2b392ef1ba4 to your computer and use it in GitHub Desktop.
Automatically generate c_cpp_properties.json from Makefile with a 99-line Ruby script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CC:=gcc | |
CFLAGS:=\ | |
-I./include\ | |
-DFOO\ | |
-DBAR\ | |
-std=c11 | |
.vscode/c_cpp_properties.json: Makefile | |
ruby vscode_cprops_gen.rb .vscode $(CC) $(CFLAGS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Automatically generate VSCode intellisense settings from your makefile. | |
# | |
# Usage: ruby vscode_cprops_gen.rb (output_dir) (compiler) (cflags...) | |
# | |
# Makefile sample: | |
# .vscode/c_cpp_properties.json: Makefile | |
# @ruby vscode_cprops_gen.rb .vscode $(CC) $(CFLAGS) | |
require 'pathname' | |
require 'json' | |
CONFIG_NAME = "Project" # name of the output c/c++ configuration | |
GENERATE_FLYLINT = true # whether to copy the config into flylint's config | |
def which(cmd) | |
# Thanks stackoverflow: https://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby | |
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] | |
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| | |
exts.each do |ext| | |
exe = File.join(path, "#{cmd}#{ext}") | |
return exe if File.executable?(exe) && !File.directory?(exe) | |
end | |
end | |
nil | |
end | |
outdir = Pathname.new(ARGV[0]).cleanpath | |
compiler_path = Pathname.new(which(ARGV[1])).cleanpath | |
wd = Pathname.new(Dir.getwd) | |
workspace_dir = wd.join(outdir).join("..").cleanpath | |
c_cpp_properties_json = outdir.join "c_cpp_properties.json" | |
settings_json = outdir.join "settings.json" | |
include_paths = [] | |
defines = [] | |
c_std = nil | |
cpp_std = nil | |
ARGV[2..].each do |arg| | |
if arg =~ /^-I/ | |
ipath = Pathname.new(arg[2..]).cleanpath | |
relpath = wd.join(ipath).relative_path_from(workspace_dir) | |
include_paths.push "${workspaceFolder}/#{relpath}" | |
elsif arg =~ /^-D/ | |
defines.push arg[2..] | |
elsif arg =~ /^-std=/ | |
if arg.include? "++" | |
cpp_std = arg[5..] | |
else | |
c_std = arg[5..] | |
end | |
end | |
end | |
unless File.exists? c_cpp_properties_json | |
default_json = { | |
version: 4, | |
configurations: [] | |
} | |
File.write c_cpp_properties_json, JSON.pretty_generate(default_json) | |
end | |
properties = { | |
'name' => CONFIG_NAME, | |
'includePath' => include_paths, | |
'defines' => defines, | |
'compilerPath' => compiler_path, | |
} | |
properties['cStandard'] = c_std if c_std | |
properties['cppStandard'] = cpp_std if cpp_std | |
json = JSON.parse File.read(c_cpp_properties_json) | |
did_update = json['configurations'].any? do |cfg| | |
if cfg['name'] == CONFIG_NAME | |
cfg.merge! properties | |
end | |
end | |
unless did_update | |
json['configurations'].push properties | |
end | |
File.write c_cpp_properties_json, JSON.pretty_generate(json) | |
if GENERATE_FLYLINT | |
unless File.exists? settings_json | |
File.write settings_json, JSON.pretty_generate({}) | |
end | |
json = JSON.parse File.read(settings_json) | |
json["c-cpp-flylint.includePaths"] = include_paths | |
json["c-cpp-flylint.defines"] = defines | |
json["c-cpp-flylint.standard"] = [c_std, cpp_std].filter { |s| !s.nil? } | |
File.write settings_json, JSON.pretty_generate(json) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment