passenger 5.0.0.beta3 → 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +11 -5
  5. data/CHANGELOG +38 -0
  6. data/CONTRIBUTING.md +1 -4
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +0 -2
  9. data/Rakefile +33 -33
  10. data/bin/passenger +1 -1
  11. data/bin/passenger-config +1 -1
  12. data/bin/passenger-install-apache2-module +800 -800
  13. data/bin/passenger-install-nginx-module +592 -592
  14. data/bin/passenger-memory-stats +127 -127
  15. data/bin/passenger-status +216 -216
  16. data/build/agents.rb +127 -127
  17. data/build/apache2.rb +87 -87
  18. data/build/basics.rb +60 -60
  19. data/build/common_library.rb +165 -165
  20. data/build/cplusplus_support.rb +51 -51
  21. data/build/cxx_tests.rb +268 -268
  22. data/build/debian.rb +143 -143
  23. data/build/documentation.rb +58 -58
  24. data/build/integration_tests.rb +81 -81
  25. data/build/misc.rb +132 -132
  26. data/build/nginx.rb +20 -20
  27. data/build/node_tests.rb +7 -7
  28. data/build/oxt_tests.rb +14 -14
  29. data/build/packaging.rb +570 -570
  30. data/build/preprocessor.rb +260 -260
  31. data/build/rake_extensions.rb +71 -71
  32. data/build/ruby_extension.rb +29 -29
  33. data/build/ruby_tests.rb +6 -6
  34. data/build/test_basics.rb +37 -37
  35. data/debian.template/control.template +3 -5
  36. data/dev/copy_boost_headers +134 -134
  37. data/dev/install_scripts_bootstrap_code.rb +25 -25
  38. data/dev/list_tests +20 -20
  39. data/dev/ruby_server.rb +223 -223
  40. data/dev/runner +18 -18
  41. data/doc/ServerOptimizationGuide.txt.md +55 -2
  42. data/doc/Users guide Nginx.txt +0 -26
  43. data/doc/Users guide Standalone.txt +5 -1
  44. data/doc/users_guide_snippets/tips.txt +9 -0
  45. data/ext/common/ApplicationPool2/Group.h +23 -11
  46. data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
  47. data/ext/common/ApplicationPool2/Pool.h +22 -17
  48. data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
  49. data/ext/common/ApplicationPool2/Spawner.h +1 -1
  50. data/ext/common/Constants.h +1 -1
  51. data/ext/common/agents/Base.cpp +35 -20
  52. data/ext/common/agents/HelperAgent/Main.cpp +8 -1
  53. data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
  54. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
  55. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
  56. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
  57. data/ext/common/agents/Main.cpp +1 -1
  58. data/ext/common/agents/Watchdog/Main.cpp +54 -19
  59. data/ext/nginx/Configuration.c +7 -0
  60. data/ext/nginx/ContentHandler.c +9 -1
  61. data/helper-scripts/backtrace-sanitizer.rb +106 -87
  62. data/helper-scripts/crash-watch.rb +32 -0
  63. data/helper-scripts/download_binaries/extconf.rb +38 -38
  64. data/helper-scripts/meteor-loader.rb +107 -107
  65. data/helper-scripts/prespawn +101 -101
  66. data/helper-scripts/rack-loader.rb +96 -96
  67. data/helper-scripts/rack-preloader.rb +137 -137
  68. data/lib/phusion_passenger.rb +292 -292
  69. data/lib/phusion_passenger/abstract_installer.rb +438 -438
  70. data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
  71. data/lib/phusion_passenger/admin_tools.rb +20 -20
  72. data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
  73. data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
  74. data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
  75. data/lib/phusion_passenger/apache2/config_options.rb +182 -182
  76. data/lib/phusion_passenger/common_library.rb +479 -485
  77. data/lib/phusion_passenger/config/about_command.rb +161 -161
  78. data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
  79. data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
  80. data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
  81. data/lib/phusion_passenger/config/command.rb +25 -25
  82. data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
  83. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
  84. data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
  85. data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
  86. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
  87. data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
  88. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
  89. data/lib/phusion_passenger/config/installation_utils.rb +204 -204
  90. data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
  91. data/lib/phusion_passenger/config/main.rb +152 -152
  92. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
  93. data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
  94. data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
  95. data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
  96. data/lib/phusion_passenger/config/utils.rb +95 -95
  97. data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
  98. data/lib/phusion_passenger/console_text_template.rb +25 -25
  99. data/lib/phusion_passenger/constants.rb +90 -90
  100. data/lib/phusion_passenger/debug_logging.rb +106 -106
  101. data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
  102. data/lib/phusion_passenger/message_channel.rb +312 -312
  103. data/lib/phusion_passenger/message_client.rb +176 -176
  104. data/lib/phusion_passenger/native_support.rb +369 -369
  105. data/lib/phusion_passenger/nginx/config_options.rb +297 -297
  106. data/lib/phusion_passenger/packaging.rb +131 -131
  107. data/lib/phusion_passenger/platform_info.rb +360 -360
  108. data/lib/phusion_passenger/platform_info/apache.rb +767 -767
  109. data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
  110. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
  111. data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
  112. data/lib/phusion_passenger/platform_info/curl.rb +32 -32
  113. data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
  114. data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
  119. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
  120. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
  121. data/lib/phusion_passenger/platform_info/linux.rb +55 -55
  122. data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
  123. data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
  124. data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
  125. data/lib/phusion_passenger/plugin.rb +66 -66
  126. data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
  127. data/lib/phusion_passenger/public_api.rb +191 -191
  128. data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
  129. data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
  130. data/lib/phusion_passenger/request_handler.rb +567 -577
  131. data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
  132. data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
  133. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
  134. data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
  135. data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
  136. data/lib/phusion_passenger/standalone/command.rb +44 -40
  137. data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
  138. data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
  139. data/lib/phusion_passenger/standalone/main.rb +73 -73
  140. data/lib/phusion_passenger/standalone/start_command.rb +697 -685
  141. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
  142. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
  143. data/lib/phusion_passenger/standalone/status_command.rb +64 -64
  144. data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
  145. data/lib/phusion_passenger/standalone/version_command.rb +9 -9
  146. data/lib/phusion_passenger/union_station/connection.rb +32 -32
  147. data/lib/phusion_passenger/union_station/core.rb +251 -251
  148. data/lib/phusion_passenger/union_station/transaction.rb +126 -126
  149. data/lib/phusion_passenger/utils.rb +199 -167
  150. data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
  151. data/lib/phusion_passenger/utils/download.rb +196 -196
  152. data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
  153. data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
  154. data/lib/phusion_passenger/utils/lock.rb +31 -31
  155. data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
  156. data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
  157. data/lib/phusion_passenger/utils/shellwords.rb +20 -20
  158. data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
  159. data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
  160. data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
  161. data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
  162. data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
  163. data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
  164. data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
  165. data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
  166. data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
  167. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
  168. data/passenger.gemspec +0 -1
  169. data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
  170. data/resources/templates/standalone/config.erb +19 -15
  171. data/test/integration_tests/apache2_tests.rb +566 -566
  172. data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
  173. data/test/integration_tests/native_packaging_spec.rb +296 -296
  174. data/test/integration_tests/nginx_tests.rb +393 -393
  175. data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
  176. data/test/integration_tests/source_packaging_test.rb +138 -138
  177. data/test/integration_tests/spec_helper.rb +5 -5
  178. data/test/integration_tests/standalone_tests.rb +367 -367
  179. data/test/ruby/debug_logging_spec.rb +133 -133
  180. data/test/ruby/message_channel_spec.rb +186 -186
  181. data/test/ruby/rack/loader_spec.rb +28 -28
  182. data/test/ruby/rack/preloader_spec.rb +34 -34
  183. data/test/ruby/rails3.0/loader_spec.rb +12 -12
  184. data/test/ruby/rails3.0/preloader_spec.rb +18 -18
  185. data/test/ruby/rails3.1/loader_spec.rb +12 -12
  186. data/test/ruby/rails3.1/preloader_spec.rb +18 -18
  187. data/test/ruby/rails3.2/loader_spec.rb +12 -12
  188. data/test/ruby/rails3.2/preloader_spec.rb +18 -18
  189. data/test/ruby/rails4.0/loader_spec.rb +12 -12
  190. data/test/ruby/rails4.0/preloader_spec.rb +18 -18
  191. data/test/ruby/rails4.1/loader_spec.rb +12 -12
  192. data/test/ruby/rails4.1/preloader_spec.rb +18 -18
  193. data/test/ruby/request_handler_spec.rb +730 -730
  194. data/test/ruby/shared/loader_sharedspec.rb +224 -224
  195. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
  196. data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
  197. data/test/ruby/spec_helper.rb +65 -65
  198. data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
  199. data/test/ruby/union_station_spec.rb +276 -276
  200. data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
  201. data/test/ruby/utils/hosts_file_parser.rb +248 -248
  202. data/test/ruby/utils/tee_input_spec.rb +215 -215
  203. data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
  204. data/test/ruby/utils_spec.rb +21 -21
  205. data/test/stub/rack/config.ru +87 -87
  206. data/test/stub/rack/library.rb +8 -8
  207. data/test/stub/rack/start.rb +30 -30
  208. data/test/support/apache2_controller.rb +191 -191
  209. data/test/support/nginx_controller.rb +90 -99
  210. data/test/support/placebo-preloader.rb +57 -57
  211. data/test/support/test_helper.rb +435 -435
  212. metadata +11 -21
  213. metadata.gz.asc +7 -7
  214. data/lib/phusion_passenger/standalone/command2.rb +0 -292
  215. data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
  216. data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
  217. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
  218. data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -26,575 +26,575 @@ PhusionPassenger.require_passenger_lib 'platform_info/operating_system'
26
26
 
27
27
  module PhusionPassenger
28
28
 
29
- module PlatformInfo
30
- private
31
- def self.detect_language_extension(language)
32
- case language
33
- when :c
34
- return "c"
35
- when :cxx
36
- return "cpp"
37
- else
38
- raise ArgumentError, "Unsupported language #{language.inspect}"
39
- end
40
- end
41
- private_class_method :detect_language_extension
42
-
43
- def self.detect_compiler_type_name(language)
44
- case language
45
- when :c
46
- return "C"
47
- when :cxx
48
- return "C++"
49
- else
50
- raise ArgumentError, "Unsupported language #{language.inspect}"
51
- end
52
- end
53
- private_class_method :detect_compiler_type_name
54
-
55
- def self.create_compiler_command(language, flags1, flags2, link = false)
56
- case language
57
- when :c
58
- result = [cc, link ? ENV['EXTRA_PRE_LDFLAGS'] : nil,
59
- ENV['EXTRA_PRE_CFLAGS'], flags1, flags2, ENV['EXTRA_CFLAGS'],
60
- ENV['EXTRA_LDFLAGS']]
61
- when :cxx
62
- result = [cxx, link ? ENV['EXTRA_PRE_LDFLAGS'] : nil,
63
- ENV['EXTRA_PRE_CXXFLAGS'], flags1, flags2, ENV['EXTRA_CXXFLAGS'],
64
- ENV['EXTRA_LDFLAGS']]
65
- else
66
- raise ArgumentError, "Unsupported language #{language.inspect}"
67
- end
68
- return result.compact.join(" ").strip
69
- end
70
- private_class_method :create_compiler_command
71
-
72
- def self.run_compiler(description, command, source_file, source, capture_output = false)
73
- if verbose?
74
- message = "#{description}\n" <<
75
- "Running: #{command}\n"
76
- if source.strip.empty?
77
- message << "Source file is empty."
78
- else
79
- message << "Source file contains:\n" <<
80
- "-------------------------\n" <<
81
- unindent(source) <<
82
- "\n-------------------------"
83
- end
84
- log(message)
85
- end
86
- if capture_output
87
- begin
88
- output = `#{command} 2>&1`
89
- result = $?.exitstatus == 0
90
- rescue SystemCallError => e
91
- result = nil
92
- exec_error_reason = e.message
93
- end
94
- log("Output:\n" <<
95
- "-------------------------\n" <<
96
- output.to_s <<
97
- "\n-------------------------")
98
- elsif verbose?
99
- result = system(command)
100
- else
101
- result = system("(#{command}) >/dev/null 2>/dev/null")
102
- end
103
- if result.nil?
104
- log("Command could not be executed! #{exec_error_reason}".strip)
105
- return false
106
- elsif result
107
- log("Check suceeded")
108
- if capture_output
109
- return { :result => true, :output => output }
110
- else
111
- return true
112
- end
113
- else
114
- log("Check failed with exit status #{$?.exitstatus}")
115
- if capture_output == :always
116
- return { :result => false, :output => output }
117
- else
118
- return false
119
- end
120
- end
121
- end
122
- private_class_method :run_compiler
123
-
124
- def self.cc_or_cxx_supports_feliminate_unused_debug?(language)
125
- ext = detect_language_extension(language)
126
- compiler_type_name = detect_compiler_type_name(language)
127
- create_temp_file("passenger-compile-check.#{ext}") do |filename, f|
128
- f.close
129
- begin
130
- command = create_compiler_command(language,
131
- "-c '#{filename}' -o '#{filename}.o'",
132
- '-feliminate-unused-debug-symbols -feliminate-unused-debug-types')
133
- result = run_compiler("Checking for #{compiler_type_name} compiler '-feliminate-unused-debug-{symbols,types}' support",
134
- command, filename, '', true)
135
- return result && result[:output].empty?
136
- ensure
137
- File.unlink("#{filename}.o") rescue nil
138
- end
139
- end
140
- end
141
- private_class_method :cc_or_cxx_supports_feliminate_unused_debug?
142
-
143
- public
144
- def self.cc
145
- return string_env('CC', default_cc)
146
- end
147
- memoize :cc
148
-
149
- def self.cxx
150
- return string_env('CXX', default_cxx)
151
- end
152
- memoize :cxx
153
-
154
- def self.default_cc
155
- # On most platforms, we'll want to use the same compiler as what the rest
156
- # of the system uses, so that we generate compatible binaries. That's
157
- # most likely the 'cc' command. We used to use 'gcc' by default.
158
- #
159
- # See for example this issue with OS X Mavericks (10.9). They switched from
160
- # GCC to Clang as the default compiler. Since the Nginx by default uses 'cc'
161
- # as the compiler, we'll have to do that too. Otherwise we'll get C++ linker
162
- # errors because Nginx is compiled with Clang while Phusion Passenger is
163
- # compiled with GCC.
164
- # https://code.google.com/p/phusion-passenger/issues/detail?id=950
165
- if PlatformInfo.find_command('cc')
166
- return 'cc'
167
- else
168
- return 'gcc'
169
- end
170
- end
171
-
172
- def self.default_cxx
173
- if PlatformInfo.find_command('c++')
174
- return 'c++'
175
- else
176
- return 'g++'
177
- end
178
- end
179
-
180
- def self.cc_is_gcc?
181
- `#{cc} -v 2>&1` =~ /gcc version/
182
- end
183
- memoize :cc_is_gcc?
184
-
185
- def self.cxx_is_gcc?
186
- `#{cxx} -v 2>&1` =~ /gcc version/
187
- end
188
- memoize :cxx_is_gcc?
189
-
190
- def self.cc_is_clang?
191
- `#{cc} --version 2>&1` =~ /clang version/
192
- end
193
- memoize :cc_is_clang?
194
-
195
- def self.cxx_is_clang?
196
- `#{cxx} --version 2>&1` =~ /clang version/
197
- end
198
- memoize :cxx_is_clang?
199
-
200
- def self.cc_is_sun_studio?
201
- `#{cc} -V 2>&1` =~ /Sun C/ || `#{cc} -flags 2>&1` =~ /Sun C/
202
- end
203
- memoize :cc_is_sun_studio?
204
-
205
- def self.cxx_is_sun_studio?
206
- `#{cxx} -V 2>&1` =~ /Sun C/ || `#{cxx} -flags 2>&1` =~ /Sun C/
207
- end
208
- memoize :cxx_is_sun_studio?
209
-
210
-
211
- # Looks for the given C or C++ header. This works by invoking the compiler and
212
- # searching in the compiler's header search path. Returns its full filename,
213
- # or true if this function knows that the header exists but can't find it (e.g.
214
- # because the compiler cannot tell us what its header search path is).
215
- # Returns nil if the header cannot be found.
216
- def self.find_header(header_name, language, flags = nil)
217
- extension = detect_language_extension(language)
218
- create_temp_file("passenger-compile-check.#{extension}") do |filename, f|
219
- source = %Q{
220
- #include <#{header_name}>
221
- }
222
- f.puts(source)
223
- f.close
224
- begin
225
- command = create_compiler_command(language,
226
- "-v -c '#{filename}' -o '#{filename}.o'",
227
- flags)
228
- if result = run_compiler("Checking for #{header_name}", command, filename, source, true)
229
- result[:output] =~ /^#include <...> search starts here:$(.+?)^End of search list\.$/m
230
- search_paths = $1.to_s.strip.split("\n").map{ |line| line.strip }
231
- search_paths.each do |dir|
232
- if File.file?("#{dir}/#{header_name}")
233
- return "#{dir}/#{header_name}"
234
- end
235
- end
236
- return true
237
- else
238
- return nil
239
- end
240
- ensure
241
- File.unlink("#{filename}.o") rescue nil
242
- end
243
- end
244
- end
245
-
246
- def self.try_compile(description, language, source, flags = nil)
247
- extension = detect_language_extension(language)
248
- create_temp_file("passenger-compile-check.#{extension}") do |filename, f|
249
- f.puts(source)
250
- f.close
251
- command = create_compiler_command(language,
252
- "-c '#{filename}' -o '#{filename}.o'",
253
- flags)
254
- return run_compiler(description, command, filename, source)
255
- end
256
- end
257
-
258
- # Like try_compile, but designed for checking whether a warning flag is
259
- # supported. Compilers sometimes do not error out upon encountering an
260
- # unsupported warning flag, but merely print a warning. This method checks
261
- # for that too.
262
- def self.try_compile_with_warning_flag(description, language, source, flags = nil)
263
- extension = detect_language_extension(language)
264
- create_temp_file("passenger-compile-check.#{extension}") do |filename, f|
265
- f.puts(source)
266
- f.close
267
- command = create_compiler_command(language,
268
- "-c '#{filename}' -o '#{filename}.o'",
269
- flags)
270
- result = run_compiler(description, command, filename, source, true)
271
- return result && result[:result] && result[:output] !~ /unknown warning option/i
272
- end
273
- end
274
-
275
- def self.try_link(description, language, source, flags = nil)
276
- extension = detect_language_extension(language)
277
- create_temp_file("passenger-link-check.#{extension}") do |filename, f|
278
- f.puts(source)
279
- f.close
280
- command = create_compiler_command(language,
281
- "'#{filename}' -o '#{filename}.out'",
282
- flags, true)
283
- return run_compiler(description, command, filename, source)
284
- end
285
- end
286
-
287
- def self.try_compile_and_run(description, language, source, flags = nil)
288
- extension = detect_language_extension(language)
289
- create_temp_file("passenger-run-check.#{extension}", tmpexedir) do |filename, f|
290
- f.puts(source)
291
- f.close
292
- command = create_compiler_command(language,
293
- "'#{filename}' -o '#{filename}.out'",
294
- flags, true)
295
- if run_compiler(description, command, filename, source)
296
- log("Running #{filename}.out")
297
- begin
298
- output = `'#{filename}.out' 2>&1`
299
- rescue SystemCallError => e
300
- log("Command failed: #{e}")
301
- return false
302
- end
303
- status = $?.exitstatus
304
- log("Command exited with status #{status}. Output:\n--------------\n#{output}\n--------------")
305
- return status == 0
306
- else
307
- return false
308
- end
309
- end
310
- end
311
-
312
-
313
- # Checks whether the compiler supports "-arch #{arch}".
314
- def self.compiler_supports_architecture?(arch)
315
- return try_compile("Checking for C compiler '-arch' support",
316
- :c, '', "-arch #{arch}")
317
- end
318
-
319
- def self.cc_supports_visibility_flag?
320
- return false if os_name =~ /aix/
321
- return try_compile("Checking for C compiler '-fvisibility' support",
322
- :c, '', '-fvisibility=hidden')
323
- end
324
- memoize :cc_supports_visibility_flag?, true
325
-
326
- def self.cxx_supports_visibility_flag?
327
- return false if os_name =~ /aix/
328
- return try_compile("Checking for C++ compiler '-fvisibility' support",
329
- :cxx, '', '-fvisibility=hidden')
330
- end
331
- memoize :cxx_supports_visibility_flag?, true
332
-
333
- def self.cc_supports_wno_attributes_flag?
334
- return try_compile_with_warning_flag(
335
- "Checking for C compiler '-Wno-attributes' support",
336
- :c, '', '-Wno-attributes')
337
- end
338
- memoize :cc_supports_wno_attributes_flag?, true
339
-
340
- def self.cxx_supports_wno_attributes_flag?
341
- return try_compile_with_warning_flag(
342
- "Checking for C++ compiler '-Wno-attributes' support",
343
- :cxx, '', '-Wno-attributes')
344
- end
345
- memoize :cxx_supports_wno_attributes_flag?, true
346
-
347
- def self.cc_supports_wno_missing_field_initializers_flag?
348
- return try_compile_with_warning_flag(
349
- "Checking for C compiler '-Wno-missing-field-initializers' support",
350
- :c, '', '-Wno-missing-field-initializers')
351
- end
352
- memoize :cc_supports_wno_missing_field_initializers_flag?, true
353
-
354
- def self.cxx_supports_wno_missing_field_initializers_flag?
355
- return try_compile_with_warning_flag(
356
- "Checking for C++ compiler '-Wno-missing-field-initializers' support",
357
- :cxx, '', '-Wno-missing-field-initializers')
358
- end
359
- memoize :cxx_supports_wno_missing_field_initializers_flag?, true
360
-
361
- def self.cxx_supports_wno_unused_local_typedefs_flag?
362
- return try_compile_with_warning_flag(
363
- "Checking for C++ compiler '-Wno-unused-local-typedefs' support",
364
- :cxx, '', '-Wno-unused-local-typedefs')
365
- end
366
- memoize :cxx_supports_wno_unused_local_typedefs_flag?, true
367
-
368
- def self.cc_supports_no_tls_direct_seg_refs_option?
369
- return try_compile("Checking for C compiler '-mno-tls-direct-seg-refs' support",
370
- :c, '', '-mno-tls-direct-seg-refs')
371
- end
372
- memoize :cc_supports_no_tls_direct_seg_refs_option?, true
373
-
374
- def self.cxx_supports_no_tls_direct_seg_refs_option?
375
- return try_compile("Checking for C++ compiler '-mno-tls-direct-seg-refs' support",
376
- :cxx, '', '-mno-tls-direct-seg-refs')
377
- end
378
- memoize :cxx_supports_no_tls_direct_seg_refs_option?, true
379
-
380
- def self.compiler_supports_wno_ambiguous_member_template?
381
- result = try_compile_with_warning_flag(
382
- "Checking for C++ compiler '-Wno-ambiguous-member-template' support",
383
- :cxx, '', '-Wno-ambiguous-member-template')
384
- return false if !result
385
-
386
- # For some reason, GCC does not complain about -Wno-ambiguous-member-template
387
- # not being supported unless the source contains another error. So we
388
- # check for this.
389
- create_temp_file("passenger-compile-check.cpp") do |filename, f|
390
- source = %Q{
391
- void foo() {
392
- return error;
393
- }
394
- }
395
- f.puts(source)
396
- f.close
397
- begin
398
- command = create_compiler_command(:cxx,
399
- "-c '#{filename}' -o '#{filename}.o'",
400
- '-Wno-ambiguous-member-template')
401
- result = run_compiler("Checking whether C++ compiler '-Wno-ambiguous-member-template' support is *really* supported",
402
- command, filename, source, :always)
403
- ensure
404
- File.unlink("#{filename}.o") rescue nil
405
- end
406
- end
407
-
408
- return result && result[:output] !~ /-Wno-ambiguous-member-template/
409
- end
410
- memoize :compiler_supports_wno_ambiguous_member_template?, true
411
-
412
- def self.cc_supports_feliminate_unused_debug?
413
- return cc_or_cxx_supports_feliminate_unused_debug?(:c)
414
- end
415
- memoize :cc_supports_feliminate_unused_debug?, true
416
-
417
- def self.cxx_supports_feliminate_unused_debug?
418
- return cc_or_cxx_supports_feliminate_unused_debug?(:cxx)
419
- end
420
- memoize :cxx_supports_feliminate_unused_debug?, true
421
-
422
- # Returns whether compiling C++ with -fvisibility=hidden might result
423
- # in tons of useless warnings, like this:
424
- # http://code.google.com/p/phusion-passenger/issues/detail?id=526
425
- # This appears to be a bug in older g++ versions:
426
- # http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00861.html
427
- # Warnings should be suppressed with -Wno-attributes.
428
- def self.cc_visibility_flag_generates_warnings?
429
- if os_name =~ /linux/ && `#{cc} -v 2>&1` =~ /gcc version (.*?)/
430
- return $1 <= "4.1.2"
431
- else
432
- return false
433
- end
434
- end
435
- memoize :cc_visibility_flag_generates_warnings?, true
436
-
437
- def self.cxx_visibility_flag_generates_warnings?
438
- if os_name =~ /linux/ && `#{cxx} -v 2>&1` =~ /gcc version (.*?)/
439
- return $1 <= "4.1.2"
440
- else
441
- return false
442
- end
443
- end
444
- memoize :cxx_visibility_flag_generates_warnings?, true
445
-
446
- def self.adress_sanitizer_flag
447
- if cc_is_clang?
448
- if `#{cc} --help` =~ /-fsanitize=/
449
- return "-fsanitize=address"
450
- else
451
- return "-faddress-sanitizer"
452
- end
453
- else
454
- return nil
455
- end
456
- end
457
- memoize :adress_sanitizer_flag
458
-
459
- def self.cxx_11_flag
460
- # C++11 support on FreeBSD 10.0 + Clang seems to be bugged.
461
- # http://llvm.org/bugs/show_bug.cgi?id=18310
462
- return nil if os_name =~ /freebsd/
463
-
464
- source = %{
465
- struct Foo {
466
- Foo(Foo &&f) { }
467
- };
468
- }
469
- if try_compile("Checking for C++ -std=gnu++11 compiler flag", :cxx, source, '-std=gnu++11')
470
- return "-std=gnu++11"
471
- elsif try_compile("Checking for C++ -std=c++11 compiler flag", :cxx, source, '-std=c++11')
472
- return "-std=c++11"
473
- else
474
- return nil
475
- end
476
- end
477
- memoize :cxx_11_flag, true
478
-
479
- def self.has_rt_library?
480
- return try_link("Checking for -lrt support",
481
- :c, "int main() { return 0; }\n", '-lrt')
482
- end
483
- memoize :has_rt_library?, true
484
-
485
- def self.has_math_library?
486
- return try_link("Checking for -lmath support",
487
- :c, "int main() { return 0; }\n", '-lmath')
488
- end
489
- memoize :has_math_library?, true
490
-
491
- def self.has_alloca_h?
492
- return try_compile("Checking for alloca.h",
493
- :c, '#include <alloca.h>')
494
- end
495
- memoize :has_alloca_h?, true
496
-
497
- def self.has_accept4?
498
- return try_compile("Checking for accept4()", :c, %Q{
499
- #define _GNU_SOURCE
500
- #include <sys/socket.h>
501
- static void *foo = accept4;
502
- })
503
- end
504
- memoize :has_accept4?, true
505
-
506
- # C compiler flags that should be passed in order to enable debugging information.
507
- def self.debugging_cflags
508
- # According to OpenBSD's pthreads man page, pthreads do not work
509
- # correctly when an app is compiled with -g. It recommends using
510
- # -ggdb instead.
511
- #
512
- # In any case we'll always want to use -ggdb for better GDB debugging.
513
- if cc_is_gcc?
514
- return '-ggdb'
515
- else
516
- return '-g'
517
- end
518
- end
519
-
520
- def self.dmalloc_ldflags
521
- if !ENV['DMALLOC_LIBS'].to_s.empty?
522
- return ENV['DMALLOC_LIBS']
523
- end
524
- if os_name == "macosx"
525
- ['/opt/local', '/usr/local', '/usr'].each do |prefix|
526
- filename = "#{prefix}/lib/libdmallocthcxx.a"
527
- if File.exist?(filename)
528
- return filename
529
- end
530
- end
531
- return nil
532
- else
533
- return "-ldmallocthcxx"
534
- end
535
- end
536
- memoize :dmalloc_ldflags
537
-
538
- def self.electric_fence_ldflags
539
- if os_name == "macosx"
540
- ['/opt/local', '/usr/local', '/usr'].each do |prefix|
541
- filename = "#{prefix}/lib/libefence.a"
542
- if File.exist?(filename)
543
- return filename
544
- end
545
- end
546
- return nil
547
- else
548
- return "-lefence"
549
- end
550
- end
551
- memoize :electric_fence_ldflags
552
-
553
- def self.export_dynamic_flags
554
- if os_name == "linux"
555
- return '-rdynamic'
556
- else
557
- return nil
558
- end
559
- end
560
-
561
-
562
- def self.make
563
- return string_env('MAKE', find_command('make'))
564
- end
565
- memoize :make, true
566
-
567
- def self.gnu_make
568
- if result = string_env('GMAKE')
569
- return result
570
- else
571
- result = find_command('gmake')
572
- if !result
573
- result = find_command('make')
574
- if result
575
- if `#{result} --version 2>&1` =~ /GNU/
576
- return result
577
- else
578
- return nil
579
- end
580
- else
581
- return nil
582
- end
583
- else
584
- return result
585
- end
586
- end
587
- end
588
- memoize :gnu_make, true
589
-
590
- def self.xcode_select_version
591
- if find_command('xcode-select')
592
- `xcode-select --version` =~ /version (.+)\./
593
- return $1
594
- else
595
- return nil
596
- end
597
- end
598
- end
29
+ module PlatformInfo
30
+ private
31
+ def self.detect_language_extension(language)
32
+ case language
33
+ when :c
34
+ return "c"
35
+ when :cxx
36
+ return "cpp"
37
+ else
38
+ raise ArgumentError, "Unsupported language #{language.inspect}"
39
+ end
40
+ end
41
+ private_class_method :detect_language_extension
42
+
43
+ def self.detect_compiler_type_name(language)
44
+ case language
45
+ when :c
46
+ return "C"
47
+ when :cxx
48
+ return "C++"
49
+ else
50
+ raise ArgumentError, "Unsupported language #{language.inspect}"
51
+ end
52
+ end
53
+ private_class_method :detect_compiler_type_name
54
+
55
+ def self.create_compiler_command(language, flags1, flags2, link = false)
56
+ case language
57
+ when :c
58
+ result = [cc, link ? ENV['EXTRA_PRE_LDFLAGS'] : nil,
59
+ ENV['EXTRA_PRE_CFLAGS'], flags1, flags2, ENV['EXTRA_CFLAGS'],
60
+ ENV['EXTRA_LDFLAGS']]
61
+ when :cxx
62
+ result = [cxx, link ? ENV['EXTRA_PRE_LDFLAGS'] : nil,
63
+ ENV['EXTRA_PRE_CXXFLAGS'], flags1, flags2, ENV['EXTRA_CXXFLAGS'],
64
+ ENV['EXTRA_LDFLAGS']]
65
+ else
66
+ raise ArgumentError, "Unsupported language #{language.inspect}"
67
+ end
68
+ return result.compact.join(" ").strip
69
+ end
70
+ private_class_method :create_compiler_command
71
+
72
+ def self.run_compiler(description, command, source_file, source, capture_output = false)
73
+ if verbose?
74
+ message = "#{description}\n" <<
75
+ "Running: #{command}\n"
76
+ if source.strip.empty?
77
+ message << "Source file is empty."
78
+ else
79
+ message << "Source file contains:\n" <<
80
+ "-------------------------\n" <<
81
+ unindent(source) <<
82
+ "\n-------------------------"
83
+ end
84
+ log(message)
85
+ end
86
+ if capture_output
87
+ begin
88
+ output = `#{command} 2>&1`
89
+ result = $?.exitstatus == 0
90
+ rescue SystemCallError => e
91
+ result = nil
92
+ exec_error_reason = e.message
93
+ end
94
+ log("Output:\n" <<
95
+ "-------------------------\n" <<
96
+ output.to_s <<
97
+ "\n-------------------------")
98
+ elsif verbose?
99
+ result = system(command)
100
+ else
101
+ result = system("(#{command}) >/dev/null 2>/dev/null")
102
+ end
103
+ if result.nil?
104
+ log("Command could not be executed! #{exec_error_reason}".strip)
105
+ return false
106
+ elsif result
107
+ log("Check suceeded")
108
+ if capture_output
109
+ return { :result => true, :output => output }
110
+ else
111
+ return true
112
+ end
113
+ else
114
+ log("Check failed with exit status #{$?.exitstatus}")
115
+ if capture_output == :always
116
+ return { :result => false, :output => output }
117
+ else
118
+ return false
119
+ end
120
+ end
121
+ end
122
+ private_class_method :run_compiler
123
+
124
+ def self.cc_or_cxx_supports_feliminate_unused_debug?(language)
125
+ ext = detect_language_extension(language)
126
+ compiler_type_name = detect_compiler_type_name(language)
127
+ create_temp_file("passenger-compile-check.#{ext}") do |filename, f|
128
+ f.close
129
+ begin
130
+ command = create_compiler_command(language,
131
+ "-c '#{filename}' -o '#{filename}.o'",
132
+ '-feliminate-unused-debug-symbols -feliminate-unused-debug-types')
133
+ result = run_compiler("Checking for #{compiler_type_name} compiler '-feliminate-unused-debug-{symbols,types}' support",
134
+ command, filename, '', true)
135
+ return result && result[:output].empty?
136
+ ensure
137
+ File.unlink("#{filename}.o") rescue nil
138
+ end
139
+ end
140
+ end
141
+ private_class_method :cc_or_cxx_supports_feliminate_unused_debug?
142
+
143
+ public
144
+ def self.cc
145
+ return string_env('CC', default_cc)
146
+ end
147
+ memoize :cc
148
+
149
+ def self.cxx
150
+ return string_env('CXX', default_cxx)
151
+ end
152
+ memoize :cxx
153
+
154
+ def self.default_cc
155
+ # On most platforms, we'll want to use the same compiler as what the rest
156
+ # of the system uses, so that we generate compatible binaries. That's
157
+ # most likely the 'cc' command. We used to use 'gcc' by default.
158
+ #
159
+ # See for example this issue with OS X Mavericks (10.9). They switched from
160
+ # GCC to Clang as the default compiler. Since the Nginx by default uses 'cc'
161
+ # as the compiler, we'll have to do that too. Otherwise we'll get C++ linker
162
+ # errors because Nginx is compiled with Clang while Phusion Passenger is
163
+ # compiled with GCC.
164
+ # https://code.google.com/p/phusion-passenger/issues/detail?id=950
165
+ if PlatformInfo.find_command('cc')
166
+ return 'cc'
167
+ else
168
+ return 'gcc'
169
+ end
170
+ end
171
+
172
+ def self.default_cxx
173
+ if PlatformInfo.find_command('c++')
174
+ return 'c++'
175
+ else
176
+ return 'g++'
177
+ end
178
+ end
179
+
180
+ def self.cc_is_gcc?
181
+ `#{cc} -v 2>&1` =~ /gcc version/
182
+ end
183
+ memoize :cc_is_gcc?
184
+
185
+ def self.cxx_is_gcc?
186
+ `#{cxx} -v 2>&1` =~ /gcc version/
187
+ end
188
+ memoize :cxx_is_gcc?
189
+
190
+ def self.cc_is_clang?
191
+ `#{cc} --version 2>&1` =~ /clang version/
192
+ end
193
+ memoize :cc_is_clang?
194
+
195
+ def self.cxx_is_clang?
196
+ `#{cxx} --version 2>&1` =~ /clang version/
197
+ end
198
+ memoize :cxx_is_clang?
199
+
200
+ def self.cc_is_sun_studio?
201
+ `#{cc} -V 2>&1` =~ /Sun C/ || `#{cc} -flags 2>&1` =~ /Sun C/
202
+ end
203
+ memoize :cc_is_sun_studio?
204
+
205
+ def self.cxx_is_sun_studio?
206
+ `#{cxx} -V 2>&1` =~ /Sun C/ || `#{cxx} -flags 2>&1` =~ /Sun C/
207
+ end
208
+ memoize :cxx_is_sun_studio?
209
+
210
+
211
+ # Looks for the given C or C++ header. This works by invoking the compiler and
212
+ # searching in the compiler's header search path. Returns its full filename,
213
+ # or true if this function knows that the header exists but can't find it (e.g.
214
+ # because the compiler cannot tell us what its header search path is).
215
+ # Returns nil if the header cannot be found.
216
+ def self.find_header(header_name, language, flags = nil)
217
+ extension = detect_language_extension(language)
218
+ create_temp_file("passenger-compile-check.#{extension}") do |filename, f|
219
+ source = %Q{
220
+ #include <#{header_name}>
221
+ }
222
+ f.puts(source)
223
+ f.close
224
+ begin
225
+ command = create_compiler_command(language,
226
+ "-v -c '#{filename}' -o '#{filename}.o'",
227
+ flags)
228
+ if result = run_compiler("Checking for #{header_name}", command, filename, source, true)
229
+ result[:output] =~ /^#include <...> search starts here:$(.+?)^End of search list\.$/m
230
+ search_paths = $1.to_s.strip.split("\n").map{ |line| line.strip }
231
+ search_paths.each do |dir|
232
+ if File.file?("#{dir}/#{header_name}")
233
+ return "#{dir}/#{header_name}"
234
+ end
235
+ end
236
+ return true
237
+ else
238
+ return nil
239
+ end
240
+ ensure
241
+ File.unlink("#{filename}.o") rescue nil
242
+ end
243
+ end
244
+ end
245
+
246
+ def self.try_compile(description, language, source, flags = nil)
247
+ extension = detect_language_extension(language)
248
+ create_temp_file("passenger-compile-check.#{extension}") do |filename, f|
249
+ f.puts(source)
250
+ f.close
251
+ command = create_compiler_command(language,
252
+ "-c '#{filename}' -o '#{filename}.o'",
253
+ flags)
254
+ return run_compiler(description, command, filename, source)
255
+ end
256
+ end
257
+
258
+ # Like try_compile, but designed for checking whether a warning flag is
259
+ # supported. Compilers sometimes do not error out upon encountering an
260
+ # unsupported warning flag, but merely print a warning. This method checks
261
+ # for that too.
262
+ def self.try_compile_with_warning_flag(description, language, source, flags = nil)
263
+ extension = detect_language_extension(language)
264
+ create_temp_file("passenger-compile-check.#{extension}") do |filename, f|
265
+ f.puts(source)
266
+ f.close
267
+ command = create_compiler_command(language,
268
+ "-c '#{filename}' -o '#{filename}.o'",
269
+ flags)
270
+ result = run_compiler(description, command, filename, source, true)
271
+ return result && result[:result] && result[:output] !~ /unknown warning option/i
272
+ end
273
+ end
274
+
275
+ def self.try_link(description, language, source, flags = nil)
276
+ extension = detect_language_extension(language)
277
+ create_temp_file("passenger-link-check.#{extension}") do |filename, f|
278
+ f.puts(source)
279
+ f.close
280
+ command = create_compiler_command(language,
281
+ "'#{filename}' -o '#{filename}.out'",
282
+ flags, true)
283
+ return run_compiler(description, command, filename, source)
284
+ end
285
+ end
286
+
287
+ def self.try_compile_and_run(description, language, source, flags = nil)
288
+ extension = detect_language_extension(language)
289
+ create_temp_file("passenger-run-check.#{extension}", tmpexedir) do |filename, f|
290
+ f.puts(source)
291
+ f.close
292
+ command = create_compiler_command(language,
293
+ "'#{filename}' -o '#{filename}.out'",
294
+ flags, true)
295
+ if run_compiler(description, command, filename, source)
296
+ log("Running #{filename}.out")
297
+ begin
298
+ output = `'#{filename}.out' 2>&1`
299
+ rescue SystemCallError => e
300
+ log("Command failed: #{e}")
301
+ return false
302
+ end
303
+ status = $?.exitstatus
304
+ log("Command exited with status #{status}. Output:\n--------------\n#{output}\n--------------")
305
+ return status == 0
306
+ else
307
+ return false
308
+ end
309
+ end
310
+ end
311
+
312
+
313
+ # Checks whether the compiler supports "-arch #{arch}".
314
+ def self.compiler_supports_architecture?(arch)
315
+ return try_compile("Checking for C compiler '-arch' support",
316
+ :c, '', "-arch #{arch}")
317
+ end
318
+
319
+ def self.cc_supports_visibility_flag?
320
+ return false if os_name =~ /aix/
321
+ return try_compile("Checking for C compiler '-fvisibility' support",
322
+ :c, '', '-fvisibility=hidden')
323
+ end
324
+ memoize :cc_supports_visibility_flag?, true
325
+
326
+ def self.cxx_supports_visibility_flag?
327
+ return false if os_name =~ /aix/
328
+ return try_compile("Checking for C++ compiler '-fvisibility' support",
329
+ :cxx, '', '-fvisibility=hidden')
330
+ end
331
+ memoize :cxx_supports_visibility_flag?, true
332
+
333
+ def self.cc_supports_wno_attributes_flag?
334
+ return try_compile_with_warning_flag(
335
+ "Checking for C compiler '-Wno-attributes' support",
336
+ :c, '', '-Wno-attributes')
337
+ end
338
+ memoize :cc_supports_wno_attributes_flag?, true
339
+
340
+ def self.cxx_supports_wno_attributes_flag?
341
+ return try_compile_with_warning_flag(
342
+ "Checking for C++ compiler '-Wno-attributes' support",
343
+ :cxx, '', '-Wno-attributes')
344
+ end
345
+ memoize :cxx_supports_wno_attributes_flag?, true
346
+
347
+ def self.cc_supports_wno_missing_field_initializers_flag?
348
+ return try_compile_with_warning_flag(
349
+ "Checking for C compiler '-Wno-missing-field-initializers' support",
350
+ :c, '', '-Wno-missing-field-initializers')
351
+ end
352
+ memoize :cc_supports_wno_missing_field_initializers_flag?, true
353
+
354
+ def self.cxx_supports_wno_missing_field_initializers_flag?
355
+ return try_compile_with_warning_flag(
356
+ "Checking for C++ compiler '-Wno-missing-field-initializers' support",
357
+ :cxx, '', '-Wno-missing-field-initializers')
358
+ end
359
+ memoize :cxx_supports_wno_missing_field_initializers_flag?, true
360
+
361
+ def self.cxx_supports_wno_unused_local_typedefs_flag?
362
+ return try_compile_with_warning_flag(
363
+ "Checking for C++ compiler '-Wno-unused-local-typedefs' support",
364
+ :cxx, '', '-Wno-unused-local-typedefs')
365
+ end
366
+ memoize :cxx_supports_wno_unused_local_typedefs_flag?, true
367
+
368
+ def self.cc_supports_no_tls_direct_seg_refs_option?
369
+ return try_compile("Checking for C compiler '-mno-tls-direct-seg-refs' support",
370
+ :c, '', '-mno-tls-direct-seg-refs')
371
+ end
372
+ memoize :cc_supports_no_tls_direct_seg_refs_option?, true
373
+
374
+ def self.cxx_supports_no_tls_direct_seg_refs_option?
375
+ return try_compile("Checking for C++ compiler '-mno-tls-direct-seg-refs' support",
376
+ :cxx, '', '-mno-tls-direct-seg-refs')
377
+ end
378
+ memoize :cxx_supports_no_tls_direct_seg_refs_option?, true
379
+
380
+ def self.compiler_supports_wno_ambiguous_member_template?
381
+ result = try_compile_with_warning_flag(
382
+ "Checking for C++ compiler '-Wno-ambiguous-member-template' support",
383
+ :cxx, '', '-Wno-ambiguous-member-template')
384
+ return false if !result
385
+
386
+ # For some reason, GCC does not complain about -Wno-ambiguous-member-template
387
+ # not being supported unless the source contains another error. So we
388
+ # check for this.
389
+ create_temp_file("passenger-compile-check.cpp") do |filename, f|
390
+ source = %Q{
391
+ void foo() {
392
+ return error;
393
+ }
394
+ }
395
+ f.puts(source)
396
+ f.close
397
+ begin
398
+ command = create_compiler_command(:cxx,
399
+ "-c '#{filename}' -o '#{filename}.o'",
400
+ '-Wno-ambiguous-member-template')
401
+ result = run_compiler("Checking whether C++ compiler '-Wno-ambiguous-member-template' support is *really* supported",
402
+ command, filename, source, :always)
403
+ ensure
404
+ File.unlink("#{filename}.o") rescue nil
405
+ end
406
+ end
407
+
408
+ return result && result[:output] !~ /-Wno-ambiguous-member-template/
409
+ end
410
+ memoize :compiler_supports_wno_ambiguous_member_template?, true
411
+
412
+ def self.cc_supports_feliminate_unused_debug?
413
+ return cc_or_cxx_supports_feliminate_unused_debug?(:c)
414
+ end
415
+ memoize :cc_supports_feliminate_unused_debug?, true
416
+
417
+ def self.cxx_supports_feliminate_unused_debug?
418
+ return cc_or_cxx_supports_feliminate_unused_debug?(:cxx)
419
+ end
420
+ memoize :cxx_supports_feliminate_unused_debug?, true
421
+
422
+ # Returns whether compiling C++ with -fvisibility=hidden might result
423
+ # in tons of useless warnings, like this:
424
+ # http://code.google.com/p/phusion-passenger/issues/detail?id=526
425
+ # This appears to be a bug in older g++ versions:
426
+ # http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00861.html
427
+ # Warnings should be suppressed with -Wno-attributes.
428
+ def self.cc_visibility_flag_generates_warnings?
429
+ if os_name =~ /linux/ && `#{cc} -v 2>&1` =~ /gcc version (.*?)/
430
+ return $1 <= "4.1.2"
431
+ else
432
+ return false
433
+ end
434
+ end
435
+ memoize :cc_visibility_flag_generates_warnings?, true
436
+
437
+ def self.cxx_visibility_flag_generates_warnings?
438
+ if os_name =~ /linux/ && `#{cxx} -v 2>&1` =~ /gcc version (.*?)/
439
+ return $1 <= "4.1.2"
440
+ else
441
+ return false
442
+ end
443
+ end
444
+ memoize :cxx_visibility_flag_generates_warnings?, true
445
+
446
+ def self.adress_sanitizer_flag
447
+ if cc_is_clang?
448
+ if `#{cc} --help` =~ /-fsanitize=/
449
+ return "-fsanitize=address"
450
+ else
451
+ return "-faddress-sanitizer"
452
+ end
453
+ else
454
+ return nil
455
+ end
456
+ end
457
+ memoize :adress_sanitizer_flag
458
+
459
+ def self.cxx_11_flag
460
+ # C++11 support on FreeBSD 10.0 + Clang seems to be bugged.
461
+ # http://llvm.org/bugs/show_bug.cgi?id=18310
462
+ return nil if os_name =~ /freebsd/
463
+
464
+ source = %{
465
+ struct Foo {
466
+ Foo(Foo &&f) { }
467
+ };
468
+ }
469
+ if try_compile("Checking for C++ -std=gnu++11 compiler flag", :cxx, source, '-std=gnu++11')
470
+ return "-std=gnu++11"
471
+ elsif try_compile("Checking for C++ -std=c++11 compiler flag", :cxx, source, '-std=c++11')
472
+ return "-std=c++11"
473
+ else
474
+ return nil
475
+ end
476
+ end
477
+ memoize :cxx_11_flag, true
478
+
479
+ def self.has_rt_library?
480
+ return try_link("Checking for -lrt support",
481
+ :c, "int main() { return 0; }\n", '-lrt')
482
+ end
483
+ memoize :has_rt_library?, true
484
+
485
+ def self.has_math_library?
486
+ return try_link("Checking for -lmath support",
487
+ :c, "int main() { return 0; }\n", '-lmath')
488
+ end
489
+ memoize :has_math_library?, true
490
+
491
+ def self.has_alloca_h?
492
+ return try_compile("Checking for alloca.h",
493
+ :c, '#include <alloca.h>')
494
+ end
495
+ memoize :has_alloca_h?, true
496
+
497
+ def self.has_accept4?
498
+ return try_compile("Checking for accept4()", :c, %Q{
499
+ #define _GNU_SOURCE
500
+ #include <sys/socket.h>
501
+ static void *foo = accept4;
502
+ })
503
+ end
504
+ memoize :has_accept4?, true
505
+
506
+ # C compiler flags that should be passed in order to enable debugging information.
507
+ def self.debugging_cflags
508
+ # According to OpenBSD's pthreads man page, pthreads do not work
509
+ # correctly when an app is compiled with -g. It recommends using
510
+ # -ggdb instead.
511
+ #
512
+ # In any case we'll always want to use -ggdb for better GDB debugging.
513
+ if cc_is_gcc?
514
+ return '-ggdb'
515
+ else
516
+ return '-g'
517
+ end
518
+ end
519
+
520
+ def self.dmalloc_ldflags
521
+ if !ENV['DMALLOC_LIBS'].to_s.empty?
522
+ return ENV['DMALLOC_LIBS']
523
+ end
524
+ if os_name == "macosx"
525
+ ['/opt/local', '/usr/local', '/usr'].each do |prefix|
526
+ filename = "#{prefix}/lib/libdmallocthcxx.a"
527
+ if File.exist?(filename)
528
+ return filename
529
+ end
530
+ end
531
+ return nil
532
+ else
533
+ return "-ldmallocthcxx"
534
+ end
535
+ end
536
+ memoize :dmalloc_ldflags
537
+
538
+ def self.electric_fence_ldflags
539
+ if os_name == "macosx"
540
+ ['/opt/local', '/usr/local', '/usr'].each do |prefix|
541
+ filename = "#{prefix}/lib/libefence.a"
542
+ if File.exist?(filename)
543
+ return filename
544
+ end
545
+ end
546
+ return nil
547
+ else
548
+ return "-lefence"
549
+ end
550
+ end
551
+ memoize :electric_fence_ldflags
552
+
553
+ def self.export_dynamic_flags
554
+ if os_name == "linux"
555
+ return '-rdynamic'
556
+ else
557
+ return nil
558
+ end
559
+ end
560
+
561
+
562
+ def self.make
563
+ return string_env('MAKE', find_command('make'))
564
+ end
565
+ memoize :make, true
566
+
567
+ def self.gnu_make
568
+ if result = string_env('GMAKE')
569
+ return result
570
+ else
571
+ result = find_command('gmake')
572
+ if !result
573
+ result = find_command('make')
574
+ if result
575
+ if `#{result} --version 2>&1` =~ /GNU/
576
+ return result
577
+ else
578
+ return nil
579
+ end
580
+ else
581
+ return nil
582
+ end
583
+ else
584
+ return result
585
+ end
586
+ end
587
+ end
588
+ memoize :gnu_make, true
589
+
590
+ def self.xcode_select_version
591
+ if find_command('xcode-select')
592
+ `xcode-select --version` =~ /version (.+)\./
593
+ return $1
594
+ else
595
+ return nil
596
+ end
597
+ end
598
+ end
599
599
 
600
600
  end # module PhusionPassenger