Skip to content

Commit

Permalink
Merge pull request #13328 from chrisroberts/windows-ext
Browse files Browse the repository at this point in the history
Patch MakeMakefile for extension builds
  • Loading branch information
chrisroberts authored Jan 13, 2024
2 parents b3c9f0d + 886aab2 commit 8809fb6
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/vagrant.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

require "log4r"

# Add patches to log4r to support trace level
require "vagrant/patches/log4r"
require "vagrant/patches/net-ssh"
require "vagrant/patches/rubygems"

# Set our log levels and include trace
require 'log4r/configurator'
Log4r::Configurator.custom_levels(*(["TRACE"] + Log4r::Log4rConfig::LogLevels))
Expand Down
116 changes: 116 additions & 0 deletions lib/vagrant/patches/builder/mkmf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

# This custom mkmf.rb file is used on Windows platforms
# to handle common path related build failures where
# a space is included in the path. The default installation
# location being in Program Files results in most many
# extensions failing to build. These patches will attempt
# to find unquoted paths in flags and quote them prior to
# usage.

# Start with locating the real mkmf.rb file and
# loading it
mkmf_paths = $LOAD_PATH.find_all { |x|
!x.start_with?(__dir__) &&
File.exist?(File.join(x, "mkmf.rb"))
}.uniq

# At this point the path collection should only consist
# of a single entry. If there's more than one, load all
# of them but include a warning message that more than
# one was encountered. If none are found, then something
# bad is going on so just bail.
if mkmf_paths.size > 1
$stderr.puts "WARNING: Multiple mkmf.rb files located: #{mkmf_paths.inspect}"
elsif mkmf_paths.empty?
raise "Failed to locate mkmf.rb file"
end

mkmf_paths.each do |mpath|
require File.join(mpath, "mkmf.rb")
end

# Attempt to detect and quote Windos paths found within
# the given string of flags
#
# @param [String] flags Compiler/linker flags
# @return [String] flags with paths quoted
def flag_cleaner(flags)
parts = flags.split(" -")
parts.map! do |p|
if p !~ %r{[A-Za-z]:(/|\\)}
next p
elsif p =~ %r{"[A-Za-z]:(/|\\).+"$}
next p
end

p.gsub(%r{([A-Za-z]:(/|\\).+)$}, '"\1"')
end

parts.join(" -")
end

# Check values defined for CFLAGS, CPPFLAGS, LDFLAGS,
# and INCFLAGS for unquoted Windows paths and quote
# them.
def clean_flags!
$CFLAGS = flag_cleaner($CFLAGS)
$CPPFLAGS = flag_cleaner($CPPFLAGS)
$LDFLAGS = flag_cleaner($LDFLAGS)
$INCFLAGS = flag_cleaner($INCFLAGS)
end

# Since mkmf loads the MakeMakefile module directly into the
# current scope, apply patches directly in the scope
def vagrant_create_makefile(*args)
clean_flags!

ruby_create_makefile(*args)
end
alias :ruby_create_makefile :create_makefile
alias :create_makefile :vagrant_create_makefile

def vagrant_append_cflags(*args)
result = ruby_append_cflags(*args)
clean_flags!
result
end
alias :ruby_append_cflags :append_cflags
alias :append_cflags :vagrant_append_cflags

def vagrant_append_cppflags(*args)
result = ruby_append_cppflags(*args)
clean_flags!
result
end
alias :ruby_append_cppflags :append_cppflags
alias :append_cppflags :vagrant_append_cppflags

def vagrant_append_ldflags(*args)
result = ruby_append_ldflags(*args)
clean_flags!
result
end
alias :ruby_append_ldflags :append_ldflags
alias :append_ldflags :vagrant_append_ldflags

def vagrant_cc_config(*args)
clean_flags!
ruby_cc_config(*args)
end
alias :ruby_cc_config :cc_config
alias :cc_config :vagrant_cc_config

def vagrant_link_config(*args)
clean_flags!
ruby_link_config(*args)
end
alias :ruby_link_config :link_config
alias :link_config :vagrant_link_config

# Finally, always append the flags that Vagrant has
# defined via the environment
append_cflags(ENV["CFLAGS"]) if ENV["CFLAGS"]
append_cppflags(ENV["CPPFLAGS"]) if ENV["CPPFLAGS"]
append_ldflags(ENV["LDFLAGS"]) if ENV["LDFLAGS"]
23 changes: 23 additions & 0 deletions lib/vagrant/patches/rubygems.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

# This allows for effective monkey patching of the MakeMakefile
# module when building gem extensions. When gem extensions are
# built, the extconf.rb file is executed as a separate process.
# To support monkey patching the MakeMakefile module, the ruby
# executable path is adjusted to add a custom load path allowing
# a customized mkmf.rb file to load the proper mkmf.rb file, and
# then applying the proper patches.
if Gem.win_platform?
Gem.class_eval do
class << self
def vagrant_ruby
cmd = ruby_ruby
"#{cmd} -I\"#{Vagrant.source_root.join("lib/vagrant/patches/builder")}\""
end

alias_method :ruby_ruby, :ruby
alias_method :ruby, :vagrant_ruby
end
end
end

0 comments on commit 8809fb6

Please sign in to comment.