diff --git a/Rakefile b/Rakefile
index 5977d0adec..3bb549d4f0 100644
--- a/Rakefile
+++ b/Rakefile
@@ -88,9 +88,18 @@ parsed_files = PARSER_FILES.map do |parser_file|
 end
 
 task "#{path}.gem" => package_parser_files
-desc "Generate all files used racc and kpeg"
+
+desc "Generate all files use racc and kpeg"
 task :generate => parsed_files
 
+unless ENV.key?('BUNDLE_GEMFILE')
+  task :gem_install do
+    Gem.install 'racc', '> 1.4.10'
+    Gem.install 'kpeg', '>= 1.3.3'
+  end
+  file parsed_files => :gem_install
+end
+
 task :clean do
   parsed_files.each do |path|
     File.delete(path) if File.exist?(path)
diff --git a/ext/rdoc/extconf.rb b/ext/rdoc/extconf.rb
new file mode 100644
index 0000000000..59ffc976c5
--- /dev/null
+++ b/ext/rdoc/extconf.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+# Generate all parse files using racc and kpeg. This is not necessary for regular gem installation, but it is when
+# installing RDoc from the git source. Without this, the generated parse files would not exist and RDoc would not work
+Dir.chdir(File.expand_path("../..", __dir__)) do
+  if !File.exist?("lib/rdoc/markdown.rb") && Dir.exist?(".git")
+    system("rake generate", exception: true)
+  end
+end
+
+# RDoc doesn't actually have a native extension, but a Makefile needs to exist in order to successfully install the gem
+require "mkmf"
+create_makefile("rdoc/rdoc")
diff --git a/rdoc.gemspec b/rdoc.gemspec
index 3144df52d6..f9d8668f83 100644
--- a/rdoc.gemspec
+++ b/rdoc.gemspec
@@ -35,6 +35,7 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
   s.bindir = "exe"
   s.executables = ["rdoc", "ri"]
   s.require_paths = ["lib"]
+  s.extensions = ["ext/rdoc/extconf.rb"]
   # for ruby core repository. It was generated by
   # `git ls-files -z`.split("\x0").each {|f| puts "    #{f.dump}," unless f.start_with?(*%W[test/ spec/ features/ .]) }
   non_lib_files = [