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
304require "language/node"
class Sunshine < Formula
CUDA_VERSION = "13.1".freeze
CUDA_FORMULA = "cuda@#{CUDA_VERSION}".freeze
GCC_VERSION = "14".freeze
GCC_FORMULA = "gcc@#{GCC_VERSION}".freeze
IS_UPSTREAM_REPO = ENV.fetch("GITHUB_REPOSITORY", "") == "LizardByte/Sunshine"
desc "@PROJECT_DESCRIPTION@"
homepage "@PROJECT_HOMEPAGE_URL@"
url "@GITHUB_CLONE_URL@",
tag: "@GITHUB_TAG@"
version "@BUILD_VERSION@"
license all_of: ["GPL-3.0-only"]
head "@GITHUB_CLONE_URL@", branch: "@GITHUB_DEFAULT_BRANCH@"
# https://docs.brew.sh/Brew-Livecheck#githublatest-strategy-block
livecheck do
url :stable
regex(/^v?(\d+\.\d+\.\d+)$/i)
strategy :github_latest do |json, regex|
match = json["tag_name"]&.match(regex)
next if match.blank?
match[1]
end
end
bottle do
root_url "https://ghcr.io/v2/lizardbyte/homebrew"
sha256 arm64_tahoe: "0000000000000000000000000000000000000000000000000000000000000000"
sha256 arm64_sequoia: "0000000000000000000000000000000000000000000000000000000000000000"
sha256 arm64_sonoma: "0000000000000000000000000000000000000000000000000000000000000000"
sha256 x86_64_linux: "0000000000000000000000000000000000000000000000000000000000000000"
end
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, :recommended]
depends_on "graphviz" => :build if build.with? "doxygen"
depends_on "node" => :build
depends_on "pkgconf" => :build
depends_on "gcovr" => :test
depends_on "boost"
depends_on "curl"
depends_on "icu4c@78"
depends_on "miniupnpc"
depends_on "openssl@3"
depends_on "opus"
on_macos do
depends_on "llvm" => [:build, :test]
end
on_linux do
depends_on GCC_FORMULA => [:build, :test]
depends_on "lizardbyte/homebrew/#{CUDA_FORMULA}" => [:build, :recommended]
depends_on "at-spi2-core"
depends_on "avahi"
depends_on "ayatana-ido"
depends_on "cairo"
depends_on "gdk-pixbuf"
depends_on "glib"
depends_on "gnu-which"
depends_on "gtk+3"
depends_on "harfbuzz"
depends_on "libayatana-appindicator"
depends_on "libayatana-indicator"
depends_on "libcap"
depends_on "libdbusmenu"
depends_on "libdrm"
depends_on "libice"
depends_on "libnotify"
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 "pulseaudio"
depends_on "systemd"
depends_on "wayland"
end
conflicts_with "sunshine-beta", 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
def setup_build_environment
ENV["BRANCH"] = "@GITHUB_BRANCH@"
ENV["BUILD_VERSION"] = "@BUILD_VERSION@"
ENV["COMMIT"] = "@GITHUB_COMMIT@"
setup_linux_gcc_environment if OS.linux?
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
%W[
-DBUILD_WERROR=ON
-DCMAKE_CXX_STANDARD=23
-DCMAKE_INSTALL_PREFIX=#{prefix}
-DHOMEBREW_ALLOW_FETCHCONTENT=ON
-DOPENSSL_ROOT_DIR=#{Formula["openssl"].opt_prefix}
-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'
]
end
def add_test_args(args)
if IS_UPSTREAM_REPO
args << "-DBUILD_TESTS=ON"
ohai "Building tests: enabled"
else
args << "-DBUILD_TESTS=OFF"
ohai "Building tests: disabled"
end
end
def add_docs_args(args)
if build.with? "doxygen"
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["icu4c"].any_version_installed?
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["icu4c"].opt_include}"
icu4c_lib_path = Formula["icu4c"].opt_lib.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?
if build.with?(CUDA_FORMULA)
configure_cuda(args)
else
args << "-DSUNSHINE_ENABLE_CUDA=OFF"
ohai "CUDA disabled"
end
end
def configure_cuda(args)
cuda_path = Formula["lizardbyte/homebrew/#{CUDA_FORMULA}"]
nvcc_path = "#{cuda_path.opt_bin}/nvcc"
gcc_path = Formula[GCC_FORMULA]
args << "-DSUNSHINE_ENABLE_CUDA=ON"
args << "-DCMAKE_CUDA_COMPILER:PATH=#{nvcc_path}"
args << "-DCMAKE_CUDA_HOST_COMPILER=#{gcc_path.opt_bin}/gcc-#{GCC_VERSION}"
ohai "CUDA enabled with nvcc at: #{nvcc_path}"
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_sunshine" 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
end
service do
run [opt_bin/"sunshine", "~/.config/sunshine/sunshine.conf"]
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
Sunshine can only access microphones on macOS due to system limitations.
To stream system audio use "Soundflower" or "BlackHole".
Gamepads are not currently supported on macOS.
EOS
end
end
def caveats
<<~EOS
Thanks for installing @PROJECT_NAME@!
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 && ENV.fetch("HOMEBREW_BOTTLE_BUILD", "false") != "true"
# run the test suite
system bin/"test_sunshine", "--gtest_color=yes", "--gtest_output=xml:tests/test_results.xml"
assert_path_exists File.join(testpath, "tests", "test_results.xml")
# create gcovr report
buildpath = ENV.fetch("HOMEBREW_BUILDPATH", "")
unless buildpath.empty?
# Change to the source directory for gcovr to work properly
cd "#{buildpath}/build" do
# Use GCC version to match what was used during compilation
if OS.linux?
gcc_path = Formula[GCC_FORMULA]
gcov_executable = "#{gcc_path.opt_bin}/gcov-#{GCC_VERSION}"
system "gcovr", ".",
"-r", "../src",
"--gcov-executable", gcov_executable,
"--exclude-noncode-lines",
"--exclude-throw-branches",
"--exclude-unreachable-branches",
"--xml-pretty",
"-o=#{testpath}/coverage.xml"
assert_path_exists File.join(testpath, "coverage.xml")
end
end
end
end
end
end