Skip to content

Commit

Permalink
Fix compilation of Apache module on macOS 10.13 High Sierra
Browse files Browse the repository at this point in the history
apxs2 is gone so the code now takes this into account. Various places have
been updated to not require the presence of apxs2. We also fallback to
using hardcoded header include paths.
  • Loading branch information
FooBarWidget committed Sep 28, 2017
1 parent f61c24c commit 4168945
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 104 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Release 5.1.9 (Not yet released)
--------------------------------

* [Apache] Fixes a race condition (segfault) on startup, which primarily affected macOS hosts (regression in 5.1.8 due to the logging improvements). Closes GH-1973.
* [Apache] Fixes compilation on macOS 10.13 High Sierra.
* [Nginx] It is now allowed to specify `passenger_enabled` in the `http` context as well.
* [Nginx] Namespaced Jsoncpp under the Passenger namespace to avoid collisions with Google Pagespeed's copy when linked into Nginx.
* Adds support for Bundler 2.0's new `gems.rb` and `gems.locked`. Learn more about these in [Gemfile's new clothes](https://depfu.com/blog/2017/09/06/gemfiles-new-clothes). Closes GH-1982.
Expand Down
20 changes: 10 additions & 10 deletions bin/passenger-install-apache2-module
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ PhusionPassenger.require_passenger_lib 'constants'
PhusionPassenger.require_passenger_lib 'platform_info/ruby'
PhusionPassenger.require_passenger_lib 'platform_info/operating_system'
PhusionPassenger.require_passenger_lib 'platform_info/linux'
PhusionPassenger.require_passenger_lib 'platform_info/macos'
PhusionPassenger.require_passenger_lib 'platform_info/apache'
PhusionPassenger.require_passenger_lib 'platform_info/apache_detector'
PhusionPassenger.require_passenger_lib 'abstract_installer'
Expand Down Expand Up @@ -79,7 +78,6 @@ class Installer < PhusionPassenger::AbstractInstaller
'libcurl-dev',
'zlib-dev',
'apache2',
'apache2-dev',
'rake',
'ruby-openssl',
'rubygems'
Expand All @@ -94,25 +92,25 @@ class Installer < PhusionPassenger::AbstractInstaller
if PlatformInfo.os_name_simple != 'macosx'
ids << 'openssl-dev'
end
if PlatformInfo.apxs2_needed_for_building_apache_modules?
ids << 'apache2-dev'
end
# Some broken servers don't have apr-config or apu-config installed.
# Nevertheless, it is possible to compile Apache modules if Apache
# was configured with --included-apr. So here we check whether
# apr-config and apu-config are available. If they're not available,
# then we only register them as required dependency if no Apache
# module can be compiled without their presence.
if needs_apr_and_apu
if needs_apr_and_apu?
ids << 'apr-dev'
ids << 'apu-dev'
end
return [specs, ids]
end

def needs_apr_and_apu
((PlatformInfo.apr_config && PlatformInfo.apu_config) ||
PlatformInfo.apr_config_needed_for_building_apache_modules?) &&
(PlatformInfo.apxs2 == '/usr/sbin/apxs' &&
(PlatformInfo.os_name_simple != "macosx" ||
PlatformInfo.macos_version < 12))
def needs_apr_and_apu?
(PlatformInfo.apr_config && PlatformInfo.apu_config) ||
PlatformInfo.apr_config_needed_for_building_apache_modules?
end

def install_doc_url
Expand Down Expand Up @@ -263,8 +261,10 @@ private
:other_installs => other_installs
puts
if interactive?
# @apache.apxs2 can be nil, which on macOS >= 10.13 High Sierra
# means that we're using the OS-provided Apache installation.
result = prompt_confirmation "Are you sure you want to install " +
"against Apache #{@apache2.version} (#{@apache2.apxs2})?"
"against Apache #{@apache2.version} (#{@apache2.apxs2 || 'OS-provided install'})?"
if !result
puts
line
Expand Down
3 changes: 1 addition & 2 deletions build/apache2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,14 @@
only(:base, :base64, 'AppTypes.o').
set_namespace("apache2").
set_output_dir(APACHE2_OUTPUT_DIR + "module_libpassenger_common").
define_tasks(lambda { PlatformInfo.apache2_module_cflags }).
define_tasks(lambda { PlatformInfo.apache2_module_cxxflags }).
link_objects
dependencies = [
APACHE2_MODULE_COMMON_LIBRARIES,
APACHE2_MODULE_BOOST_OXT_LIBRARY,
APACHE2_OBJECTS.keys
].flatten
file(APACHE2_TARGET => dependencies) do
PlatformInfo.apxs2.nil? and raise "Could not find 'apxs' or 'apxs2'."
PlatformInfo.apache2ctl.nil? and raise "Could not find 'apachectl' or 'apache2ctl'."
PlatformInfo.httpd.nil? and raise "Could not find the Apache web server binary."

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ You are about to install <%= PhusionPassenger::PROGRAM_NAME %> against the follo
Apache installation:

<b>Apache <%= @current.version %></b>
apxs2 : <%= @current.apxs2 %>
apxs2 : <%= @current.apxs2 || 'N/A (OS-provided install)' %>
Executable: <%= @current.httpd %>

However, <%= @other_installs.size %> other Apache installation(s) have been found on your system:
<% @other_installs.each do |result| %>
* Apache <%= result.version %>
apxs2 : <%= result.apxs2 %>
apxs2 : <%= result.apxs2 || 'N/A (OS-provided install)' %>
Executable: <%= result.httpd %>
<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,12 @@ def check_apache2_installed
checking "whether Apache is installed"

if PlatformInfo.httpd
if PlatformInfo.apxs2
# macOS >= 10.13 High Sierra no longer includes apxs2, but that's
# okay because we know Apache is installed
if PlatformInfo.apxs2 ||
(PlatformInfo.os_name_simple == 'macosx' &&
PlatformInfo.os_version >= '10.13' &&
PlatformInfo.httpd == '/usr/sbin/httpd')
check_ok
true
else
Expand Down Expand Up @@ -567,7 +572,7 @@ def check_apache2_load_module_config
for Apache is not installed or not active. Please run the
#{PROGRAM_NAME} Apache module installer:
#{ruby_command} #{installer_command} --apxs2=#{PlatformInfo.apxs2}
#{ruby_command} #{installer_command} --apxs2=#{PlatformInfo.apxs2 || 'none'}
}
end
else
Expand Down
121 changes: 101 additions & 20 deletions src/ruby_supportlib/phusion_passenger/platform_info/apache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,17 @@ module PlatformInfo
# The absolute path to the 'apxs' or 'apxs2' executable, or nil if not found.
def self.apxs2
if env_defined?("APXS2")
return ENV["APXS2"]
if ENV['APXS2'] == 'none'
# This is a special value indicating that we should pretend as if
# apxs2 is not found. It is applicable when the user is running
# macOS >= 10.13 High Sierra, where apxs2 is not included in the OS.
# When the user runs 'passenger-config about detect-apache2',
# that command will tell the way to install against this specific
# Apache is to run passenger-install-apache2-module --apxs2-path='none'
return nil
else
return ENV["APXS2"]
end
end
['apxs2', 'apxs'].each do |name|
command = find_command(name)
Expand All @@ -70,7 +80,7 @@ def self.apache2ctl(options = {})
# The absolute path to the Apache binary (that is, 'httpd', 'httpd2', 'apache'
# or 'apache2'), or nil if not found.
def self.httpd(options = {})
apxs2 = options[:apxs2] || self.apxs2
apxs2 = options.fetch(:apxs2, self.apxs2)
if env_defined?('HTTPD')
return ENV['HTTPD']
elsif apxs2.nil?
Expand Down Expand Up @@ -401,36 +411,42 @@ def self.httpd_mods_enabled_directory(options = nil)

# The absolute path to the 'a2enmod' executable.
def self.a2enmod(options = {})
apxs2 = options[:apxs2] || self.apxs2
dir = File.dirname(apxs2)
apxs2 = options.fetch(:apxs2, self.apxs2)
dir = File.dirname(apxs2) if apxs2
# a2enmod is supposed to be a Debian extension that only works
# on the APT-installed Apache, so only return non-nil if we're
# working against the APT-installed Apache.
if dir == "/usr/bin" || dir == "/usr/sbin"
if env_defined?('A2ENMOD')
log "Using $A2ENMOD (= #{ENV['A2ENMOD']})"
return ENV['A2ENMOD']
else
return find_apache2_executable("a2enmod", options)
end
else
return nil
log "Not applicable"
nil
end
end
memoize :a2enmod

# The absolute path to the 'a2enmod' executable.
def self.a2dismod(options = {})
apxs2 = options[:apxs2] || self.apxs2
dir = File.dirname(apxs2)
apxs2 = options.fetch(:apxs2, self.apxs2)
dir = File.dirname(apxs2) if apxs2
# a2dismod is supposed to be a Debian extension that only works
# on the APT-installed Apache, so only return non-nil if we're
# working against the APT-installed Apache.
if dir == "/usr/bin" || dir == "/usr/sbin"
if env_defined?('A2DISMOD')
log "Using $A2DISMOD (= #{ENV['A2DISMOD']})"
return ENV['A2DISMOD']
else
return find_apache2_executable("a2dismod", options)
end
else
log "Not applicable"
nil
end
end
memoize :a2dismod
Expand Down Expand Up @@ -527,9 +543,16 @@ def self.find_apache2_executable(*possible_names)

# The absolute path to the Apache 2 'bin' directory, or nil if unknown.
def self.apache2_bindir(options = {})
apxs2 = options[:apxs2] || self.apxs2
apxs2 = options.fetch(:apxs2, self.apxs2)
if apxs2.nil?
return nil
# macOS >= 10.13 High Sierra no longer ships apxs2, so we'll use
# a hardcoded default.
if os_name_simple == 'macosx' && os_version >= '10.13' \
&& httpd(:apxs2 => apxs2) == '/usr/sbin/httpd'
'/usr/bin'
else
nil
end
else
return `#{apxs2} -q BINDIR 2>/dev/null`.strip
end
Expand All @@ -538,9 +561,16 @@ def self.apache2_bindir(options = {})

# The absolute path to the Apache 2 'sbin' directory, or nil if unknown.
def self.apache2_sbindir(options = {})
apxs2 = options[:apxs2] || self.apxs2
apxs2 = options.fetch(:apxs2, self.apxs2)
if apxs2.nil?
return nil
# macOS >= 10.13 High Sierra no longer ships apxs2, so we'll use
# a hardcoded default.
if os_name_simple == 'macosx' && os_version >= '10.13' \
&& httpd(:apxs2 => apxs2) == '/usr/sbin/httpd'
'/usr/sbin'
else
nil
end
else
return `#{apxs2} -q SBINDIR`.strip
end
Expand Down Expand Up @@ -578,7 +608,14 @@ def self.apache2_module_c_or_cxxflags(language, with_apr_flags = true)
flags << apu_cxxflags
end
end
if !apxs2.nil?
if apxs2.nil?
# macOS >= 10.13 High Sierra no longer includes apxs2
# so we'll use hardcoded paths here.
if os_name_simple == 'macosx' && os_version >= '10.13' && httpd == '/usr/sbin/httpd'
xcode_prefix = `/usr/bin/xcode-select -p`.strip
flags << "-I#{xcode_prefix}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/apache2"
end
else
apxs2_flags = `#{apxs2} -q CFLAGS`.strip << " -I" << `#{apxs2} -q INCLUDEDIR`.strip
apxs2_flags.gsub!(/-O\d? /, '')

Expand Down Expand Up @@ -613,6 +650,12 @@ def self.apache2_module_c_or_cxxflags(language, with_apr_flags = true)
# https://github.com/phusion/passenger/issues/1756
apxs2_flags.gsub!('-pie', '')

# macOS >= 10.12 Sierra no longer includes apr-config
# so we'll use a hardcoded path here.
if os_name_simple == 'macosx' && os_version >= '10.12' && httpd == '/usr/sbin/httpd'
apxs2_flags << ' -I/usr/include/apr-1'
end

apxs2_flags.strip!
flags << apxs2_flags
end
Expand Down Expand Up @@ -728,24 +771,54 @@ def self.apu_cxx_ldflags

################ Miscellaneous information ################

# Returns whether it is necessary to use information outputted by 'apxs2'
# in order to compile an Apache module.
#
# Since macOS 10.13 High Sierra apxs2 is no longer included in the
# operating system, so we return false in that case. We'll fallback
# to hardcoded paths.
def self.apxs2_needed_for_building_apache_modules?
!(os_name_simple == 'macosx' &&
os_version >= '10.13' &&
httpd == '/usr/sbin/httpd')
end

# Returns whether it is necessary to use information outputted by
# 'apr-config' and 'apu-config' in order to compile an Apache module.
#
# When Apache is installed with --with-included-apr, the APR/APU
# headers are placed into the same directory as the Apache headers,
# and so 'apr-config' and 'apu-config' won't be necessary in that case.
#
# Also, since macOS 10.12 Sierra apr-config is no longer included
# in the operating system, so we also return false in that case.
# We'll fallback to hardcoded paths.
def self.apr_config_needed_for_building_apache_modules?
return !try_compile("whether APR is needed for building Apache modules",
:c, "#include <apr.h>\n", apache2_module_cflags(false))
!(
os_name_simple == 'macosx' &&
os_version >= '10.13' &&
httpd == '/usr/sbin/httpd'
) &&
!try_compile("whether APR is needed for building Apache modules",
:c, "#include <apr.h>\n", apache2_module_cflags(false))
end
memoize :apr_config_needed_for_building_apache_modules?, true

private
def self.determine_apr_info(language)
if apr_config.nil?
if os_name_simple == 'macosx' && apxs2 == '/usr/sbin/apxs'
# macOS 10.12 Sierra does not supply apr-config, so
if os_name_simple == 'macosx' && httpd == '/usr/sbin/httpd'
# macOS >= 10.12 Sierra does not supply apr-config, so
# we use hardcoded defaults.
['-I/usr/include/apr-1', '-lapr-1']
if os_version >= '10.13'
# On macOS >= 10.13 High Sierra /usr/include no longer
# exists.
xcode_prefix = `/usr/bin/xcode-select -p`.strip
["-I#{xcode_prefix}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/apr-1",
'-lapr-1']
else
['-I/usr/include/apr-1', '-lapr-1']
end
else
[nil, nil]
end
Expand Down Expand Up @@ -783,10 +856,18 @@ def self.determine_apr_cxx_info

def self.determine_apu_info(language)
if apu_config.nil?
if os_name_simple == 'macosx' && apxs2 == '/usr/sbin/apxs'
# macOS 10.12 Sierra does not supply apu-config, so
if os_name_simple == 'macosx' && httpd == '/usr/sbin/httpd'
# macOS >= 10.12 Sierra does not supply apu-config, so
# we use hardcoded defaults.
['-I/usr/include/apr-1', '-laprutil-1']
if os_version >= '10.13'
# On macOS >= 10.13 High Sierra /usr/include no longer
# exists.
xcode_prefix = `/usr/bin/xcode-select -p`.strip
["-I#{xcode_prefix}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/apr-1",
'-laprutil-1']
else
['-I/usr/include/apr-1', '-laprutil-1']
end
else
[nil, nil]
end
Expand Down
Loading

1 comment on commit 4168945

@jithinraj
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.

Please sign in to comment.