-
-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathsunshine-beta.rb
More file actions
484 lines (407 loc) · 14.8 KB
/
Copy pathsunshine-beta.rb
File metadata and controls
484 lines (407 loc) · 14.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
require "language/node"
class SunshineBeta < Formula
include Language::Python::Virtualenv
CUDA_VERSION = "13.1".freeze
CUDA_FORMULA = "cuda@#{CUDA_VERSION}".freeze
COVERAGE_LCOV = "coverage.lcov".freeze
COVERAGE_PROFDATA = "coverage.profdata".freeze
COVERAGE_XML = "coverage.xml".freeze
GCC_VERSION = "14".freeze
GCC_FORMULA = "gcc@#{GCC_VERSION}".freeze
LLVM_PROFILE_FILE_ENV = "LLVM_PROFILE_FILE".freeze
TEST_BINARY = "test_sunshine".freeze
IS_UPSTREAM_REPO = ENV.fetch("GITHUB_REPOSITORY", "") == "LizardByte/Sunshine"
desc "Self-hosted game stream host for Moonlight"
homepage "https://app.lizardbyte.dev/Sunshine"
url "https://github.com/LizardByte/Sunshine.git",
tag: "v2026.816.192458"
license all_of: ["GPL-3.0-only"]
head "https://github.com/LizardByte/Sunshine.git", branch: "master"
# https://docs.brew.sh/Brew-Livecheck#githublatest-strategy-block
livecheck do
url :stable
regex(/^v?(\d+\.\d+\.\d+)$/i)
strategy :github_releases do |json, regex|
json.map do |release|
next if release["draft"]
match = release["tag_name"]&.match(regex)
next if match.blank?
match[1]
end
end
end
bottle do
root_url "https://ghcr.io/v2/lizardbyte/homebrew"
sha256 arm64_tahoe: "8f91eb18a426a8e957c7abfb0426b11c2bf93132a64b38a1b52db4660c6ea231"
sha256 arm64_sequoia: "4f3b17855df34e4f9e96f38cca0b2df584acd7f6b468919ee4633bb8fb15bba0"
sha256 arm64_sonoma: "01c7d5ce6ca57931c2f720b40979b0ec30b07bc8f46cc5691a236561b320677d"
sha256 arm64_linux: "6243b6bc21a2f677d00fd63f66b485fdc65ebeee61684b9ea108d00d200c1663"
sha256 x86_64_linux: "461d1c00d25d8b8d06e411574dafbc4bf9a8de9b158ea645c40627b680c93a35"
end
option "with-docs", "Enable docs build"
option "with-static-boost", "Enable static link of Boost libraries"
option "without-static-boost", "Disable static link of Boost libraries" # default option
depends_on "cmake" => :build
depends_on "doxygen" => :build if build.with? "docs"
depends_on "graphviz" => :build if build.with? "docs"
depends_on "node" => :build
depends_on "pkgconf" => :build
depends_on "boost"
depends_on "curl"
depends_on "icu4c@78"
depends_on "miniupnpc"
depends_on "openssl@3"
depends_on "opus"
depends_on "qtbase"
depends_on "qtsvg"
on_sonoma do
depends_on xcode: ["16.2", :build] # required for jthreads on macos-14
end
on_linux do
depends_on GCC_FORMULA => [:build, :test]
depends_on "gcovr" => [:build, :test]
depends_on "lizardbyte/homebrew/#{CUDA_FORMULA}" => :build
depends_on "python3" => :build
depends_on "imagemagick" => :test
depends_on "at-spi2-core"
depends_on "avahi"
depends_on "cairo"
depends_on "gdk-pixbuf"
depends_on "glib"
depends_on "gnu-which"
depends_on "harfbuzz"
depends_on "libcap"
depends_on "libdrm"
depends_on "libice"
depends_on "libsm"
depends_on "libva"
depends_on "libx11"
depends_on "libxcb"
depends_on "libxcursor"
depends_on "libxext"
depends_on "libxfixes"
depends_on "libxi"
depends_on "libxinerama"
depends_on "libxrandr"
depends_on "libxtst"
depends_on "mesa"
depends_on "numactl"
depends_on "pango"
depends_on "pipewire"
depends_on "pulseaudio"
depends_on "shaderc"
depends_on "systemd"
depends_on "vulkan-loader"
depends_on "wayland"
# Jinja2 is required at build time by the glad OpenGL/EGL loader generator (Linux only).
# Declared as resources per https://docs.brew.sh/Formula-Cookbook#python-dependencies
resource "markupsafe" do
url "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz"
sha256 "722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"
end
resource "jinja2" do
url "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz"
sha256 "0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"
end
end
conflicts_with "sunshine", because: "sunshine and sunshine-beta cannot be installed at the same time"
fails_with :clang do
build 1400
cause "Requires C++23 support"
end
fails_with :gcc do
version "12" # fails with GCC 12.x and earlier
cause "Requires C++23 support"
end
fails_with :gcc do
version "13"
cause "Array out of bounds error when compiling glad sources"
end
def setup_build_environment
ENV["BRANCH"] = ""
ENV["BUILD_VERSION"] = "2026.816.192458"
ENV["COMMIT"] = "687e12d013a838e1769ffdf996eb1d5ef8402660"
setup_linux_gcc_environment if OS.linux?
return unless OS.linux?
# Install jinja2 (required by the glad OpenGL/EGL loader generator) into a
# temporary virtualenv. We pass its Python path to cmake via Python_EXECUTABLE
# so glad uses the venv Python that has jinja2, and set GLAD_SKIP_PIP_INSTALL=ON
# to prevent cmake from trying to install Python dependencies again.
# Follows https://docs.brew.sh/Formula-Cookbook#python-dependencies
venv = virtualenv_create(buildpath/"venv", "python3")
venv.pip_install resources
@glad_python = (buildpath/"venv/bin/python3").to_s
end
def setup_linux_gcc_environment
# Use GCC because gcov from llvm cannot handle our paths
gcc_path = Formula[GCC_FORMULA]
ENV["CC"] = "#{gcc_path.opt_bin}/gcc-#{GCC_VERSION}"
ENV["CXX"] = "#{gcc_path.opt_bin}/g++-#{GCC_VERSION}"
end
def base_cmake_args
args = %W[
-DBUILD_WERROR=ON
-DCMAKE_INSTALL_PREFIX=#{prefix}
-DGLAD_SKIP_PIP_INSTALL=ON
-DHOMEBREW_ALLOW_FETCHCONTENT=ON
-DOPENSSL_ROOT_DIR=#{formula_opt_prefix("openssl")}
-DSUNSHINE_ASSETS_DIR=sunshine/assets
-DSUNSHINE_BUILD_HOMEBREW=ON
-DSUNSHINE_PUBLISHER_NAME='LizardByte'
-DSUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev'
-DSUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
]
args << "-DSUNSHINE_EXECUTABLE_PATH=#{opt_bin}/sunshine" if OS.linux?
# Point cmake at the venv Python that has jinja2 installed (set up in setup_build_environment)
args << "-DPython_EXECUTABLE=#{@glad_python}" if @glad_python
args
end
def add_test_args(args)
if IS_UPSTREAM_REPO
args << "-DBUILD_TESTS=ON"
args << "-DSUNSHINE_LLVM_COVERAGE=ON" if OS.mac?
ohai "Building tests: enabled"
else
args << "-DBUILD_TESTS=OFF"
ohai "Building tests: disabled"
end
end
def add_docs_args(args)
if build.with? "docs"
ohai "Building docs: enabled"
args << "-DBUILD_DOCS=ON"
else
ohai "Building docs: disabled"
args << "-DBUILD_DOCS=OFF"
end
end
def add_boost_args(args)
if build.without? "static-boost"
args << "-DBOOST_USE_STATIC=OFF"
ohai "Disabled statically linking Boost libraries"
else
configure_static_boost(args)
end
end
def configure_static_boost(args)
args << "-DBOOST_USE_STATIC=ON"
ohai "Enabled statically linking Boost libraries"
unless formula_any_version_installed?("icu4c")
odie <<~EOS
icu4c must be installed to link against static Boost libraries,
either install icu4c or use brew install sunshine --with-static-boost instead
EOS
end
ENV.append "CXXFLAGS", "-I#{formula_opt_include("icu4c")}"
icu4c_lib_path = formula_opt_lib("icu4c").to_s
ENV.append "LDFLAGS", "-L#{icu4c_lib_path}"
ENV["LIBRARY_PATH"] = icu4c_lib_path
ohai "Linking against ICU libraries at: #{icu4c_lib_path}"
end
def add_cuda_args(args)
return unless OS.linux?
configure_cuda(args)
end
def configure_cuda(args)
cuda_path = Formula["lizardbyte/homebrew/#{CUDA_FORMULA}"]
nvcc_path = "#{cuda_path.opt_libexec}/homebrew/bin/nvcc"
gcc_path = Formula[GCC_FORMULA]
args << "-DSUNSHINE_ENABLE_CUDA=ON"
args << "-DCMAKE_CUDA_COMPILER:PATH=#{nvcc_path}"
args << "-DCMAKE_CUDA_TOOLKIT_ROOT_DIR:PATH=#{cuda_path.opt_libexec}"
args << "-DCMAKE_CUDA_HOST_COMPILER=#{gcc_path.opt_bin}/gcc-#{GCC_VERSION}"
ohai "CUDA enabled with nvcc at: #{nvcc_path}"
end
def release_homebrew_testpath
testpath_value = ENV.fetch("HOMEBREW_TEST_ARTIFACTS_DIR", "")
return Pathname.new(testpath_value) unless testpath_value.empty?
return if ENV.fetch("HOMEBREW_TEST_BOT", "") != "1"
temp_path = ENV.fetch("HOMEBREW_TEMP", "")
return if temp_path.empty?
Pathname.new(temp_path)/name/"test"
end
def ensure_artifact_exists(path)
odie "#{path} was not created" unless path.exist?
end
def run_test_suite(artifact_dir)
mkdir_p artifact_dir/"tests"
test_results = artifact_dir/"tests/test_results.xml"
if OS.mac?
with_llvm_profile_file(artifact_dir) do
system bin/TEST_BINARY, "--gtest_color=yes", "--gtest_output=xml:#{test_results}"
end
else
system bin/TEST_BINARY, "--gtest_color=yes", "--gtest_output=xml:#{test_results}"
end
ensure_artifact_exists test_results
end
def with_llvm_profile_file(artifact_dir)
original_profile_file = ENV.fetch(LLVM_PROFILE_FILE_ENV, nil)
ENV[LLVM_PROFILE_FILE_ENV] = "#{artifact_dir}/sunshine-%p.profraw"
yield
ensure
if original_profile_file
ENV[LLVM_PROFILE_FILE_ENV] = original_profile_file
else
ENV.delete(LLVM_PROFILE_FILE_ENV)
end
end
def coverage_gcov_options
gcc_path = Formula[GCC_FORMULA]
["--gcov-executable", "#{gcc_path.opt_bin}/gcov-#{GCC_VERSION}"]
end
def llvm_profdata_executable
Utils.safe_popen_read("xcrun", "--find", "llvm-profdata").strip
end
def llvm_cov_executable
Utils.safe_popen_read("xcrun", "--find", "llvm-cov").strip
end
def coverage_report_path(artifact_dir)
artifact_dir/(OS.mac? ? COVERAGE_LCOV : COVERAGE_XML)
end
def coverage_common_options(coverage_report)
[
"--exclude-noncode-lines",
"--exclude-throw-branches",
"--exclude-unreachable-branches",
"--xml-pretty",
"-o=#{coverage_report}",
]
end
def generate_coverage_report(artifact_dir, coverage_buildpath)
return if coverage_buildpath.to_s.empty?
coverage_report = coverage_report_path(artifact_dir)
if OS.mac?
generate_llvm_coverage_report artifact_dir, coverage_buildpath, coverage_report
else
generate_gcov_coverage_report coverage_report, coverage_buildpath
end
ensure_artifact_exists coverage_report
end
def generate_llvm_coverage_report(artifact_dir, coverage_buildpath, coverage_report)
profile_files = Dir["#{artifact_dir}/*.profraw"]
odie "No LLVM profile data was created" if profile_files.empty?
profile_data = artifact_dir/COVERAGE_PROFDATA
system llvm_profdata_executable, "merge", "--sparse", "-o", profile_data.to_s, *profile_files
lcov = Utils.safe_popen_read(
llvm_cov_executable,
"export",
"-format=lcov",
"-instr-profile=#{profile_data}",
(bin/TEST_BINARY).to_s,
)
coverage_report.write lcov_for_source_files(lcov, coverage_buildpath)
ensure_lcov_report_has_lines coverage_report
end
def generate_gcov_coverage_report(coverage_report, coverage_buildpath)
cd "#{coverage_buildpath}/build" do
system "gcovr", ".",
"-r", "../src",
*coverage_gcov_options,
*coverage_common_options(coverage_report)
end
ensure_cobertura_report_has_lines coverage_report
end
def coverage_source_prefixes(coverage_buildpath)
paths = [
coverage_buildpath.to_s,
Pathname.new(coverage_buildpath.to_s).realpath.to_s,
]
paths.uniq.map { |path| "#{path}/src/" }
end
def relative_lcov_record(record, source_prefixes)
lines = record.lines
source_index = lines.index { |line| line.start_with?("SF:") }
return unless source_index
source_path = lines[source_index].delete_prefix("SF:").strip
source_prefix = source_prefixes.find { |prefix| source_path.start_with?(prefix) }
return unless source_prefix
lines[source_index] = "SF:src/#{source_path.delete_prefix(source_prefix)}\n"
"#{lines.join}end_of_record\n"
end
def lcov_for_source_files(lcov, coverage_buildpath)
source_prefixes = coverage_source_prefixes(coverage_buildpath)
records = lcov.split("end_of_record\n")
records.filter_map { |record| relative_lcov_record(record, source_prefixes) }.join
end
def ensure_cobertura_report_has_lines(path)
lines_valid = path.read[/lines-valid="(\d+)"/, 1].to_i
odie "#{path} does not contain any source lines" if lines_valid.zero?
end
def ensure_lcov_report_has_lines(path)
has_lines = path.read.lines.any? { |line| line.start_with?("DA:") }
odie "#{path} does not contain any source lines" unless has_lines
end
def collect_test_artifacts
artifact_dir = release_homebrew_testpath
return unless IS_UPSTREAM_REPO
return unless artifact_dir
run_test_suite artifact_dir
generate_coverage_report artifact_dir, buildpath
end
def build_cmake_args
args = base_cmake_args
add_test_args(args)
add_docs_args(args)
add_boost_args(args)
add_cuda_args(args)
args
end
def build_and_install_project
system "cmake", "-S", ".", "-B", "build", "-G", "Unix Makefiles",
*std_cmake_args,
*build_cmake_args
system "make", "-C", "build"
system "make", "-C", "build", "install"
end
def install_platform_specific_files
bin.install "build/tests/#{TEST_BINARY}" if IS_UPSTREAM_REPO
# codesign the binary on intel macs
system "codesign", "-s", "-", "--force", "--deep", bin/"sunshine" if OS.mac? && Hardware::CPU.intel?
bin.install "src_assets/linux/misc/postinst" if OS.linux?
end
def install
setup_build_environment
build_and_install_project
install_platform_specific_files
collect_test_artifacts
end
service do
run [opt_bin/"sunshine", "~/.config/sunshine/sunshine.conf"] if OS.mac?
name linux: "app-dev.lizardbyte.app.Sunshine" if OS.linux?
end
def post_install
if OS.linux?
opoo <<~EOS
ATTENTION: To complete installation, you must run the following command:
`sudo #{bin}/postinst`
EOS
end
if OS.mac?
opoo <<~EOS
Gamepads are not currently supported on macOS.
EOS
end
end
def caveats
<<~EOS
Thanks for installing Sunshine!
To get started, review the documentation at:
https://docs.lizardbyte.dev/projects/sunshine
EOS
end
test do
# test that the binary runs at all
system bin/"sunshine", "--version"
if IS_UPSTREAM_REPO
artifact_dir = release_homebrew_testpath
if artifact_dir
assert_path_exists artifact_dir/"tests/test_results.xml"
assert_path_exists coverage_report_path(artifact_dir)
elsif ENV.fetch("HOMEBREW_BOTTLE_BUILD", "false") != "true"
run_test_suite testpath
generate_coverage_report testpath, ENV.fetch("HOMEBREW_BUILDPATH", "")
end
end
end
end