Compare commits
4301 Commits
Author | SHA1 | Date | |
---|---|---|---|
baa988ec81 | |||
8eac0d34bd | |||
0b1dcb3ea7 | |||
3d529b0c3e | |||
a2ab4804dd | |||
ca226d2ab5 | |||
670e91cb60 | |||
cc291219f9 | |||
0eda2447dc | |||
867e6223ce | |||
3e7f9083ca | |||
902e861fc6 | |||
36d2109a15 | |||
bd9d5e0990 | |||
9a8667e99c | |||
710a48fcaf | |||
52807ab279 | |||
d2a85cb580 | |||
d13db1109f | |||
64bbcb2834 | |||
070d83d887 | |||
cf4144cb50 | |||
40ebae394a | |||
0f95bf1e42 | |||
b446bdf4a9 | |||
ef40ba8439 | |||
1bd69ecbb2 | |||
b18082376d | |||
127a31ba3a | |||
220a1de99a | |||
2349f29be0 | |||
f8bb1a872a | |||
86e2f6c58c | |||
2526275c5e | |||
5a54d80c6e | |||
ea7dd9cfcc | |||
eb3f1ee27a | |||
55ac17c45b | |||
54305397e4 | |||
736246e6c8 | |||
9dcb7e9759 | |||
69c2720872 | |||
364cb4ff6a | |||
df2a92d5f4 | |||
3719ea21b0 | |||
bd11b93a0c | |||
12d567a9b8 | |||
38d77b58cd | |||
a161f5cfe2 | |||
5be80df1ee | |||
87f2f88d4c | |||
b376888f43 | |||
0fe3241df6 | |||
7d5206818b | |||
db19362a97 | |||
cefb96e812 | |||
e7e80e704f | |||
2c4af7e793 | |||
f0fd1bd5e5 | |||
5d926582c7 | |||
7b62d14683 | |||
80723eeca1 | |||
e9fd02baca | |||
7ad48d8677 | |||
9a0cfbc648 | |||
1f2483c39e | |||
b9c1dc7325 | |||
cf33927f21 | |||
c638a63a03 | |||
2081fcd3f5 | |||
90ebbd8e91 | |||
165d218300 | |||
069bc887f1 | |||
5aa2b88861 | |||
d348f20dd9 | |||
b1bd0ceade | |||
8f2f99801e | |||
aae65e3e4e | |||
436db23ffc | |||
6c9856b9dc | |||
0927035a26 | |||
5985d8b118 | |||
cc990c4f94 | |||
c4882e7162 | |||
9d15255e0a | |||
ca9b593483 | |||
ef0813754b | |||
6bbff310bc | |||
6fb7a98901 | |||
9705e6325a | |||
7112d04df5 | |||
2ab48a43dd | |||
682134435d | |||
05d7cc31bf | |||
c498ad1787 | |||
4939a33456 | |||
023b3e3c39 | |||
7015b8f7b2 | |||
32eaaa25d9 | |||
ca4b58d5d7 | |||
4eb8db16f1 | |||
a7842ecc33 | |||
6150908025 | |||
5cb6d93136 | |||
7e6a08548d | |||
11a0241b5c | |||
8eb8f167ab | |||
5f5214e5dd | |||
04a7275280 | |||
05caa874bc | |||
dc74ea7382 | |||
8d0a53273f | |||
bca5e8f395 | |||
d49f81d132 | |||
82461b1113 | |||
4f1ee85424 | |||
b67c2c71d1 | |||
a7bdfb5f6b | |||
c6c17036e3 | |||
e913f61305 | |||
c78d4e7bb6 | |||
024c474658 | |||
03ad430699 | |||
ac38585a2a | |||
3cba5adb5a | |||
d186c34385 | |||
77979b4c95 | |||
8069de29b2 | |||
540fc7d2a8 | |||
d612ab94a7 | |||
bfa9613373 | |||
93be8b0735 | |||
2cea7454ef | |||
eab1180f68 | |||
e3a147f56d | |||
898a719d3e | |||
be8a9f6541 | |||
589ab24f7e | |||
317c7b5544 | |||
00bbbdc6e9 | |||
84269f9596 | |||
34294383eb | |||
4802f6950e | |||
531b58093e | |||
2ff9ef0620 | |||
5b7c5607a9 | |||
9acbf98f94 | |||
bef701eba8 | |||
742384909f | |||
606c12ffeb | |||
498c9db1ce | |||
59e565ef96 | |||
f370f0d749 | |||
b8d9c3d779 | |||
ebde563648 | |||
4ee6a6711d | |||
86b47b3421 | |||
7c636d4608 | |||
0406e168e7 | |||
1684cff7ac | |||
ad9fb7349f | |||
14af7044be | |||
fa65ac3ff7 | |||
f3c089792a | |||
81a3ba18bc | |||
98bc102f5b | |||
97da8892b9 | |||
97ced1f459 | |||
a49851cb40 | |||
d72c3aba80 | |||
9afe80b0e0 | |||
00af385619 | |||
bf6dc10f35 | |||
4cb424470b | |||
9445a555e4 | |||
47d1f23568 | |||
82a0a5bca1 | |||
10192c540b | |||
6aa821df9c | |||
89e434bd5b | |||
78f8a31cd6 | |||
e7d6be531f | |||
ba3a1b6280 | |||
d483b613b1 | |||
cf599865f6 | |||
546d49e183 | |||
7dd2530027 | |||
e9ecdd05b9 | |||
ad6f15f293 | |||
94c1cd6bcf | |||
e155844671 | |||
2918d61b16 | |||
bbf4e3b04d | |||
caf925cbad | |||
88f3e19f81 | |||
19b5a5e00b | |||
347228a246 | |||
1213a5ab46 | |||
17f696bffc | |||
e095780cc3 | |||
c01e95b79c | |||
984e870bca | |||
eb66e37b83 | |||
30ff417074 | |||
7e65aea2ef | |||
6cfe2dbc50 | |||
25ce11d85d | |||
707da5a25a | |||
584e800279 | |||
befa3baa6a | |||
f23a8e4b4b | |||
8c30cb3706 | |||
c1855c6ce3 | |||
b83fdbd1b7 | |||
0e67686295 | |||
e98bca4749 | |||
bdc2fca711 | |||
211865a1e1 | |||
311e36b5d6 | |||
fbf6833124 | |||
e4e4c4a430 | |||
97d932db62 | |||
5d70f4dbca | |||
66cbbfec0c | |||
07d8598638 | |||
79652799bd | |||
630145a1d0 | |||
0680d2dceb | |||
9110fbf282 | |||
e3b04d10cf | |||
8c607ae734 | |||
c5aac24a93 | |||
4036cecfc0 | |||
df14f88307 | |||
29736b3b1f | |||
9735e46a7e | |||
479335dfe0 | |||
d1566f2610 | |||
a2d44744fe | |||
288d0d1fd4 | |||
abfd1a4205 | |||
094cee8ec6 | |||
c54fecf5d9 | |||
172680abf8 | |||
5f3e9672cd | |||
f897b14e3e | |||
bb4b89470d | |||
2990c5d0c9 | |||
ea384d59fb | |||
3e448904a3 | |||
783af2c06a | |||
6c0492c0d1 | |||
1515607060 | |||
41bd008f5d | |||
d7b6450613 | |||
85c23b26de | |||
095de5ed4b | |||
6178e5a975 | |||
aa065f2b51 | |||
59ec0135d7 | |||
2283498ccb | |||
e6ba2f4970 | |||
b93cd88292 | |||
f8f9ffa118 | |||
4704c522e0 | |||
f7951f6082 | |||
eed7e996da | |||
06dbd381f8 | |||
3574d89e0f | |||
0e96111116 | |||
09aca7a0b5 | |||
b1783d8fb1 | |||
c3d03f0c33 | |||
7acfe36a62 | |||
45dad27a6d | |||
fff378b643 | |||
d7dadabfbf | |||
1eb75b6852 | |||
492bf373c6 | |||
02264f67f3 | |||
fcb436f1f4 | |||
e2e0a7af45 | |||
c50c3eaa94 | |||
3638fc0a7d | |||
8092c321a9 | |||
8e5be6f420 | |||
19316e22b4 | |||
5c95448f1f | |||
254444470f | |||
0aaea9bf5d | |||
5b4dcae7d9 | |||
963627fe98 | |||
232bb568da | |||
d3c7850f53 | |||
ebbc8838a8 | |||
d25e89a4c1 | |||
f99b04bd16 | |||
acf586ef82 | |||
0138cd65cb | |||
ab6301d5a1 | |||
3098aecf97 | |||
05094b7382 | |||
58efd3e9e2 | |||
4c52b18bdd | |||
44ff247f5f | |||
fecc1e087a | |||
d3acac16e6 | |||
28ffa8bf44 | |||
eb4efa5a9c | |||
6d1c67663d | |||
f4ebeedc21 | |||
be2888d6fb | |||
7ab391904a | |||
aac734d174 | |||
ffd8ed550f | |||
c5bac475e8 | |||
e88418ab7f | |||
bc0934a19c | |||
044ce4df32 | |||
758999fa64 | |||
4a1d85f999 | |||
6da2e7d3f6 | |||
85f36ebed7 | |||
f8ffb14619 | |||
5e2d1ffdfb | |||
3e2733d840 | |||
bad44ea264 | |||
f0da16a758 | |||
b0e197de38 | |||
6c2c724bd9 | |||
c88088c91a | |||
f919d363b7 | |||
589d8b6923 | |||
a5e7aedb4f | |||
07f25d6cca | |||
c22eec8f27 | |||
1faf741004 | |||
8cff7c4de6 | |||
cf27d2f9ab | |||
6c362afc21 | |||
c94ee67077 | |||
62c14cea2a | |||
01c3750835 | |||
52e5ee7111 | |||
3a0aa353cc | |||
8f5bb982cd | |||
a360ddbe0b | |||
06aba530d7 | |||
c2d6a137ab | |||
b927e58126 | |||
f1c3da6583 | |||
4c446ccd50 | |||
83aa0062c7 | |||
ff67fd10c3 | |||
7ba1e7d356 | |||
f533173b95 | |||
14d5fd7edb | |||
740ca54c87 | |||
6ce7e426d2 | |||
0c753619a4 | |||
4b06255cc2 | |||
1939e3e6ed | |||
9546c77113 | |||
0ba88ff138 | |||
215d7dbb74 | |||
91ba4cf75e | |||
779f70057b | |||
a44cb6430e | |||
1aadaa208d | |||
6d070e8607 | |||
5056a51c18 | |||
3c209ba502 | |||
71890707c0 | |||
b3b2e9df35 | |||
3aba7f8fec | |||
d6e4fe7c1f | |||
c9d628bf18 | |||
35358f8180 | |||
019e5ca3e8 | |||
6423edaa76 | |||
44153a28e3 | |||
bcf0635efd | |||
92dbe1684e | |||
7879091cea | |||
73adac2501 | |||
d801151d5c | |||
ea43d0f687 | |||
396f812496 | |||
f6d8c9659c | |||
e2d77f21ba | |||
ef6f9487f4 | |||
8140374e26 | |||
d67277a668 | |||
97ef8e8d0e | |||
2090f958c8 | |||
8731f4ba27 | |||
b3da35be74 | |||
1c3449e5a2 | |||
a351d1834a | |||
31ffe79a29 | |||
d9cd6f9c50 | |||
e079cbb055 | |||
7004388105 | |||
9afa7cc91f | |||
9a9a4fcfd4 | |||
74fe2fb2a6 | |||
eeb5fdbc9f | |||
a83e5be8f2 | |||
75c7df46a7 | |||
efaf4024ab | |||
99fd1e622c | |||
37e5f6af48 | |||
5b8c997180 | |||
7c547f6452 | |||
f7e8ec1855 | |||
72de2d5254 | |||
f25d0a4e0e | |||
1d3f2674d1 | |||
f9ebcb5d2e | |||
b2fdd83594 | |||
91eb30f037 | |||
d936b25868 | |||
e7c2274893 | |||
377fc0352a | |||
939a2d67ed | |||
304e294ea7 | |||
ae793f6cf1 | |||
1d638e018a | |||
50c7d39e08 | |||
c5bffed21e | |||
d48dd7eb6a | |||
b013133cc1 | |||
1bafa36c17 | |||
afaf6f894c | |||
8b3c465a50 | |||
40c614b3a5 | |||
ac36a2289f | |||
fa2b784f7e | |||
01e17806f6 | |||
f561e7febf | |||
39d4f0df66 | |||
1d468ac35a | |||
ce2ca13815 | |||
f256b836f4 | |||
71fb38c91f | |||
076c189948 | |||
9f66f6495a | |||
c07a857359 | |||
76df836378 | |||
a545f67a21 | |||
9d5818916a | |||
ea56ff255d | |||
01d3eea379 | |||
f13eccb03d | |||
39d7bc6c24 | |||
6a7f63166d | |||
bae59a8c07 | |||
bb039d4bc7 | |||
92b2f463e3 | |||
16e6a01881 | |||
81bc9e488f | |||
e64e4d7ef7 | |||
f19e8dd086 | |||
b4ae6e9774 | |||
5a9f780cf8 | |||
2d1197f59f | |||
d8f2a1354f | |||
b572f75dba | |||
14e16db01e | |||
7091bc81c2 | |||
1e947ca893 | |||
b9fe37aec1 | |||
5d68a4c992 | |||
760b80934f | |||
6d564628b7 | |||
f03924478b | |||
7c1a465ec9 | |||
a7ef663735 | |||
186211244d | |||
5740ee0444 | |||
945939ba68 | |||
9137721e8e | |||
566425166b | |||
d1513732be | |||
1467072f3d | |||
d133b40b25 | |||
c3eb17db74 | |||
4789708cc2 | |||
83fce74bb1 | |||
fcac98b367 | |||
97ff7afbe7 | |||
7e58b965b7 | |||
1ca7e5efe9 | |||
d460986de0 | |||
bdec11c501 | |||
b1aa9e5846 | |||
51bfda937d | |||
4a9ea832ff | |||
a8498b0dab | |||
48e5040196 | |||
928e18b66d | |||
62aa7a52c4 | |||
3c472fd7e0 | |||
b15f689ccf | |||
d960effb99 | |||
1e82cb6a7c | |||
31b62203a7 | |||
af59c41713 | |||
f7ffbcca6c | |||
342a0d0091 | |||
1974bb7e59 | |||
e6b4fc9182 | |||
c778dcbc9c | |||
a0944dab7a | |||
719d87de3b | |||
816acc9c76 | |||
a9fefb2eeb | |||
4ad448993c | |||
bcadffa0e3 | |||
ce2d2c9f32 | |||
6f652e1d2f | |||
361583edfc | |||
fbf29274e8 | |||
3c35d647b8 | |||
b4159d30fc | |||
f843d0732b | |||
280f041acb | |||
4f00012268 | |||
4ab630b832 | |||
a32ca43288 | |||
f505d43fc0 | |||
6a01c277e8 | |||
684c2ec47a | |||
273d75fd51 | |||
6f6b0b9661 | |||
2253100ac6 | |||
b31644e228 | |||
57430fd189 | |||
6ffcfcd7e9 | |||
516ddb22ae | |||
0b74b3833a | |||
ef21879df4 | |||
ad92c30472 | |||
bfafbdc51e | |||
1a7c5693cc | |||
f8b935ab37 | |||
8705e88e91 | |||
0be4db30eb | |||
821dd8400b | |||
c37e1fb9f1 | |||
5088d33fd2 | |||
39f7bea53e | |||
842f08dcfc | |||
f8d9cd9a03 | |||
960093700a | |||
54d393632d | |||
c633c6d083 | |||
96ebdfc9a8 | |||
f55120654a | |||
44ca7c7d22 | |||
58c2059e10 | |||
b7bccb9058 | |||
f046bd7d50 | |||
593f452986 | |||
97662f5c8e | |||
f8d88cc83d | |||
f393aa684e | |||
4c319c8f4f | |||
477b72ad33 | |||
3728cbb62a | |||
015f88bf83 | |||
02082cda09 | |||
5eec0f5901 | |||
3fbc25155b | |||
ecac05b2fc | |||
5b54475d3e | |||
391497645f | |||
f8fcb98c68 | |||
2eff1de560 | |||
1fbb41f5e2 | |||
01afa8957f | |||
5162203c7d | |||
b0940d696b | |||
fe73d696cb | |||
2ea4a78541 | |||
f5891940e0 | |||
cd9310afed | |||
64041a84a2 | |||
78ee63af38 | |||
455c495338 | |||
0bf70d677e | |||
2be630904f | |||
49cebc2da4 | |||
049abc9b1a | |||
e8c44e700d | |||
54a091ca59 | |||
ec32618e11 | |||
aaf1726965 | |||
6b970954d6 | |||
fb5aefffb2 | |||
20e2c70464 | |||
ed2f680202 | |||
5e0df9b696 | |||
ec41252535 | |||
4df9df03ab | |||
7441974d9d | |||
79222a56e3 | |||
cadb7142f0 | |||
251055302e | |||
b54d1651ab | |||
9d0175b81a | |||
002430db46 | |||
de30a72c4e | |||
0a956bbc73 | |||
1e9a596908 | |||
b9568279dc | |||
fcdd9ea986 | |||
c145bfa524 | |||
18ebc858fd | |||
6597a5c860 | |||
a3ffa64550 | |||
a6305ac891 | |||
06fc8358d9 | |||
c346d875a2 | |||
a2a09ffe01 | |||
21ffed3bf5 | |||
fd7aab466b | |||
da87e825a1 | |||
7befd63cce | |||
2c2c39b42c | |||
0692cbe701 | |||
ab10524cd7 | |||
1ccfba13eb | |||
b9ed8283b7 | |||
1495bfb73e | |||
9b02c31f8d | |||
50dae9d4f3 | |||
9a3931dac6 | |||
515197fba2 | |||
149b6d59cf | |||
37fb52aada | |||
db9f5f44e0 | |||
094af0f78f | |||
cebb4dd17a | |||
3487e1cb64 | |||
440afcedb0 | |||
b0a21c9389 | |||
fc4a1ef193 | |||
c8533c0b0d | |||
b0a018d823 | |||
3becd4386b | |||
3099a70edc | |||
cde85947c7 | |||
5d10045cc8 | |||
520594e529 | |||
95b300f1ea | |||
bd6e8533ad | |||
843c2d67eb | |||
89aaedc06c | |||
94d4d12ee0 | |||
997a3709d4 | |||
76cc8ce043 | |||
9499066375 | |||
25f7cf23d3 | |||
9ee68b9268 | |||
1208300ddf | |||
06a7d447f6 | |||
766e833a73 | |||
6d5a2ceefe | |||
149bc8e9ce | |||
9957aeb003 | |||
634612ae81 | |||
f0d2aab784 | |||
4c69290381 | |||
640aaa8c23 | |||
1aa5fa03f9 | |||
99ba02afb6 | |||
9aedb5afff | |||
e21756ea8c | |||
35ccfdb799 | |||
91c9082d19 | |||
4f4ccdaa59 | |||
01e058d8c1 | |||
f816e3cd3f | |||
49109b9213 | |||
d43399c2b4 | |||
308877aa8f | |||
159f14c076 | |||
8e4de055b8 | |||
d7f4e40f85 | |||
6e2fcc9e11 | |||
0d31e31282 | |||
4dc4c589ba | |||
d53d58a5d4 | |||
e704072892 | |||
a54bbae622 | |||
08c140b9b4 | |||
0c6362f28d | |||
67d473aab7 | |||
20c781b23b | |||
7f138e3538 | |||
3211b265d7 | |||
bc2940e16a | |||
1131038fdb | |||
d1528c1044 | |||
51d7a6289e | |||
10678096e5 | |||
51e62761ee | |||
d1cceac7d1 | |||
b8482a5d89 | |||
3139af8487 | |||
6fcdac0d36 | |||
073cb91f88 | |||
3154c2644a | |||
e225a72180 | |||
ec85266860 | |||
4c25e3ce75 | |||
8ae67b84db | |||
440dcdf022 | |||
22327bbe71 | |||
b8b8c8d4ac | |||
93870c315f | |||
13d67c6524 | |||
e8dc1564b6 | |||
f9578066d6 | |||
71e73bb6f8 | |||
8638076aa1 | |||
965ee5687a | |||
2cb22ad280 | |||
4dbcedd03f | |||
5ba13297c6 | |||
5fe9a7a6c3 | |||
a028894855 | |||
183ed7b90b | |||
24b9ed106f | |||
7c8a010378 | |||
817ecf8225 | |||
4509fde410 | |||
34cf28712c | |||
1fbc17d275 | |||
908ac813e0 | |||
3c96d5e0d5 | |||
c5705705d5 | |||
03a1d68b74 | |||
50eff80ca1 | |||
96c118779d | |||
64c591b234 | |||
0e5c377680 | |||
6d758795af | |||
dedc9e4edc | |||
fa7cfc77d8 | |||
14692eed40 | |||
f0aab541f8 | |||
026293f773 | |||
5d5f1b86fd | |||
ba159ba971 | |||
e5b9bfb2e7 | |||
8cb8273e67 | |||
73d8343914 | |||
3960eb7d32 | |||
4004e0faee | |||
b47993b736 | |||
ca061080c1 | |||
f1bd9700f7 | |||
5f63c781b4 | |||
43e6f05ed5 | |||
aad5ca5474 | |||
cf2393a509 | |||
81c0a1c4bd | |||
6fc745e98c | |||
7579fff532 | |||
7ac2a23bc8 | |||
6c4cf085e0 | |||
b51f1f1d41 | |||
8d7dcdfc5b | |||
3fe518ff2b | |||
98d6904e4a | |||
d7d2d9f612 | |||
2a5d291bd9 | |||
e2a65a7077 | |||
671d3c1c80 | |||
6cc3587da2 | |||
9f9b5254a2 | |||
284e374ae8 | |||
4cdf669154 | |||
4332b62a62 | |||
7138425c85 | |||
b67844e74c | |||
cea285f5f5 | |||
1fd90e9dd0 | |||
c523765c19 | |||
cd527c44a4 | |||
6476023cf7 | |||
a01a48793c | |||
18e628e873 | |||
00f75e2d54 | |||
81207c6502 | |||
8dd3a02747 | |||
3db83a189c | |||
b6e9a54951 | |||
6c374f5f08 | |||
4320830a86 | |||
603e3e7e2e | |||
109ae5bae0 | |||
41cb8d7ec6 | |||
494483fd2b | |||
a6c8a37a5d | |||
87efa700ab | |||
e38adf6006 | |||
25ffc4c4b0 | |||
8211befc29 | |||
1dc7f80034 | |||
cb7ff81ade | |||
400a2f7201 | |||
c123558314 | |||
f287d9deac | |||
534d156b12 | |||
54d88e4dbf | |||
95969e87a1 | |||
e29126ca26 | |||
1b5c78b066 | |||
1c3402d081 | |||
6b3b119db0 | |||
66461ac500 | |||
46e840fdf1 | |||
7033e28572 | |||
0008b22d8b | |||
8f9bd9617f | |||
0f64ee6a5f | |||
c23bf2fd22 | |||
3ad559ab22 | |||
5f1074471d | |||
c04cee7ff7 | |||
4123343130 | |||
faec21d572 | |||
cb35fb8d0e | |||
213f03351f | |||
00be211169 | |||
90fc720190 | |||
23b3711f96 | |||
6aa30d334c | |||
54cb077b40 | |||
92847b9774 | |||
6e5716f097 | |||
6f7454243e | |||
45c39d078f | |||
385babb458 | |||
904b128afe | |||
dffffc784e | |||
40fb387185 | |||
63acf0a7b4 | |||
fce000206f | |||
f5e4171df4 | |||
0aaec9ae4f | |||
d25452a64e | |||
41d0f74750 | |||
22bb260ae3 | |||
d82ae31fc1 | |||
cf5c01a5b1 | |||
f2015eee80 | |||
c0f0462550 | |||
1f70589deb | |||
f8f1c3cf23 | |||
ed4dce2fb6 | |||
4d49486cc9 | |||
b7dd32274c | |||
d8e0b14dc4 | |||
8bebd7f042 | |||
90da57a806 | |||
b142407b21 | |||
10266f65e4 | |||
c49ee87857 | |||
5b04a17730 | |||
4ea0a567bc | |||
8aeec1d52d | |||
f39d2de0cc | |||
1ba08f4641 | |||
4b65315cdc | |||
903fae94be | |||
275351e19c | |||
35c233d4c5 | |||
e099a3f7e8 | |||
4313466589 | |||
d2a3acd493 | |||
516dd6bd1a | |||
44bc60021d | |||
50d5eb0621 | |||
3d3acb7a92 | |||
bee88b1c7f | |||
98174b7a37 | |||
5d03919b59 | |||
2357d167b8 | |||
013a26aafe | |||
fe9927d10d | |||
df4fd7df7f | |||
c8ff812ab8 | |||
6d0e255ca1 | |||
3105f314cb | |||
6db906d623 | |||
418677ef31 | |||
9c10965997 | |||
1bd778d0ae | |||
87155e346c | |||
52dd09bdf7 | |||
d344ffe370 | |||
4745ab64cd | |||
288ea3d19b | |||
8ade44c9a3 | |||
fa3a46498f | |||
953a2590e2 | |||
02b628653b | |||
3546f57a42 | |||
8d3bc6b6b9 | |||
c75ba0f855 | |||
d1603f1945 | |||
84c63f4f01 | |||
514080653f | |||
603ed22015 | |||
ef0752972a | |||
fd5b155ee7 | |||
40fbae8ff6 | |||
ce4a86fbcd | |||
54d7477679 | |||
6f7d901a1f | |||
5eb71fc6a9 | |||
8a3aba1634 | |||
bb8e6ef35e | |||
529e2054ea | |||
158b07a39e | |||
932531c8ba | |||
69c21454ec | |||
564e394ec8 | |||
f0e4e07c05 | |||
df932c6587 | |||
81c1a95166 | |||
bcf45c74a1 | |||
8b576fd2bd | |||
7fdd68d768 | |||
f825d7753a | |||
19cb6ad588 | |||
4a84084d9d | |||
25579fbedc | |||
59e1e51903 | |||
30ef5475c7 | |||
9804996db6 | |||
b774817ada | |||
8939096db6 | |||
df6d46de9e | |||
a325d814e2 | |||
cd1e8dc8cc | |||
377707d3db | |||
7ebc8c48a8 | |||
42bc04a0d2 | |||
4322222acc | |||
cce6a54701 | |||
68865353cf | |||
0e7f435921 | |||
20ba6e5fb5 | |||
cf94adb363 | |||
d74a23d5b2 | |||
750209b8bb | |||
31aaa6d1da | |||
823cd3862d | |||
741c23a72a | |||
28de461067 | |||
69c709b05a | |||
222a10891c | |||
cb2671a02c | |||
0a56631831 | |||
046d510134 | |||
90df092174 | |||
85bbab0e92 | |||
67db141203 | |||
c5ea8367aa | |||
f8adb508ab | |||
6613deca0f | |||
763b3c3236 | |||
718aca3d06 | |||
bf95cfb30e | |||
8df5ab8aa7 | |||
83efdccfe1 | |||
f1ebec641a | |||
a4521ac0bb | |||
c5f16276d7 | |||
03361e51ef | |||
85495c794d | |||
049b02cee4 | |||
05d2c1f0b0 | |||
3c9c39cb89 | |||
377f27b16f | |||
58321f3491 | |||
4e07f9574a | |||
da6f846a49 | |||
9ad356d66f | |||
836e8d2e28 | |||
b84dc8551a | |||
f7d502c68c | |||
9d2516a199 | |||
e7ad373d89 | |||
dea33a3c1d | |||
1f16380efc | |||
05a8232a8f | |||
0063d52952 | |||
2e82c1d40c | |||
820892d7cc | |||
0d2105dec4 | |||
480faca559 | |||
0975dbc3dd | |||
8aa02320e0 | |||
470518eb3a | |||
ba609f3600 | |||
ca659136e2 | |||
f1a6dc5332 | |||
4eaa7dc8b1 | |||
94510edd72 | |||
9ad29e8d85 | |||
07f3d27fb8 | |||
f2692e60f3 | |||
009623823d | |||
a32a3e25ad | |||
3e3be9ae6f | |||
3c648ff9fd | |||
f769b0b4c6 | |||
75bd626f33 | |||
f2471f0f68 | |||
d9b24f7705 | |||
a389983d7d | |||
82d3755e25 | |||
6ccc7e77f9 | |||
b62e4c0cc7 | |||
f6f0fbbd9f | |||
c13a90540c | |||
6fd729e285 | |||
8ad9692daa | |||
d02858040e | |||
3ee0fec729 | |||
ec063470d7 | |||
b2ed2bf810 | |||
f8a02a5c9b | |||
6685810081 | |||
53d40df292 | |||
af6bf11793 | |||
d5b5f0503c | |||
555cb40efd | |||
9d22fce53f | |||
aee0999daa | |||
1bdde1f947 | |||
319ce8c19f | |||
4e66f55d84 | |||
6826f1d605 | |||
0161520b33 | |||
12cd8a7bea | |||
2d00a727f6 | |||
b123f4f948 | |||
fd9a8d1551 | |||
6bc1150ad0 | |||
45cce1d19a | |||
412349ac58 | |||
000f4386a2 | |||
5d3329b1ef | |||
147366bc0a | |||
13804f80de | |||
1d354df1f8 | |||
1b42b9a08e | |||
535fb2c4d6 | |||
98a07da39b | |||
8bf5ba2836 | |||
798e1abb58 | |||
90a4f622d2 | |||
6812823b55 | |||
7ad9abf9bc | |||
cb52be433d | |||
1f2b0ad698 | |||
6667ff9330 | |||
5bf091149d | |||
be0df38453 | |||
fcfb3d2df7 | |||
1ff8136f98 | |||
182e19eae3 | |||
9908e115aa | |||
811c79423f | |||
cf4c1605eb | |||
e0b901169a | |||
3f1548ae0e | |||
3526d00a23 | |||
e8b0a7c6f0 | |||
d4f2059b78 | |||
a4502f44c2 | |||
18c436c2bc | |||
b77fb05908 | |||
703f7698c1 | |||
69bfb55397 | |||
180ed0cc1a | |||
b174f82261 | |||
9406022e70 | |||
f4a814b5e6 | |||
94ddc8bbf7 | |||
d6c7b4e813 | |||
ad0493390b | |||
5aa1c340dc | |||
47372c2fbd | |||
ae9e8dbafd | |||
b7d82354cb | |||
b3d743635c | |||
f2932c6d03 | |||
93436b0940 | |||
f96b135ef7 | |||
bfe7e3afed | |||
75b1eaed0c | |||
7fb4c8358b | |||
95f6860005 | |||
5b3431b268 | |||
e6872aba75 | |||
11cbeb8f96 | |||
886b372ade | |||
534328f16d | |||
318d11481d | |||
5d425ecc02 | |||
c225ecbb55 | |||
0b4807dc1f | |||
d33de2e427 | |||
1191c33c2b | |||
52054469cd | |||
a90eaafa70 | |||
bbd9e4de9b | |||
8abe6b6732 | |||
9b9d439fce | |||
62d1bc87ae | |||
51ed39804f | |||
d12110b47b | |||
accf0cd40e | |||
e936bc4c60 | |||
f724059b88 | |||
1e702ee40f | |||
a9302468e7 | |||
3b9d822d72 | |||
f3a7de6b76 | |||
a807b231a7 | |||
a2d0d5a71d | |||
d59a06344a | |||
e884341795 | |||
3a068970f9 | |||
c343036d3b | |||
1043d29dd5 | |||
6505a62801 | |||
7e016c44c1 | |||
7c5047b2ac | |||
961285d6ab | |||
e1b37f3cd3 | |||
0c24827a52 | |||
e6eee82fb9 | |||
c5cf78205a | |||
37b4f606c8 | |||
5824047ffa | |||
df18d8560d | |||
3dccc38f42 | |||
3531c5bb8c | |||
cc41b039e6 | |||
7e0e1ec51d | |||
ab41816265 | |||
2c95973446 | |||
89d8f9b829 | |||
0bda885bbf | |||
f613b03efd | |||
3c87e5d31e | |||
e26827b849 | |||
8eb10e991f | |||
f6f32914de | |||
9ca74cd009 | |||
d50bd096a4 | |||
1840505a0f | |||
29e532c096 | |||
0f0cbd4c1f | |||
0ece0b5b27 | |||
74d4a98864 | |||
17691ab515 | |||
f619a04fe7 | |||
3a6657596b | |||
5627b4a9c5 | |||
6a4fb6a271 | |||
46a13c8767 | |||
3bbe33132a | |||
b48540dc32 | |||
4e0a08345d | |||
9b1e0eb57d | |||
4cbae0a751 | |||
68c2833552 | |||
dbe14c6be5 | |||
4593538fc8 | |||
7c85462ff3 | |||
8db4a2a5b9 | |||
2dce08caf1 | |||
f5729d9a7c | |||
0b2044e9a4 | |||
03b66ba7a5 | |||
6c082403c4 | |||
29c3dc40ef | |||
1c91d2f242 | |||
5fe9e30f39 | |||
4eb9083ddc | |||
b28f682ad9 | |||
eb079c8060 | |||
c0f9ccc5b5 | |||
51c39ec681 | |||
10436ed70c | |||
775236a1b3 | |||
b9503ff15f | |||
b4dff181f7 | |||
737fc1a2a4 | |||
bdff8591aa | |||
27c3775f99 | |||
bf0a577fb9 | |||
954d4d701a | |||
ce2d58bb7d | |||
7af116fb00 | |||
0357921284 | |||
86974b046e | |||
a04a6f1e0d | |||
37420405c7 | |||
acf1946dac | |||
a52574b026 | |||
5d14724e66 | |||
d582bf7f1f | |||
7d79abb607 | |||
c81cb59b4b | |||
ff03dd22fe | |||
aae892dfd1 | |||
2680dba0aa | |||
832a61f886 | |||
cf4df19986 | |||
c156034069 | |||
f24211e8b5 | |||
e61d8e4dc8 | |||
403279e926 | |||
70983c7269 | |||
086a7e19f0 | |||
42f9eccb17 | |||
3c937532f2 | |||
863027cbe8 | |||
6b8fe283f0 | |||
7983977156 | |||
21cb459899 | |||
1b3ff96ffd | |||
2f37cb31d9 | |||
e5534cd1f3 | |||
42ceaa0015 | |||
90b330d4ba | |||
4f0ec908ec | |||
bd1ea64d02 | |||
649753e97e | |||
fc656b6927 | |||
3be18b58bb | |||
22aaf56855 | |||
7537ea1ef5 | |||
94cd831e8d | |||
2078133493 | |||
ffcc58cb3e | |||
8c7fd3327e | |||
f60562c5a2 | |||
18cfe219fe | |||
129e959a3b | |||
e1b6020b76 | |||
d5c6a1b4d1 | |||
79ce7eb1fc | |||
b1ffc8ddab | |||
5b8d025440 | |||
3e11d94829 | |||
6b6d6a01dc | |||
82287e0407 | |||
c5aff7cc1e | |||
b16829b0f9 | |||
f27716656c | |||
37a6ef95f0 | |||
475761b295 | |||
0b251fa754 | |||
30cf73a22f | |||
884ac73078 | |||
ef6cbdfa2a | |||
718abaae0e | |||
62a402d05a | |||
ce5bb29c44 | |||
d535f73a58 | |||
d38696f411 | |||
a3173b5371 | |||
54fb799d95 | |||
565202c990 | |||
63c21c53af | |||
d0b6f0124b | |||
b266068644 | |||
74e7c13a17 | |||
3cfcc83ea9 | |||
ee94be624e | |||
2fe3dc5960 | |||
fd7338d3f3 | |||
ed185f047f | |||
d384d991fa | |||
9913080a82 | |||
ec157b766e | |||
469ef3e06d | |||
107b470289 | |||
e0635955df | |||
8b14b946e2 | |||
f7b912fc9d | |||
9fbec3793f | |||
5ec4cbf1cb | |||
e4449a0ba3 | |||
42dc3ed03f | |||
f6ed2036b3 | |||
f8bf71e152 | |||
e0380960fd | |||
64ba5e4ed1 | |||
733619ca74 | |||
9f9c829bc5 | |||
236764adf6 | |||
a80b425551 | |||
d7032d975c | |||
96decbac27 | |||
0fb6a2836b | |||
fe36471b8d | |||
6b28af6cc5 | |||
6306fb564b | |||
cdccb25fe3 | |||
b6452215c1 | |||
f1028fa66d | |||
9d2f0e4dc8 | |||
f997529cd4 | |||
495103f72e | |||
d80dee2a54 | |||
788fa40c2a | |||
ae75585b52 | |||
ff07714e8c | |||
f54fc16718 | |||
61a2355618 | |||
248920a221 | |||
7298f9c273 | |||
b2ecb9ac09 | |||
f738d7566e | |||
672f5cf160 | |||
1d167f8fda | |||
460e83207f | |||
75116364c6 | |||
f7931c2ee2 | |||
dfc2b9c76a | |||
22bbf1bd1f | |||
10aac4fe17 | |||
42bc91463e | |||
b4fa6e120a | |||
2c744da9f7 | |||
ffaa47bf54 | |||
63c4469475 | |||
c1490cd627 | |||
1a390b6043 | |||
fac33498db | |||
31e84780a8 | |||
f3f8f3574a | |||
7bd26ce468 | |||
bcea19b957 | |||
5079ce8d64 | |||
f231a33f6e | |||
4fe497cd68 | |||
5655a33515 | |||
92cda68480 | |||
f41426f394 | |||
87db723008 | |||
8dc3267925 | |||
709736d3f9 | |||
12f0d51c0c | |||
2e9403a324 | |||
ba17efa381 | |||
b8e0c8ebc6 | |||
1b05303250 | |||
51095c5a27 | |||
a02f67ed0e | |||
11f8d25d94 | |||
4fbd5abe41 | |||
d524935b67 | |||
6d5c629b43 | |||
3a7961834a | |||
95842ee25f | |||
371c839573 | |||
1b8b044b52 | |||
a988111507 | |||
c56db0408b | |||
2321d9c065 | |||
ed085630db | |||
74d5c7c1a4 | |||
813ccc1381 | |||
b65f4c9536 | |||
012d8bb468 | |||
d7a137ad13 | |||
073aaf9b3b | |||
871d647c93 | |||
0ce3049579 | |||
de20258aa7 | |||
41c5e523b2 | |||
197be9cfd0 | |||
5b50b806ec | |||
62c59820cf | |||
0cf1fc72a3 | |||
5ce7874280 | |||
ba2b5c3a65 | |||
0a9081cb87 | |||
eea1e3b800 | |||
70364884a9 | |||
ea7f03770c | |||
bc1a7d2890 | |||
732bc53692 | |||
4055e34320 | |||
81b1406290 | |||
538092b727 | |||
4df4b43900 | |||
3e3b92d4c1 | |||
c7dc115365 | |||
e42050cc8a | |||
df17f5e899 | |||
a0045ece07 | |||
4c013e59f0 | |||
09d607f39c | |||
9418c62d95 | |||
ef50e5595e | |||
02bf086c09 | |||
77932061bc | |||
44bf32e729 | |||
0c986ba4d0 | |||
a28193430c | |||
0bec0046bb | |||
a96519cbdc | |||
458c2f38bc | |||
dc5402349e | |||
ae289c923c | |||
e0ef86340f | |||
1ca2c59f2e | |||
3ec92acfe7 | |||
656bfd36f6 | |||
562ae676a5 | |||
72292f4e03 | |||
536da704fc | |||
a0e03c41c0 | |||
a1053a4c5a | |||
9f441a9678 | |||
7870cf28e5 | |||
9939367db7 | |||
1210c3256d | |||
2e8d04aad0 | |||
3a0e4546c2 | |||
cd2419137d | |||
34ac8b3ec3 | |||
2837236d81 | |||
bc8336a4b1 | |||
397e7f0363 | |||
c5bbe42b57 | |||
c9105e525e | |||
1bed7754e0 | |||
5978882378 | |||
8ba51c7900 | |||
6d160a7b7e | |||
32409a361b | |||
2ceefea5f3 | |||
485f156e57 | |||
f794e49bb6 | |||
46f448dfba | |||
710156b9f1 | |||
6dcf34acdc | |||
d2f674e08f | |||
ec8cb056bf | |||
1893871a99 | |||
8837f06e4e | |||
5346dfc782 | |||
ddca838e46 | |||
45b0367d14 | |||
dce86edff0 | |||
84e91ec3b5 | |||
05b6969ee5 | |||
3390e84a9f | |||
af949f5cdd | |||
7707af08e3 | |||
5db4fabcad | |||
cfca82ceb3 | |||
a1130dace0 | |||
95a0bd61a9 | |||
b324778be7 | |||
950f921c09 | |||
9dff1bac83 | |||
c17f6e37e5 | |||
e0e26a37b5 | |||
15a0c03664 | |||
7642e75b28 | |||
4b36d1e3ea | |||
20525bec29 | |||
430369feb8 | |||
5ac3e5c958 | |||
2e1c123c05 | |||
83c5264598 | |||
abc2a529fb | |||
c638fd9056 | |||
1dd96898e1 | |||
2cc9b0df06 | |||
3bd4ad7c93 | |||
a8ffdeca2b | |||
59b15c5f08 | |||
59cf8f678f | |||
088be050b2 | |||
5d5fcae501 | |||
970ec8187c | |||
76f66148db | |||
6bdd6ce571 | |||
dd96e1819d | |||
07702d3be7 | |||
b9dfcf6d2f | |||
f3f0652d2b | |||
aae60334d1 | |||
b38af948b9 | |||
06de728aa7 | |||
87384182a1 | |||
f583e617ec | |||
a2716f5cf6 | |||
55f928f845 | |||
2343aad088 | |||
dcaa907fed | |||
adcdf28d64 | |||
f28a7b9d08 | |||
6505b0c065 | |||
88ef02474f | |||
9ec32b2561 | |||
a5dd6b6cd7 | |||
46cc325f7c | |||
0fadb5a2be | |||
8b897ac714 | |||
a80b820e94 | |||
4efbf22089 | |||
5c913149c8 | |||
9265c319a9 | |||
cbe6eff2fa | |||
1f3d18ec12 | |||
89255e34bd | |||
a7b8092296 | |||
1feb630520 | |||
9f202caf93 | |||
651e511ff0 | |||
b46aca52ee | |||
0eae9355e6 | |||
4878f1a438 | |||
f986b4cd56 | |||
d5c6704475 | |||
fda9ca1e34 | |||
01c4ed232e | |||
dc8109658c | |||
8ce8055aeb | |||
a71b743ee3 | |||
c50e9ac418 | |||
7973b01e81 | |||
6a5e9a59df | |||
bb62c62a03 | |||
9cc3d9d4ce | |||
b977ac6df5 | |||
256fc322a8 | |||
33bf85a387 | |||
1f0fc61b53 | |||
89c945ecc8 | |||
c15962c6c1 | |||
9c2a3231c5 | |||
80840f1fdb | |||
7d02e1f866 | |||
d93cb751b0 | |||
c07fff7503 | |||
7896dd19c1 | |||
f5f2d33f93 | |||
4331eaae2e | |||
d5d4f87236 | |||
5d49433326 | |||
381d7413c8 | |||
e70a5a47ee | |||
6be7eed878 | |||
a6ac832f8f | |||
104863846b | |||
5883c30b84 | |||
cebaae76b4 | |||
d886d32bd8 | |||
8440c2819b | |||
8114d8778f | |||
f36c3a3f6c | |||
46c6cc2d2b | |||
ada5e88eb9 | |||
b724607e31 | |||
c3ea303a37 | |||
e89a10945c | |||
8ddc89fa01 | |||
a47bf72b07 | |||
34460dd77a | |||
c125c96e88 | |||
d2fd0fd8e8 | |||
74a875bdce | |||
edaa66f622 | |||
c392db7e0d | |||
6ac073e779 | |||
58d9ceda4b | |||
3781c64d41 | |||
4166d9ab7b | |||
435273e08a | |||
35a62d9787 | |||
75683039c5 | |||
1a609612f2 | |||
121a7a9e23 | |||
e593faf245 | |||
ec5bb944b2 | |||
deed49574a | |||
7cc39cd357 | |||
a714d5966e | |||
2b0252d4ae | |||
c78db5459e | |||
a27564ed70 | |||
df8df41621 | |||
d5a0d4b452 | |||
357b6ee991 | |||
4d2b5c2f42 | |||
f705cf09bc | |||
29f7ea752f | |||
9b7c8ea22d | |||
199a7df807 | |||
5186ad95d3 | |||
0546345182 | |||
90feaaf2df | |||
6d27ef5eea | |||
e4e8a51e5c | |||
3ddf413332 | |||
6eb36fb053 | |||
58239ff98f | |||
6e841a3b7e | |||
085e067fc1 | |||
c45fa016c0 | |||
16477a8f6c | |||
04e4900415 | |||
322f317a5b | |||
ea5020e188 | |||
cefa1662ef | |||
2a949fcb86 | |||
445f9e5f71 | |||
5a25ce8c1b | |||
670cf8ee07 | |||
6c5f6e8900 | |||
4ed4fb2314 | |||
f16989bea9 | |||
55d4064335 | |||
3b38a4c690 | |||
ada595663d | |||
b2de01b076 | |||
f3acf35aea | |||
3da1d6a464 | |||
b9df10c8bd | |||
ec1f73c827 | |||
cdc9f93f71 | |||
bcebb1920f | |||
81848e05f1 | |||
5ae69c079a | |||
0199d8a74f | |||
f49ad2ee03 | |||
7ed993b54e | |||
9934537e19 | |||
00d42d296e | |||
ad74fedfba | |||
730f714e97 | |||
3bec4a80b3 | |||
a84e4b0e07 | |||
198139feb4 | |||
de11017552 | |||
6fb837c529 | |||
c0c3892064 | |||
1a35fec134 | |||
f1247d2224 | |||
7992b7eb89 | |||
cd893e18d2 | |||
a5c8b166fe | |||
72a9b98ef0 | |||
cf022524d1 | |||
ebb0596c1a | |||
3de681d2d6 | |||
f7b0ba88da | |||
c95c81d42f | |||
9407596b12 | |||
c294c2d1df | |||
bd36f8e220 | |||
3a168ba6dd | |||
1919069b12 | |||
ba677a8cb7 | |||
e62e1d9701 | |||
b3330cb0da | |||
7d128c79a3 | |||
3cff23dae2 | |||
c3f0139f76 | |||
563fe8d515 | |||
38e20eb148 | |||
36571c5e22 | |||
c8eca4fb85 | |||
0e207aba6c | |||
45d1319891 | |||
39b7ac90d4 | |||
ef87bdf18a | |||
433a802c6e | |||
6a18079953 | |||
b937d33436 | |||
f7244fbf68 | |||
4e80d1fc79 | |||
b2f48eaeb8 | |||
160dd09fc2 | |||
80eea05deb | |||
5e89ba7079 | |||
ff7878217d | |||
807da6a035 | |||
4e2a958896 | |||
3ee0ec7cd0 | |||
22a2b7ac46 | |||
aa7c910e26 | |||
24a4bd3a1c | |||
fff52cb247 | |||
219c5b323d | |||
14278a9e35 | |||
dd013209e8 | |||
96d5438633 | |||
391ef64c22 | |||
d45a62b3a6 | |||
976e550aa7 | |||
668b19d119 | |||
5c48f0b458 | |||
689fe1e2c7 | |||
7d440402ad | |||
6daa457838 | |||
49d317b19a | |||
1b80ae0fca | |||
a113ecca8b | |||
61144f7a21 | |||
574af2c795 | |||
a4870d4834 | |||
78bbcac0ea | |||
d4b346b7ae | |||
ca9b2525c8 | |||
bb1c387a98 | |||
38ce37b6fd | |||
7fdc81236e | |||
fca40c1c6b | |||
52b3a54e4b | |||
d5d5d66e03 | |||
0481ae187a | |||
9de6927c3f | |||
30b01ef053 | |||
03b75bf2a9 | |||
f3f628410d | |||
9901ecda49 | |||
39becf607e | |||
f5955a4738 | |||
e018b30875 | |||
2dbd775cf3 | |||
a5051327db | |||
8140f5136d | |||
f04703f09b | |||
be7f81421a | |||
17317ea308 | |||
cb32711077 | |||
2faf8332ee | |||
e0e3d4d8fe | |||
ba81ad1ac3 | |||
eefb259ddf | |||
9b8add1961 | |||
e186523878 | |||
021e6c02d7 | |||
cba3d68063 | |||
7e2d78bab5 | |||
4b12c85d91 | |||
0ebf04a021 | |||
d55f47077a | |||
11df4845b7 | |||
7f438425aa | |||
c470f05abf | |||
141e94369e | |||
257970c27d | |||
67ac3da8a0 | |||
c1e5179b5f | |||
7a651bdc53 | |||
f33f596584 | |||
c8d8046412 | |||
4d334b645d | |||
58d3779efb | |||
3691f3a296 | |||
463b4fbe0c | |||
9f1c79a5ec | |||
70573b6f31 | |||
6ea1234a3b | |||
434f639b0c | |||
bf04becc9e | |||
e8ee4497f7 | |||
b2082bfde7 | |||
78984eea3a | |||
5c96b1c628 | |||
8422e3ac01 | |||
cfce54fe46 | |||
a7c9b2f172 | |||
eb31a951a1 | |||
ccfe605920 | |||
878614ff68 | |||
25e23e50ca | |||
64c51a70a3 | |||
e4296c48c8 | |||
dd3848d7b1 | |||
56ac1a0813 | |||
cbe5af235c | |||
f932ffcc5b | |||
0a50c5bf40 | |||
e416e5d301 | |||
884bd85495 | |||
94067f34cf | |||
3227859992 | |||
01139c3b50 | |||
ee3e65d759 | |||
c85867395d | |||
bf2ce54076 | |||
07de285299 | |||
8c194cd245 | |||
8cbec3d5a0 | |||
cdf05e74c8 | |||
b98b4f1027 | |||
fc11dfd6b4 | |||
483a5b6cae | |||
df1b7f1656 | |||
a566d1c5de | |||
11c8237d8b | |||
6dc19c85a8 | |||
6e07c11f65 | |||
8da6667816 | |||
81fedbf03c | |||
0516055b31 | |||
e3f8d99087 | |||
22aebc2215 | |||
3653e9d5e3 | |||
40f16b6d62 | |||
a61daa40dc | |||
ee67b5f1ad | |||
aa3633d2d7 | |||
7b805a38b9 | |||
c8d8dda79a | |||
c440f33122 | |||
b0c866bfaa | |||
dd578354c4 | |||
fdac978c84 | |||
3b81ada1c3 | |||
87bcefd08a | |||
4ee29b388d | |||
8a6776731a | |||
bfa5fe1598 | |||
ead59c0246 | |||
cfeadf858e | |||
7534eaf006 | |||
8a81aaaa0a | |||
b544661e81 | |||
52dc9068e5 | |||
4f1ea712da | |||
849b92665e | |||
d193ed9eeb | |||
ee003cd9ee | |||
127b094c41 | |||
b2285be5bc | |||
6ede02bb84 | |||
821c424b66 | |||
5450e0edf3 | |||
e05ccc0e55 | |||
4f3786c2e1 | |||
107977f3d1 | |||
813663485d | |||
64585d8f78 | |||
756d933d1a | |||
83deccf266 | |||
aaef448959 | |||
7e96077ed7 | |||
c44f931059 | |||
15084c8d6d | |||
822c5a530e | |||
6eb641ae56 | |||
9eb14e6b9b | |||
7cc42269a9 | |||
c45442760c | |||
83f0611200 | |||
d95625ed88 | |||
5622bcc563 | |||
deb9c98630 | |||
2c1e887c8d | |||
4a13d72997 | |||
2d5820e910 | |||
6cb857b895 | |||
590875d022 | |||
8f30237765 | |||
cb0339b492 | |||
e427174ff0 | |||
fc4c57f0d9 | |||
9ad4ae5340 | |||
0f48e0fc06 | |||
37ad1b40d8 | |||
514e7ae6a0 | |||
ab2f3bb5bc | |||
34230bfcf4 | |||
c390e211ee | |||
b0d69db878 | |||
b373beee21 | |||
8c99edd3c5 | |||
8036272e87 | |||
6f50809457 | |||
bb386a1162 | |||
80054e4db2 | |||
1630a23fb0 | |||
4e75419e08 | |||
089018015a | |||
feb6f285ce | |||
cb12c51afc | |||
c5c426ecbc | |||
74f7039abf | |||
57b905be24 | |||
34794cc4af | |||
38f59fdf39 | |||
527c1113f1 | |||
04dbe28793 | |||
968366c2ae | |||
7f5dea28bb | |||
d4979974b4 | |||
9539230915 | |||
25cfa26e7b | |||
0ff8891c66 | |||
58d2c15ffa | |||
82699cc297 | |||
08d008a5aa | |||
9e17ff884f | |||
1c567232e3 | |||
cba2608c1c | |||
e5c42f68c2 | |||
02b4468bcd | |||
746f6945da | |||
5cab4d8864 | |||
5cedfcbfaf | |||
c06abd9b6b | |||
e08d97825d | |||
d61323aa6d | |||
5ae044db93 | |||
c6e4fdac7e | |||
9669377b06 | |||
c8c3fe1023 | |||
85bddbed86 | |||
318a2a429c | |||
07359865c6 | |||
2fd7338cd3 | |||
ce3cfa212c | |||
b29c99656e | |||
45b0762096 | |||
aceafb28f6 | |||
928939cbe3 | |||
2462b8e524 | |||
263a72879d | |||
70620d5137 | |||
79d5beff8d | |||
fa3caf091a | |||
93707560cb | |||
5c6f325071 | |||
b9a17f5999 | |||
ab23f542c6 | |||
fa98bf1ee7 | |||
3cc987a5b4 | |||
d1a1b8b6e8 | |||
0d08e082be | |||
386fb28a35 | |||
79b79b752c | |||
a116778402 | |||
4c1c26a0e6 | |||
9e1653ebb4 | |||
99dd9874df | |||
24193163e1 | |||
94d164c0f2 | |||
efef2e95ab | |||
5efa725e92 | |||
42c00213ce | |||
b7d1b9ac61 | |||
52d06ed814 | |||
46a1c855a9 | |||
31dc82b1a6 | |||
4e27e132a0 | |||
a5b0b4800a | |||
e6244c937a | |||
3cbf8d4993 | |||
f3279a0697 | |||
8cac61f0be | |||
236c196e68 | |||
6c09efd630 | |||
cc92e1b0b6 | |||
c90f2c3ac6 | |||
6bdd27a08e | |||
80ff0b1418 | |||
a8943ce1ee | |||
71d35dc70b | |||
9daf2a2996 | |||
f5d6aea942 | |||
5850447fd0 | |||
e12a7a4415 | |||
81d84b8d02 | |||
bae0a0530b | |||
cbf4159c7e | |||
4a1d082614 | |||
fd8b4c5368 | |||
5872c34315 | |||
b60fe08d44 | |||
6a51eda361 | |||
96e8217b00 | |||
e6cb6cae11 | |||
980f03dd20 | |||
20c281d6f8 | |||
66f9fed2f2 | |||
68b7aa0a4d | |||
f916ce8752 | |||
fdbd8d9d2b | |||
4208c2c72a | |||
5cc91965d0 | |||
c74f852364 | |||
c1b3a3adb4 | |||
7096f02b88 | |||
70a11935a8 | |||
f601135cc0 | |||
884fe0d574 | |||
ffcbf97dcc | |||
f55fc51e9b | |||
df0f9259c0 | |||
bb7a321c6e | |||
2d69d63efe | |||
479843f56b | |||
6e1639551b | |||
2367903ac6 | |||
30607c34a1 | |||
817947c928 | |||
29926a59bb | |||
d92ae530d7 | |||
e0e428ce38 | |||
d1db7a0e23 | |||
c27ebde575 | |||
a99cd16422 | |||
1f6b8f9d2b | |||
a33b804923 | |||
f527958cb3 | |||
b1bdc6f745 | |||
8dacbafc8b | |||
70fa92f22c | |||
3482076a20 | |||
f7239f7f8a | |||
20ba787c00 | |||
669eef92eb | |||
c6d9edb78f | |||
347ae0a9ad | |||
dbd01d35e6 | |||
b24c09665f | |||
fa96ebd382 | |||
52d43f843b | |||
90376749f0 | |||
5cf2a8b5fc | |||
f72ac94c11 | |||
bd3a693e70 | |||
298871e207 | |||
ce958f4ffd | |||
2de150bfc8 | |||
40970a1a87 | |||
8aae652be1 | |||
37a117d2ef | |||
debc1659e1 | |||
23e411c42b | |||
88feebe499 | |||
e8b871ac72 | |||
9f30c6d94b | |||
c4c1e75de8 | |||
c1763cc4b0 | |||
ee096edfff | |||
464b9ebc95 | |||
7705f290ca | |||
7439fd6bcb | |||
6fe626ab9a | |||
a12f892841 | |||
aa3ea79f94 | |||
ef53455b66 | |||
ba46ff6692 | |||
0e916244f0 | |||
1e4ee02cbc | |||
cedc7754d9 | |||
fece9e207b | |||
cca052ccc9 | |||
5be9472912 | |||
f60b09568c | |||
be765f8d88 | |||
8d6aecd944 | |||
aef5349aee | |||
ac993aa31f | |||
fce323b945 | |||
5558f3d2cc | |||
08f8623cb7 | |||
f8a137a26e | |||
3cba359d38 | |||
b8d7aedb2c | |||
55c7b291e1 | |||
472d931b4b | |||
ce892c9e77 | |||
e14b998da3 | |||
2c9452efaf | |||
97a7af855f | |||
5be8545edc | |||
0a04c3a2a7 | |||
dcfc15a0a1 | |||
841c2e9166 | |||
07392d493c | |||
acd50969e0 | |||
074b53eb6b | |||
c4cfec1e94 | |||
b0269e6dfc | |||
43b9d9484d | |||
69bbb29328 | |||
577069cfb4 | |||
fe94c3609e | |||
173aed7fd8 | |||
335bec68fb | |||
bbb7e9f5c7 | |||
086304f7f2 | |||
bd7065eece | |||
15aaff7c1c | |||
e048bce13e | |||
ddfb449b28 | |||
5322155b19 | |||
45ce72593a | |||
b813c867b5 | |||
f7d7d76ee8 | |||
7e5076b068 | |||
dbe0553b4a | |||
9be48f1dc4 | |||
6043444e4e | |||
487e352642 | |||
cc5f82bfac | |||
4d4dfab388 | |||
b83f9be1bd | |||
6ae3b183fd | |||
f12117c532 | |||
70768189ba | |||
30b266622c | |||
25b306b7e1 | |||
9af1b00df5 | |||
51c27e2748 | |||
b9e2c3524c | |||
3f6cc17818 | |||
5909af9878 | |||
64576f4c4c | |||
21dbd28a2f | |||
b57fee1a44 | |||
cabd887866 | |||
863a168cb5 | |||
5ee4fb3522 | |||
bb8ac9b99a | |||
2f10fa8b61 | |||
46a8e18841 | |||
6c53e68a52 | |||
392452d422 | |||
99ed0b6c2c | |||
e6d057fe6d | |||
9ad6eb11a3 | |||
32c2ad2bbd | |||
f2ca9a6b31 | |||
50d40257fe | |||
d90eff64d0 | |||
e6dc34fe10 | |||
745c331311 | |||
1ea2e85415 | |||
4a2df30f92 | |||
922220c11e | |||
56d5035c63 | |||
4abf3a20c6 | |||
5912ef3b45 | |||
9931c9a286 | |||
1da834f650 | |||
fb677a7489 | |||
404796d4b2 | |||
5b9bfe8891 | |||
779bc2c63d | |||
cae1ba7cd8 | |||
8ce78dcc54 | |||
afe088dba1 | |||
e899e31745 | |||
dabb84f62a | |||
9b8096c699 | |||
ac5b74301e | |||
609b30110b | |||
35d200356f | |||
0cd1d7aa7e | |||
ade7526f5f | |||
a7b1700d42 | |||
c0b8c53e69 | |||
e86fbc697f | |||
e5622ce824 | |||
99d9868116 | |||
107fa6b4f7 | |||
9062d28704 | |||
e68dcea6bc | |||
787c5a515f | |||
ce2df4b36f | |||
fcb9733df0 | |||
245928a064 | |||
589d160515 | |||
380e76a2e3 | |||
9ac6114b63 | |||
d558ff305a | |||
89aaac3a70 | |||
456999eee6 | |||
16e3b786fc | |||
126bbd67f7 | |||
38e1d44dbb | |||
9fb80a2687 | |||
d5d224d89a | |||
4708ce4226 | |||
a0580946dc | |||
e68fd7c1e3 | |||
369419870e | |||
0938f80b41 | |||
9f462dcc27 | |||
96008d3bb2 | |||
c05f744ec2 | |||
3df31579a1 | |||
f1d3481a29 | |||
cf3aad9c41 | |||
7b1e68bfa8 | |||
82256a2fe8 | |||
016b3448e8 | |||
2dde26e485 | |||
2999afe781 | |||
bfc5a6488b | |||
4af22d663a | |||
ba8322aa5c | |||
e4bd82190a | |||
695734636f | |||
bdac2a5f4d | |||
f8ea6212c7 | |||
5e9b26dbef | |||
67c99369ab | |||
d35c2db41e | |||
dff5fea976 | |||
ab6c7244fc | |||
353b51f11e | |||
76050880f1 | |||
396a7994f9 | |||
e29259cd55 | |||
79a728d7d2 | |||
98444bd865 | |||
3f75e1cb1d | |||
4f327120ac | |||
cc8456ec6b | |||
f8ad1a052f | |||
372ce588cd | |||
12632ec404 | |||
e777c26a14 | |||
1d38248194 | |||
d52868c6c5 | |||
29c1639b1d | |||
653a953d2f | |||
9f5537d936 | |||
21a7af535c | |||
a241d3f187 | |||
8f045af867 | |||
6d4efc0443 | |||
e2e6d00064 | |||
e682c3e9b8 | |||
fe347262e9 | |||
c993209b76 | |||
2cf4d5f8ec | |||
c6ab9718ae | |||
3e3ef03855 | |||
c2f37716e5 | |||
e9bfd43ff7 | |||
2958ffa73f | |||
3d11d044d2 | |||
7eb0b1c69a | |||
8d39a9ea61 | |||
cb796dbdfb | |||
4254c20eda | |||
094b57bb23 | |||
9ca4f19aea | |||
a29d88c313 | |||
a1ed8154f7 | |||
6c45a990ef | |||
8dfa3393dc | |||
d12323396f | |||
48d34741f3 | |||
76203018e9 | |||
7956e6f04e | |||
668342b470 | |||
0a0ce74105 | |||
f6a3fa55b1 | |||
718a9a3559 | |||
5485c5aaed | |||
afcdf4b9cf | |||
a3f5ea3598 | |||
fef60a9da0 | |||
576867605d | |||
d1626d20bd | |||
c890aa18f7 | |||
6c7d040439 | |||
d03ae34b61 | |||
b9547adce7 | |||
7f32c6464d | |||
209a1650e4 | |||
b142e2a7a7 | |||
6010ce0dc5 | |||
a7a331a26e | |||
fda2c116be | |||
d2f3dbaa29 | |||
e9d4793b1e | |||
13c7efa058 | |||
1598d65824 | |||
028e086960 | |||
04b39294ba | |||
3a446c410c | |||
35edea2141 | |||
ce1a4857cc | |||
dfdf739282 | |||
7086b1e65c | |||
f2d445d27b | |||
29d362a6e0 | |||
c8adc4e356 | |||
8467daa0ec | |||
13e14b712e | |||
27dfe30fe6 | |||
d89a541a8d | |||
42350e689d | |||
b7d5fee995 | |||
fd099166c6 | |||
b4be28b9bb | |||
19a8d51bf3 | |||
5d1aac3c53 | |||
87b0d3fe11 | |||
98891a036d | |||
b142a6da5b | |||
1c0139c5f4 | |||
1b7ae4321d | |||
7f991ed897 | |||
5ed7eb9d53 | |||
c00f96c7ca | |||
81333515e0 | |||
be3c9abcfe | |||
177f17450a | |||
150a3adaaf | |||
76146e0f17 | |||
4500e345b3 | |||
e885f3c26a | |||
e6e92f2b0e | |||
03b48554b1 | |||
f229574758 | |||
7b446dd30f | |||
a5be974f1a | |||
952615eadb | |||
93894f62ff | |||
2051de51b5 | |||
2ba3de79d8 | |||
d35c985d2e | |||
b18466da84 | |||
90714a93f3 | |||
990cfb7b33 | |||
aacf7938ae | |||
2e0f818905 | |||
63b6c6685c | |||
610b971117 | |||
318f657c31 | |||
482d3a1d76 | |||
b516dd970f | |||
d9463620e6 | |||
385c452ddf | |||
a89df42561 | |||
08cd5d52fa | |||
d0e668e1d8 | |||
eeb95f89e1 | |||
e4e0c27e1c | |||
b638a6ae95 | |||
74b98af8e5 | |||
6a474a0125 | |||
224304813a | |||
4caf06bc99 | |||
15593b5c09 | |||
e7e56eb1e3 | |||
43bf601f12 | |||
d5109f024b | |||
7f441f5b87 | |||
0aac85dda1 | |||
4777a45722 | |||
29e6e170cc | |||
01db80d19a | |||
8b28ed67ae | |||
f35a30d371 | |||
1a8de111a3 | |||
9bb62e1bba | |||
b2789fef0f | |||
46fe7e77b3 | |||
99e1c13e80 | |||
a6e65dfc7a | |||
1471eddc7e | |||
89fd84d916 | |||
0e17eee096 | |||
81f1305270 | |||
2ec4310104 | |||
24e4db676a | |||
6e21a9829d | |||
4e99e10cbd | |||
500a7eceab | |||
1dad35ca76 | |||
8b3093e758 | |||
a406aeb3ea | |||
970e4b020e | |||
a4f4f2891c | |||
a6b13487f0 | |||
56ae4e5b6a | |||
54c26b05fa | |||
bd376d5217 | |||
2592c69021 | |||
4a2b25e841 | |||
ba4af1a890 | |||
9b17cde019 | |||
7a8c963722 | |||
82d1dbf173 | |||
aefb8b353e | |||
5b75869c0b | |||
1288b92615 | |||
7eecf454e8 | |||
ccf7d1e0c4 | |||
e4b5cd23e6 | |||
819296cc9c | |||
67c7d80f41 | |||
919f8c54d7 | |||
cbaf71f581 | |||
f118c602e6 | |||
ff2f40f5e1 | |||
9758c9b2a2 | |||
09e4e100a2 | |||
bdd5c180d3 | |||
749b085063 | |||
c5a796ad8e | |||
12d8409e65 | |||
8db89b4cfb | |||
31dc92dafe | |||
01b90809e8 | |||
0a7383a4e1 | |||
5e86a34925 | |||
ece206b81c | |||
88341b923a | |||
5d27633821 | |||
a9d4370ad4 | |||
8a0318c779 | |||
8e754d9a56 | |||
0e209dcb02 | |||
6f2d6425a2 | |||
b46c4a81e0 | |||
b6aa33f3a6 | |||
ab68d9198d | |||
32eebd3ca7 | |||
3f2e5633b4 | |||
a99b9e80b8 | |||
42ed7e4626 | |||
ae910eea62 | |||
d35920f356 | |||
c29e7477f0 | |||
86bbc7939c | |||
dab091a7b7 | |||
513d93cfc7 | |||
d7478c14fd | |||
297c593edd | |||
6439ef11aa | |||
d6479e133d | |||
50bbf2aacc | |||
41032aaac2 | |||
4e08f28246 | |||
46c57e120f | |||
6b52ee61ae | |||
61fbc5a791 | |||
22365205f9 | |||
c6515c1dad | |||
8201d1df02 | |||
ddf168c536 | |||
c9f81f56e9 | |||
570264e1e9 | |||
325e58d98c | |||
23a2960aa3 | |||
888a87463e | |||
2ebaf46095 | |||
3a95a3b7c1 | |||
c4edffb388 | |||
5eec7cc788 | |||
fb4cf0b75d | |||
5584884fe6 | |||
3bb1068ef0 | |||
b1b85313ae | |||
92dfd659f1 | |||
d87f743a2b | |||
aec3e7b0fc | |||
243600b75b | |||
3d89d126d0 | |||
54281e53a1 | |||
6befd2be81 | |||
1f0ca9ed92 | |||
f3db9c3920 | |||
83ceb26151 | |||
32cdfb871c | |||
801e7da5ee | |||
2cf1ab7ec5 | |||
d049c1afaf | |||
9f45389bc1 | |||
d875481969 | |||
17a1e1245c | |||
06d28c3eec | |||
684982c25c | |||
421522a61a | |||
f3b29d67f4 | |||
2ee5c6b2a1 | |||
5083772c6f | |||
fd51e5df47 | |||
3405fd91c6 | |||
194822f11e | |||
98963d4cdf | |||
804ef36b20 | |||
3c6ff8fddf | |||
511893d535 | |||
e05fe77bfe | |||
2b7b9a2abb | |||
6db3f68ae1 | |||
3773f2e7a5 | |||
1f8bffc15a | |||
afaef4e83b | |||
b746f723cb | |||
cfaf44f57b | |||
eed541201e | |||
a8bcb85f7b | |||
981e9cf290 | |||
3ac398ac49 | |||
2d0728395f | |||
722194405a | |||
0868a5e534 | |||
a86b9c82ce | |||
f8642548c8 | |||
27873f7ed4 | |||
b3eda6bcbb | |||
1c7799e292 | |||
aecd158d3c | |||
87d35f0d16 | |||
c089f9b59f | |||
82d7f9f5a4 | |||
8bc529be3d | |||
924c1634d3 | |||
03d077e915 | |||
303628bb05 | |||
3b92ec8e82 | |||
545944cb0d | |||
c90a88b6b6 | |||
89e45a61b3 | |||
2aff7bac4a | |||
124097d3a5 | |||
c520faed6d | |||
5bdb3703ed | |||
2901039a48 | |||
dfa220ef02 | |||
f26be00571 | |||
83654a193e | |||
b2a5d8daf4 | |||
19ee736e1d | |||
fda3f1352e | |||
d194b02e28 | |||
aaba99dc10 | |||
93a2e0f777 | |||
71f3c6b461 | |||
aabcca5059 | |||
7e67fd8c79 | |||
fecf1ffcb9 | |||
fafc9cf9ca | |||
3111e6a721 | |||
e436f471a0 | |||
28f84902f6 | |||
ebee50eedc | |||
e0ef09dfe1 | |||
d7992ab29d | |||
60f19f305e | |||
d99976f5d7 | |||
db158a5735 | |||
ea3be17220 | |||
f26049009e | |||
787234a53a | |||
fc3a64056c | |||
6ebc9abb80 | |||
80e9eed35a | |||
23b3990f99 | |||
41276403df | |||
e3e9e39498 | |||
f315025a8d | |||
8e43d97133 | |||
c97a47dc62 | |||
7ccafdc993 | |||
0dca9cb6b8 | |||
be3d780720 | |||
0f59a1dde1 | |||
7c6bb80cee | |||
62841c5b23 | |||
aad4f8d1f7 | |||
11c44c676c | |||
370c3aa598 | |||
1cdadafdf8 | |||
dd6f670dec | |||
9ff364b0d3 | |||
58a5331f7b | |||
ed261f0af9 | |||
c01b475cbf | |||
3d4feeec8d | |||
a1800ec23f | |||
8a4f1c66f8 | |||
b187231b0e | |||
60b38de69f | |||
600c49f7f0 | |||
e7380e70a3 | |||
3df8594f19 | |||
ee4a829293 | |||
1862f3c124 | |||
777ab3416f | |||
ecf5ab75e7 | |||
4f6d964217 | |||
06019f01e3 | |||
ddde885084 | |||
be8c6f218c | |||
9eb35ea7c8 | |||
d2fdbec41d | |||
2dd372600c | |||
eda6cf11ef | |||
68facd6b93 | |||
87002fb8f8 | |||
6a50fa35ec | |||
6541570969 | |||
4b0ceea894 | |||
8c0816c166 | |||
be769d07f1 | |||
3a9d58e31c | |||
7024acac06 | |||
6131346e2f | |||
eed73c9078 | |||
795d6f35ee | |||
ebd46705d5 | |||
72d2ca234e | |||
2246c3359b | |||
242fb156a2 | |||
208ed73e59 | |||
4441b37338 | |||
941d75824a | |||
ec9ddc4f22 | |||
98b6f90172 | |||
7e280de361 | |||
7bd8bd13fe | |||
09e85e948c | |||
9ec1c00887 | |||
c6bcb6228b | |||
a24d589845 | |||
ebbcc9f6da | |||
23fc453fae | |||
aad6f74db6 | |||
07dcefabcb | |||
40c68595d7 | |||
fe9a4fece4 | |||
098327f128 | |||
0873b8d304 | |||
c9eb584ac8 | |||
10493bd44a | |||
9e35230467 | |||
81e326571b | |||
1b2a7de4e2 | |||
11216d200c | |||
777be6a48d | |||
5765a1fdf1 | |||
29dcb9d274 | |||
8674ac4f68 | |||
684b8f24f3 | |||
1ca2be0039 | |||
8c41ff68f7 | |||
931d6c280a | |||
ee0fb2d0e0 | |||
c496ad1237 | |||
277fa21f5f | |||
1cf949226e | |||
be3fae6511 | |||
5932f36285 | |||
30abb65368 | |||
64a06b5ed6 | |||
69d18f17a5 | |||
4c7d3a103c | |||
10320bdeb4 | |||
4261dcff39 | |||
a091245793 | |||
ca282f9fb3 | |||
7cf2c3be0f | |||
f65d506f26 | |||
333dbca01e | |||
42eb265624 | |||
8a65726e9d | |||
1b0ca47682 | |||
8e3f5c3305 | |||
3c0a6987cd | |||
e37f70b9f7 | |||
03c148ce50 | |||
4817f0312d | |||
b70a82c609 | |||
25d1e0c4e6 | |||
8e3356f11a | |||
1b559c7776 | |||
d5583f0f02 | |||
bedd3c50b6 | |||
43a7af3f44 | |||
9db27c6acc | |||
42c81395b3 | |||
3b13e692d2 | |||
0331f5a1eb | |||
8a7e117f6b | |||
9b984cedac | |||
dd9e30b24a | |||
6a93688b2e | |||
3ab17a97a8 | |||
f21ae66265 | |||
afa1a5e932 | |||
050768c266 | |||
cda2bfc240 | |||
2f167b1512 | |||
ba3ac85356 | |||
ec29cedeb7 | |||
064ae49d2b | |||
247f99ce2f | |||
7b6d269904 | |||
87a0482b8b | |||
e899699918 | |||
bdf464e792 | |||
c410bb4ecb | |||
a720bcc637 | |||
369a8cdc74 | |||
3f4e55be4f | |||
9171f471ab | |||
2186b134a4 | |||
f371ec210c | |||
afcd669d2f | |||
fbf542d205 | |||
13184eb8e9 | |||
ddf1e1ccee | |||
5ac4e73697 | |||
6be59b53f1 | |||
bb54fec907 | |||
0b81b283bf | |||
e2ab2aea32 | |||
c3ceefbafb | |||
e7cf9932a9 | |||
0c9d03f5df | |||
92aa24ae34 | |||
97a74d5c1f | |||
256f8094f5 | |||
1e2f0ab308 | |||
af2cf2734d | |||
ec62d8e973 | |||
3225f514f6 | |||
2d63c86022 | |||
2dcff83be7 | |||
afb9ebcd99 | |||
92d7e44525 | |||
a517f442ea | |||
311758233b | |||
6e086eb808 | |||
7e8644430c | |||
70a8f6743a | |||
69eafd0e11 | |||
6b6a095b91 | |||
d5a2185030 | |||
26f31e9288 | |||
e654e66839 | |||
bb4861cf0d | |||
01505910f4 | |||
ab766a0598 | |||
51c664a678 | |||
3c4b45c9e7 | |||
93507a263b | |||
1175461030 | |||
2f5e55bea0 | |||
c375e7b4df | |||
5d188c69ed | |||
6bff7751d0 | |||
1a5986abe0 | |||
cebac3c10e | |||
a5da3db966 | |||
cd30f75173 | |||
94df4ceb36 | |||
a14476c5fb | |||
d82bb29919 | |||
33af0c6a7c | |||
68f3f98bc3 | |||
f873cd5b1a | |||
fa8df286d9 | |||
76aa0c434a | |||
78dc0cfdf3 | |||
9654728bfb | |||
123d1864f4 | |||
96a91e988d | |||
19ecb1701e | |||
8085b2728d | |||
56cad31a36 | |||
3275bc4e93 | |||
8963378039 | |||
c7d435bb7a | |||
06cc7e4ea0 | |||
fba20e2cfb | |||
358f080c76 | |||
8cea57ff0f | |||
7b27f200b1 | |||
f4b207220c | |||
d835e1d14e | |||
75f92de8f8 | |||
293c1deee5 | |||
4dee05a967 | |||
8d6414d74a | |||
362ecdb583 | |||
058b9f9272 | |||
355762aa30 | |||
be4fb65470 | |||
4ed296bad4 | |||
a8aa862919 | |||
31ba1de53b | |||
bca1fef2b2 | |||
f33b31e048 | |||
0d10ebb7ca | |||
4a8abc948e | |||
6fd3672618 | |||
abd090bd48 | |||
bd9140f1f3 | |||
9d78b2d259 | |||
9c9528838a | |||
77b640b76b | |||
a8dfe98b1a | |||
cee41b87f7 | |||
7a95314e42 | |||
6aaf1f4f21 | |||
368a0ddd44 | |||
0808a10b7b | |||
6f052baa94 | |||
5bc67d3f6b | |||
74c6c5cfbc | |||
158b7fd166 | |||
c3f647dc96 | |||
5936c7b65c | |||
a8bcd85c93 | |||
127b558f95 | |||
6e9a27f40f | |||
4a13dbe3bb | |||
0f61f5ba03 | |||
5f1efbeb67 | |||
9c105914f0 | |||
579582740e | |||
b15544c163 | |||
94a63e3859 | |||
842b7e6c39 | |||
22f5011451 | |||
74120fe1f3 | |||
b4e8abd0ad | |||
336f1f4f50 | |||
1c256d8876 | |||
1ce0f0e7a5 | |||
fbf1901d86 | |||
0382f33c46 | |||
13372f3f99 | |||
e741cb7f0a | |||
fb289c6b17 | |||
75a7ea55d4 | |||
86573a5ccd | |||
6fe55a79f1 | |||
1a6cb9ee99 | |||
a495d9eca5 | |||
65a945f968 | |||
a9e8ed5087 | |||
00520b6a0e | |||
e6f2a3893a | |||
24c034ff6a | |||
631a93bcd8 | |||
b1763353ea | |||
f95bcf45ad | |||
15ec1abb6a | |||
cfda8dbb2b | |||
3aa2003951 | |||
0e473f4570 | |||
bfa824ee71 | |||
1157436a24 | |||
4596e78df0 | |||
813dfbd2d3 | |||
ba7dfb360c | |||
6aad750fe0 | |||
5e443ae347 | |||
c65f5f7728 | |||
74b62727af | |||
2e94562f79 | |||
061ea5648e | |||
439e7bbf4e | |||
0f1d51f866 | |||
75cfaf0672 | |||
ceaa732e5f | |||
deb2a2bd14 | |||
33853b6107 | |||
ab6e1b112b | |||
220e823c8d | |||
c666c3e251 | |||
9cc1773fa7 | |||
e78c7af715 | |||
b96e76134a | |||
fd2b206997 | |||
2d53c7c5b2 | |||
28ae5d710e | |||
7a13412ec7 | |||
c86610b917 | |||
502750492c | |||
8fc1653b0c | |||
6841ebc31d | |||
8757281467 | |||
20b1723e78 | |||
be78afeee5 | |||
3746a2566d | |||
0cb47cf7d7 | |||
dec81c4f27 | |||
54b335711a | |||
6bb8332b4b | |||
de9e304236 | |||
650af5eb64 | |||
47bdcb6050 | |||
58dc3e93d3 | |||
79b0a16f7a | |||
2b65ee433f | |||
001bbef9ee | |||
c4316e81e6 | |||
fac63541a4 | |||
dfd6cb29be | |||
5f75e531e6 | |||
a7648d60ce | |||
52c45c2d32 | |||
fd6755c93f | |||
a53ee2e35c | |||
4e6978ff6f | |||
91a5c4bdcb | |||
9a07ede615 | |||
dfab55112b | |||
1709b47bb7 | |||
2d10c246a8 | |||
6e2869834f | |||
b8b71c7dd2 | |||
c3f6c3dd82 | |||
844b245776 | |||
4bcf8e6975 | |||
0e52112016 | |||
32a9545360 | |||
9a44c92211 | |||
dd6aabf9ab | |||
91776311c7 | |||
882c82f82c | |||
43b9db6e45 | |||
032ceefa1d | |||
05fa266e6b | |||
56085310cb | |||
6a1d611fd1 | |||
c8a72c876d | |||
ec87a8ddfc | |||
33e34ebb83 | |||
dce435c882 | |||
396b3c3952 | |||
8cf42f4e15 | |||
17ea51ce27 | |||
04818ca626 | |||
6732b77594 | |||
3e4346e321 | |||
4dfc01899a | |||
b0b8ccfd4a | |||
4d35c66af3 | |||
509f7bd018 | |||
42b9b3d72a | |||
e280f9fe3e | |||
89493a2f1d | |||
e259bffca6 | |||
ba9164022d | |||
a4672ba00f | |||
c0bf267bae | |||
1a26a53659 | |||
8f4d7ac655 | |||
c5625d8d32 | |||
548a2a1d64 | |||
df01a58099 | |||
ac8ee9f981 | |||
b1805b70ea | |||
eae8a2914e | |||
03429db528 | |||
10f27250ee | |||
aed7963d11 | |||
2810413112 | |||
31fd92e071 | |||
b3b76d5d56 | |||
cd948dceae | |||
eb33a87ff5 | |||
bf560f4594 | |||
d77237ca5d | |||
211d596fdd | |||
f464b347b2 | |||
203c3ec233 | |||
e2a74dfc30 | |||
4e99da7b62 | |||
eb5ed50824 | |||
3b4539de79 | |||
3e4d1c04de | |||
fdf5748029 | |||
3562e94650 | |||
15c5bbcf22 | |||
c363423718 | |||
e58158c3cd | |||
ff2cd50bfa | |||
984692dc62 | |||
a7fc23dd96 | |||
c1bcbf8c63 | |||
9e69b8fe1b | |||
e0ae631d59 | |||
3b187b5246 | |||
20666763f0 | |||
f591c87665 | |||
e6fe701727 | |||
35a698ef72 | |||
998271414e | |||
1749f25420 | |||
4ab0e70a9a | |||
08989bde5e | |||
87cbff391c | |||
962923bbce | |||
311b081e60 | |||
4103948132 | |||
906f26698b | |||
8a1a583afe | |||
9e19b73ce6 | |||
e11706d99d | |||
301b811310 | |||
273cf3d565 | |||
f432cfd73a | |||
ffa756ccee | |||
e210a4b244 | |||
f1902a4471 | |||
04b865adae | |||
00df092a99 | |||
cad581388f | |||
e7ed3abb79 | |||
e5f6dc1b14 | |||
145da82cd8 | |||
64776d6bac | |||
64d123f524 | |||
0ec4ade683 | |||
4bfc445cf8 | |||
4232b1cedb | |||
474d77ac57 | |||
3c40355d7c | |||
cbc1aad58d | |||
89a30a47c5 | |||
881a5603dc | |||
68c48b2c8a | |||
0f9260869b | |||
412fdb0f7b | |||
81d52b6169 | |||
278d2169da | |||
5599b5a337 | |||
471d6d6031 | |||
b90d6b0f26 | |||
cd22da9c62 | |||
fb75c23f4e | |||
7f22994f68 | |||
7aba7b6064 | |||
e32030f364 | |||
b40619bcbd | |||
fe2e1d931f | |||
2e17e78052 | |||
f2fa82fd3c | |||
8cec4b60a6 | |||
bf9888099c | |||
02201631e7 | |||
8e80b4bfc1 | |||
63dfc0633f | |||
50f1847904 | |||
79840f0fca | |||
06bf7b0f31 | |||
dbb63b97bd | |||
3039cb5c02 | |||
b5d2570fe2 | |||
5f951e8f21 | |||
286f82cc99 | |||
ed5415aeb8 | |||
bef79df6bb | |||
2edabe0f99 | |||
91b5f0228d | |||
d639da741b | |||
84bd5ace6c | |||
63589d2ba9 | |||
d6f4ff26b5 | |||
b606a2e040 | |||
f685139d89 | |||
68d6ce60a9 | |||
2bba64fe3a | |||
774ed044fc | |||
9cc235cde0 | |||
91375e4c6d | |||
0ef8da64e0 | |||
9ef38171e2 | |||
455e4de6f3 | |||
4e319254dd | |||
04e8780dd0 | |||
0fe4384067 | |||
bdfcd0b99e | |||
5da87d1904 | |||
821edf0f51 | |||
04e822acfb | |||
c31fce3621 | |||
5c05cf2206 | |||
d4e544c62c | |||
d232248268 | |||
90025ed45d | |||
964151d9c7 | |||
409c9bf9d2 | |||
a135c06bcf | |||
efb1f4abf2 | |||
036a826b3a | |||
8d2b66a0fd | |||
31d6278b31 | |||
5558d7eef8 | |||
6103d86a47 | |||
b8899a534d | |||
fa6829a6a1 | |||
5335540c33 | |||
7f62de3854 | |||
0afa2e92d5 | |||
6d1b166ad7 | |||
4b6ddfb89b | |||
9ec260619b | |||
4c6ac9e4fe | |||
08fc3ea2e0 | |||
03e454b71d | |||
c527ea83fb | |||
8b9ac63657 | |||
0ba02f0830 | |||
1f6cef6f8a | |||
251942323e | |||
8e3efec40f | |||
3d0740f80e | |||
707a68cb4f | |||
e6b1a1fa76 | |||
3e8d450741 | |||
d0881b7420 | |||
27239b2dde | |||
3fbbaddece | |||
effe46db86 | |||
ba939c92ec | |||
e25cdd9d12 | |||
d394235ee0 | |||
349fc4143d | |||
4be9e6a0bc | |||
cb258146c4 | |||
9f039cef72 | |||
d08815bbc1 | |||
c04e38d011 | |||
794022d399 | |||
8e43190984 | |||
2212a6e40f | |||
63b69c0b0c | |||
278219b1d8 | |||
2ce4ce9064 | |||
4448418b63 | |||
9f1f37e780 | |||
40ccd1a469 | |||
a4ef0940ed | |||
2ff0aa09e3 | |||
32217a774f | |||
8856c8cd62 | |||
e843b8e188 | |||
c4f2e3a955 | |||
91301ec7fe | |||
13b03e7e50 | |||
8a0aa5a0c8 | |||
2bd8e7dca4 | |||
d75571ffa1 | |||
8683d529fc | |||
2ee4b6768d | |||
a9f0a85590 | |||
37160f973f | |||
9bbf50e864 | |||
51258ab28c | |||
29e5a213a5 | |||
2d261607df | |||
54144154f9 | |||
81daffe68e | |||
2ea20a8b29 | |||
2257c875f5 | |||
8a2e8ad953 | |||
fa5b1d9978 | |||
529fb07b42 | |||
4a261cac1a | |||
b3c8f9d508 | |||
1b878030aa | |||
46e403b20b | |||
1b1f728c58 | |||
309013efb3 | |||
705cf6499e | |||
f2ed4a92e2 | |||
0c8ca1b3c0 | |||
6ee5ee496e | |||
7f8aa2099c | |||
1d9797660b | |||
cd0d8a76c5 | |||
3f1251e78b | |||
89d4405563 | |||
8966364648 | |||
1c60e9b4fc | |||
843c860d98 | |||
6587e39992 | |||
757fa1410c | |||
dd6d8e0002 | |||
cd49406bfe | |||
7a3acc3249 | |||
db1c804812 | |||
493d58f358 | |||
fcd56dddc2 | |||
91b85f9919 | |||
4cecba8787 | |||
5930acc418 | |||
61d36c1723 | |||
c2a43c6f40 | |||
1ab00ca8b2 | |||
778baa6dbe | |||
25ab121e42 | |||
cf4949b4f5 | |||
4ca634d229 | |||
ca21b31696 | |||
38ff76d2b8 | |||
147bde5294 | |||
1a004f0c4d | |||
7d21bf15e8 | |||
a88ad8025b | |||
e06bf17d13 | |||
04a3669fc4 | |||
795075f90d | |||
2727df704f | |||
8ce8aadd9b | |||
2999e69f0f | |||
7ac16ed073 | |||
3585e4764b | |||
065e38c6aa | |||
9054ee18a1 | |||
9d8b95107d | |||
8731c86d0d | |||
d7fad4bd04 | |||
2746251dcd | |||
73e46e569f | |||
4f0f74d201 | |||
adf1e1982a | |||
f5405e835e | |||
85ee7fb3a4 | |||
ee00a5d8ee | |||
65d23fc9b9 | |||
3448d7cb70 | |||
db1abb02d6 | |||
36d78577e2 | |||
20832682ef | |||
8e6c592ad9 | |||
0b3115997a | |||
b07c5982e1 | |||
4a0b0d8735 | |||
7b9f67f4b4 | |||
577f17c916 | |||
d4c1d62781 | |||
80da1f1bb9 | |||
febdb85f96 | |||
96b76c8f5c | |||
411bf3be03 | |||
a98b6663e1 | |||
e7f35e6ca3 | |||
f0ec165d42 | |||
abd240468e | |||
b5e00027d1 | |||
1698554024 | |||
f4604bbf79 | |||
699ad316f0 | |||
fcbe233fdb | |||
4af8a9ed2d | |||
80627b4f89 | |||
83078cd49a | |||
53e0d13142 | |||
85901082a2 | |||
f19e27e875 | |||
c864046cee | |||
2d68235e55 | |||
2be8100e7c | |||
ab3e2562db | |||
123d6c72e4 | |||
0ea2135aa5 | |||
48e20cb5f7 | |||
0ffe0b6894 | |||
338156500b | |||
bfd9bd43c9 | |||
283e50e670 | |||
6fb5bb6a5e | |||
5d3bef32ca | |||
3ff26d5cfe | |||
88c1e504b0 | |||
0263677e1f | |||
940455f81c | |||
f541ea659c | |||
938cae1130 | |||
7f73e57c67 | |||
e50ec31351 | |||
a28fa219d7 | |||
8a1ba03bcb | |||
f8e7fb3d48 | |||
e8b7e70ec9 | |||
67c5aa0be9 | |||
e644380160 | |||
c5eb6fe6fb | |||
ae2ef324f2 | |||
d0337da8ea | |||
17b30b2ae2 | |||
5e17d53c7f | |||
22e0527502 | |||
ca3c6c5e8a | |||
4bd30f5e72 | |||
3cc26b15a1 | |||
9673dac22b | |||
0426149580 | |||
fce5c57548 | |||
4ee5264e24 | |||
101ca60b2b | |||
f28a0aa666 | |||
997bf91442 | |||
5a1de15332 | |||
42f8ec5b14 | |||
2fc1b99911 | |||
3a923060ce | |||
0985adfd74 | |||
59d628208b | |||
5c5699bba5 | |||
67e0214fa5 | |||
e17b6804a7 | |||
96e36f0604 | |||
a99858c64d | |||
ba50765c30 | |||
d7f6b36990 | |||
4439666e67 | |||
23febc6d94 | |||
fab4a7a602 | |||
092d2f8917 | |||
e9fb566c07 | |||
5a34e8fd7c | |||
fcfb2cfc3d | |||
e93b9560b5 | |||
8e4438b375 | |||
eaa5ce4467 | |||
c86c719e1a | |||
b30b88716e | |||
c3e6b1aa8a | |||
6d0ea13f97 | |||
dca4ea5cea | |||
be1e2c07ec | |||
2a0018e730 | |||
ac4497a1f2 | |||
d72c75db23 | |||
6821a45b7f | |||
f24cdd6564 | |||
cb69869836 | |||
0b85051a23 | |||
f2e2053134 | |||
b181f4bc30 | |||
f00dbdc215 | |||
309dcc82ca | |||
0922a7f410 | |||
7d91db607f | |||
2be583ad4d | |||
efcba698ac | |||
b191291737 | |||
c988b4d213 | |||
90007e2d9d | |||
29ef1e2c4b | |||
fbe84f9e47 | |||
b036d95bab | |||
bfffcb3910 | |||
3bc02b9662 | |||
bc450e4cee | |||
de02deac98 | |||
e2ad3b0183 | |||
caf6d02728 | |||
35f71f5793 | |||
b2a89ee4b9 | |||
b84d52be3d | |||
305973c0e7 | |||
7c251efc47 | |||
166f872712 | |||
8f2c485c92 | |||
613f2fc447 | |||
9a0d6124f3 | |||
2646ae29f0 | |||
b4707f46ad | |||
482e049ac7 | |||
c04adf7452 | |||
92e8aaf36f | |||
b1f486518e | |||
3cab0e69f1 | |||
1ec7878c07 | |||
cdd83c279c | |||
12cadf3af0 | |||
2bc6da038d | |||
3b4b34b369 | |||
6542f5f15a | |||
30b56dbcbd | |||
cbc8c1aed6 | |||
6afe59e76b | |||
88a93945d4 | |||
2847cefff7 | |||
96f16069a9 | |||
188c5aaa35 | |||
f5f59203a2 | |||
c329730de8 | |||
97a83c9b7a | |||
1e6df7eec0 | |||
f3c72f4f08 | |||
05cd30ac06 | |||
34adcec616 | |||
f9f46609ee | |||
b5bdfa6c2e | |||
ea4ef1655b | |||
7eb61a28be | |||
92b913ca37 | |||
3806f23b02 | |||
36045a8b0a | |||
943090db98 | |||
77caaca50d | |||
f66e0fa0e8 | |||
441075f610 | |||
b2878dca1d | |||
b883ce5c51 | |||
127dfadc6c | |||
ff9f3cb31f | |||
a21bd41580 | |||
8e9f1bcf18 | |||
4b06fc5323 | |||
cc27bb3231 | |||
c1700054f4 | |||
cc13310083 | |||
1012912272 | |||
edbd90a4e6 | |||
ddc3b5eb0b | |||
17bbfe8d89 | |||
96deb5b09d | |||
9b387d73e5 | |||
c02a6780b0 | |||
85ec9d95a4 | |||
6dfec4db40 | |||
2e9d7f5c3d | |||
696a711e39 | |||
887246a66b | |||
2993318d19 | |||
2b52cf01f5 | |||
cd9e0e0cc0 | |||
f66598db8a | |||
cf5c752dda | |||
a6d2c5e181 | |||
82760f4b91 | |||
62e099ace5 | |||
e92b7bd25e | |||
e7bb3b2776 | |||
ec3c882a44 | |||
66ce5a4a2d | |||
a110d445ac | |||
a67f3131e7 | |||
7f305aad1b | |||
80908efdcb | |||
e5d0097116 | |||
6d78ea5a45 | |||
550d6a6a9b | |||
9be8160bf2 | |||
3070565fa3 | |||
7194bb1b81 | |||
78cf0c73c8 | |||
4adc61bda9 | |||
93e0041d0e | |||
682a7fb6ba | |||
5f2398fe59 | |||
3abf466632 | |||
4bb429a0fb | |||
4a0e4fdb85 | |||
a43f882d48 | |||
9731e06728 | |||
8e764fc8fb | |||
4745ed2818 | |||
49de5d9b07 | |||
365cc198ba | |||
9899a0e098 | |||
5ea8cec16f | |||
9dd70ca9ae | |||
4fda35b466 | |||
31988f0529 | |||
db03846358 | |||
c6b3eccbdf | |||
3f259eb97a | |||
fac0b027b3 | |||
84b962f256 | |||
123ed5bd2e | |||
c3336251e0 | |||
c054d0f329 | |||
8dd68580a6 | |||
067484a6a8 | |||
c83e16aba4 | |||
d85fc456a9 | |||
dd2b324d8f | |||
0bce08d30f | |||
57d65177c8 | |||
040ee919e5 | |||
efa3fbff39 | |||
8c8eabf7ac | |||
3aea639fe4 | |||
046f1e6e58 | |||
37e8f495b4 | |||
512d7b07d0 | |||
527fa7ba9c | |||
288e7bc9c5 | |||
649b8ac7c6 | |||
96b2758169 | |||
40e0252d7d | |||
5171d99fe5 | |||
ea9d61c21c | |||
da25f3b84e | |||
1e34de98ab | |||
7b46f50cf1 | |||
cab40026f2 | |||
ac66bddeda | |||
f4237be9bd | |||
dd11ccb3fd | |||
c4549a5375 | |||
e9b3140d12 | |||
bdd2d57808 | |||
22f5128e39 | |||
ae1aa6f63e | |||
29a53d7e95 | |||
2fbb7be23b | |||
f7f39854f8 | |||
113528e1f2 | |||
6bffa06063 | |||
dcc41ef885 | |||
e909cc363d | |||
9a87ae575e | |||
860a7af679 | |||
4fdb21b414 | |||
eeb5297284 | |||
8de63b60b1 | |||
0b38d878a1 | |||
d29720fbce | |||
0556ae4749 | |||
1a86f72690 | |||
25d380f051 | |||
546d394868 | |||
8110040f86 | |||
239e4adf29 | |||
5662d41062 | |||
1e03ef484d | |||
1d95f10090 | |||
6768768373 | |||
dac801c8ac | |||
ece5ca52b2 | |||
3205d9e9da | |||
b931dc0f93 | |||
efe4e7df06 | |||
b94f70ea96 | |||
bd946c78f3 | |||
a507907443 | |||
0507b56bed | |||
ac405aa564 | |||
aad7c63282 | |||
1ff459d995 | |||
52454ca77b | |||
884f772362 | |||
bc06571dba | |||
1e8ad3d979 | |||
b0a469baab | |||
c968c1be78 | |||
a0bafa4952 | |||
e56f0db11b | |||
8bcbe07c87 | |||
ba9059c7c8 | |||
45783c1661 | |||
71777e7a6f | |||
c86ec0bd36 | |||
08b1b2669a | |||
94a655b055 | |||
717067e9eb | |||
5a5797d914 | |||
75826aca13 | |||
f52b7c030f | |||
c1386bcb04 | |||
234a9e48e9 | |||
908e6364c9 | |||
3ec511010f | |||
b3e1691c01 | |||
5adcc26190 | |||
db6dae7541 | |||
4e97f2a6fe | |||
4643046989 | |||
3c3ce71214 | |||
0682fe544a | |||
27e803e4a4 | |||
405c44c9e1 | |||
4c5f701b05 | |||
c7563a5f7c | |||
3ff3c335bc | |||
b9d5e1bbf1 | |||
e313b366a0 | |||
027c666265 | |||
4a3d94aaf9 | |||
c637e3657c | |||
9462dd3ddc | |||
c3524a9d57 | |||
53ff66c317 | |||
ec2ac2e80c | |||
27c72935f8 | |||
31c757d912 | |||
fcdc7a1a35 | |||
f13c776099 | |||
ebded1ec49 | |||
7b9d462fbc | |||
c174a1eb01 | |||
ac77997a7a | |||
fa352ff4d3 | |||
fd7745cbeb | |||
c348de96e4 | |||
1bb35b9204 | |||
cbbcc2d68b | |||
fcbf37f60f | |||
56ce7f5dcd | |||
0ccbc801cf | |||
4c52cc414f | |||
6b45386252 | |||
3acc761419 | |||
dd4c67b654 | |||
0c581cfb62 | |||
703bf9bb7a | |||
a40dee2230 | |||
cab9afa45f | |||
ba5946dc60 | |||
9bad83a551 | |||
a549828655 | |||
c1398a6a1a | |||
e11d1b5202 | |||
abdb846c3f | |||
b0b6dd8f87 | |||
4a971226e4 | |||
b10d4d3b8f | |||
6ed130fc16 | |||
90d4acd1a1 | |||
a42d2afcee | |||
ba020fbd21 | |||
af167e8e67 | |||
be82f4db9e | |||
6a97ac603a | |||
e59d3a339f | |||
db7cb12551 | |||
1049507b3f | |||
1303771b58 | |||
f6605bc3f8 | |||
80ec178d5f | |||
ef76bd355a | |||
b0a8bd7dfe | |||
5d8d7740ba | |||
3e64935844 | |||
7577115c3c | |||
2cb242e9b3 | |||
7aeccbb6b0 | |||
8406c7f431 | |||
8c98cc9458 | |||
715d7d4424 | |||
8e9eca6a97 | |||
5f15f51610 | |||
277de41200 | |||
63bce04648 | |||
76dfb7825a | |||
5cb0e75093 | |||
c730fd6e5f | |||
c2b97c3e3f | |||
e0ab8207ed | |||
ecad388846 | |||
9a120f43c8 | |||
4ff1306e0c | |||
1dd663af6e | |||
06d9821b2c | |||
abb20c65e3 | |||
9fb5674233 | |||
18ac109e5a | |||
14a0e85862 | |||
fa2b3bcc63 | |||
620555d210 | |||
ea3ceb382a | |||
37a30fbc3f | |||
99193a2d7b | |||
abfb99ba3f | |||
fcb311eecd | |||
54e4f88ada | |||
89125fde22 | |||
9f3eed6ca2 | |||
ab82358dcb | |||
75fddd0052 | |||
8a2c5f5b0d | |||
66caac0bbc | |||
ab8d897bd7 | |||
3024dbcf2c | |||
eeae3eca67 | |||
d0cda6d605 | |||
167e32a69f | |||
be2512bb4b | |||
c3f1c13a31 | |||
35cfb41a9c | |||
74cdf5350d | |||
9349232bd4 | |||
1811302deb | |||
e6564aa69f | |||
566a83b245 | |||
9eb9ddc668 | |||
cc5261051f | |||
fa870bc026 | |||
99d569ed0e | |||
a1a7b9c151 | |||
dc6340bf38 | |||
8732bea99b | |||
bbc6b71138 | |||
5fb096d7b9 | |||
cf8680f1ab | |||
115d8b5945 | |||
bd8b61651a | |||
d2ffaee9f8 | |||
8f61633551 | |||
d33d5b847d | |||
c8879df621 | |||
c367769781 | |||
02b44256b2 | |||
b6e722a048 | |||
7f2615b2a5 | |||
a232c2d509 | |||
c8205fda9f | |||
8df88e7fbb | |||
c8092269ba | |||
9d88f07955 | |||
f267375ac2 | |||
d44fa416ca | |||
41d7b27d43 | |||
5f461374b8 | |||
d5576779b7 | |||
c098be40ab | |||
333f7cc320 | |||
9180c751d8 | |||
131a04653f | |||
6e6d495bc7 | |||
2c07f758a0 | |||
251f0efec2 | |||
e8697068fb | |||
269c1bbf58 | |||
9b8493c304 | |||
c389a711ed | |||
382548e0a7 | |||
a90fc3d7fe | |||
48a6380e31 | |||
64ca96f470 | |||
59b3e30821 | |||
92e5e0e95b | |||
9202996c62 | |||
e22d54abd3 | |||
b53ba12fa2 | |||
335115041c | |||
bac67800be | |||
306df9e17f | |||
5f2e768376 | |||
575c92ec47 | |||
4d8bf0b621 | |||
954074942e | |||
341eb16a4c | |||
3a7eeff135 | |||
659f93b1de | |||
ea60e48d9d | |||
6054abaffb | |||
3a1feed723 | |||
85f3fc9944 | |||
87cf38a377 | |||
5e77b548b1 | |||
104de9e795 | |||
424f4a72ff | |||
ec6409914d | |||
6a25cacc3e | |||
b1af689546 | |||
0a5dfeb3d7 | |||
6a180f495f | |||
3672dbc5af | |||
81b50c0387 | |||
bd60c54911 | |||
87acaa0926 | |||
54d2c91320 | |||
94e7961df0 | |||
0d46ea5c71 | |||
6bd345b1ad | |||
cb384261b8 | |||
75301bec4b | |||
d00c320c00 | |||
e13ca94061 | |||
e02369ba6b | |||
82c35f2746 | |||
a9d935f9ef | |||
92f3154e8f | |||
eb06d0116f | |||
f66910d054 | |||
1b47132ebb | |||
a89cbf116d | |||
471ea680a5 | |||
51de84407f | |||
d252917792 | |||
dfa5f614aa | |||
f3a244e90a | |||
c7c83a35fa | |||
6025cd0ca5 | |||
ce05ce92bb | |||
a5fc640f2c | |||
0a4a3fece5 | |||
fcf728f3b5 | |||
cd4851c98b | |||
3db5f30403 | |||
58957122b9 | |||
8b46658b05 | |||
571e322d66 | |||
ddda02f092 | |||
bf6fa6bce4 | |||
025a3cf730 | |||
6d9eaee7f9 | |||
7471ce4530 | |||
149ffb844f | |||
4cf3ac42c8 | |||
d16c6b0e69 | |||
76e1aba58b | |||
c560d06b8d | |||
0681568d3e | |||
c7fdfb8116 | |||
c6b1a776dc | |||
8accb6f04e | |||
d1d055564c | |||
2741c58a01 | |||
64399dd8d6 | |||
f2ca11688e | |||
3c0c57359b | |||
062fc79286 | |||
2da565f5d4 | |||
e8373bbf65 | |||
26acc836d9 | |||
9c22af9685 | |||
75d0078a38 | |||
536b1a23fc | |||
cafff5e504 | |||
dd5c4b6864 | |||
a2c85a8531 | |||
de4d757650 | |||
f22cd0e8c7 | |||
702a1da0ac | |||
768007d980 | |||
2e40ab6244 | |||
95182ed74b | |||
8bc6cdf55c | |||
6c0b101fed | |||
9841c0a63d | |||
17d200dc88 | |||
c8fec556c0 | |||
b7f2959353 | |||
4899d3c458 | |||
c311dba465 | |||
75ec4256e2 | |||
bb5a91c179 | |||
8225f1ac92 | |||
06d16c6b13 | |||
90780818ca | |||
a160bd0062 | |||
7e0312493b | |||
ccfd06ad21 | |||
48c2146a42 | |||
abb9fa8cbd | |||
f99245b917 | |||
e35db82c27 | |||
6202525372 | |||
ec66c8fd3d | |||
19804c5718 | |||
fa5fa53592 | |||
da43ed8ce1 | |||
2d1f99b765 | |||
f01b8f29c6 | |||
440e9731e2 | |||
acdb54b88e | |||
00c3336ec8 | |||
a268ac7141 | |||
aedb513c9e | |||
ac3a7acc45 | |||
8409aa2571 | |||
199740cc61 | |||
a0f76cba62 | |||
5b8003cbe5 | |||
c0719102a0 | |||
9d8bbf34e6 | |||
ec9d0e70fb | |||
f1e44291cc | |||
b3b613d8b4 | |||
177b685557 | |||
71a4333f55 | |||
f1c21a912a | |||
84a142096f | |||
bb2b344d33 | |||
b96572774f | |||
641a96e4a9 | |||
9f8983b570 | |||
e42c5b00a4 | |||
a3d7ad731d | |||
dc98609ef8 | |||
c799faaca6 | |||
07e4c4d189 | |||
c4a8fd353c | |||
91524d6d6e | |||
c1201997a3 | |||
d814e21f0d | |||
49d122a2c4 | |||
0813eba367 | |||
4fe13c64a1 | |||
b3c2a56ece | |||
9c57b54a81 | |||
b131d3b2ec | |||
16bfafa29e | |||
f714adf6d2 | |||
dc9e250868 | |||
b6cf0359fa | |||
39bd04f06f | |||
d755174bee | |||
1229e90817 | |||
5a638fa977 | |||
5e9d49a910 | |||
ae39d16c11 | |||
b93daf1fb7 | |||
6545d250e8 | |||
b162351ff4 | |||
53468ea474 | |||
3697d70b48 | |||
e0c025b162 | |||
9e443faba3 | |||
f95cebaf06 | |||
9a8599e4ba | |||
2d68308d49 | |||
0dd1c26cf3 | |||
881b2f2b38 | |||
ca211558b5 | |||
3a03f90831 | |||
9020f632b2 | |||
8bdd2befe9 | |||
ebececf8c6 | |||
e1f28be151 | |||
10231aa404 | |||
139ff82432 | |||
4e8f075ff3 | |||
148775b3e9 | |||
075d900d45 | |||
5d1ca33b84 | |||
ccc493cb2b | |||
2745325ae0 | |||
84e9ce71b0 | |||
88fc1e32ee | |||
4f975bfb04 | |||
692b9cf0e0 | |||
ae354688c9 | |||
c9bf7f9896 | |||
e8929599a5 | |||
27f37315f8 | |||
c4f4e9e620 | |||
f2b850ad20 | |||
ccc27d1b7c | |||
4835ec3f6d | |||
40a9828fba | |||
04840d0638 | |||
38f12c50f7 | |||
ca8b62291f | |||
69d01204e0 | |||
1e3b896fda | |||
9e35560554 | |||
f9d4751ec0 | |||
a66e6a413f | |||
2c911a5475 | |||
e2c2a38005 | |||
aa4a6bb3be | |||
4af020161d | |||
f8b0d6453a | |||
0102e91940 | |||
1004211a66 | |||
f5cf4eb45f | |||
512395e3f1 | |||
9c6727e27f | |||
624ab25cd4 | |||
a70d1f1a91 | |||
3059f13011 | |||
6d1f9d4d02 | |||
d3e7d30ee0 | |||
5bbb4f31dc | |||
da70122d9c | |||
8556ff5eac | |||
adacab3349 | |||
613b351f13 | |||
80a29af497 | |||
7e1fad55d9 | |||
9b7cd029a7 | |||
c5d9944993 | |||
14717396eb | |||
9c71f364d2 | |||
be910374dc | |||
10de75623e | |||
7fc55b58fe | |||
12c8a04458 | |||
796e58b6f2 | |||
a7d37fa69a | |||
7b4b997a34 | |||
6b4469c6cc | |||
107a0ea852 | |||
6d7676202f | |||
0305b7a1fd | |||
02384f81c7 | |||
4536b19512 | |||
45f89c6255 | |||
b1cf77e847 | |||
037b0d7190 | |||
ff17202b43 | |||
a3d8313dcb | |||
36841eaf63 | |||
e24a183dad | |||
8596753a63 | |||
51183bef33 | |||
2cd837896d | |||
c75ae71190 | |||
48c20f5aaa | |||
929a035f96 | |||
5779f20fa1 | |||
384e0df9e1 | |||
a5b06514c6 | |||
a309f4e721 | |||
159d868b77 | |||
0854e83ce4 | |||
bb02226870 | |||
9ddbaaf7e8 | |||
3b7cc4391a | |||
70a055bc27 | |||
61db1c46be | |||
a60b2feb5f | |||
6ba031f048 | |||
812f00eb81 | |||
2f6973e08b | |||
fb14796ed7 | |||
7d912726d0 | |||
e3c8eb062c | |||
3cf81faabc | |||
0df605e559 | |||
e97a6ef957 | |||
c4dd8d9c72 | |||
bcfa3246cb | |||
f67871e79e | |||
11f892380e | |||
fd72cb034c | |||
b9be8d08d2 | |||
33d369d78c | |||
0e6e6a7521 | |||
eb692c2ee9 | |||
3eee38fedd | |||
0ba61bb590 | |||
9497485103 | |||
551d9c86ba | |||
e61e827eb9 | |||
92a5b12bd9 | |||
35d1330fe2 | |||
b4e0b7584a | |||
2341212337 | |||
53ea261350 | |||
a17e5d0a4d | |||
5d4a66ed8a | |||
8d2e7db178 | |||
383c93ff01 | |||
13d41bde7f | |||
d42d6fe25a | |||
beaac54dc9 | |||
70f8cb81b8 | |||
f8ca6b4867 | |||
49f5f67467 | |||
35d2ae3ef7 | |||
22ca572ae0 | |||
619fcbfabf | |||
292869141f | |||
ca9929214d | |||
121ad4e4bf | |||
2f87a4477e | |||
d72c511131 | |||
8b68c06547 | |||
b911151786 | |||
7531a2894b | |||
5b507a8944 | |||
d2f86cbf32 | |||
08dff6613b | |||
901ec15dc8 | |||
5284d604ef | |||
b2b4ab3f0c | |||
b646fc5a13 | |||
d35cbfd9c4 | |||
f25152e068 | |||
dd8946b15a | |||
305350fdc8 | |||
f31d5372e7 | |||
ca1a2bbe2c | |||
dba9199e58 | |||
e806903d7e | |||
41d8e3cbd7 | |||
5e32783c4e | |||
fdc3a4104b | |||
8199941a81 | |||
651d237200 | |||
6f5b380199 | |||
c746d77a06 | |||
9ab3841570 | |||
3a28741cc3 | |||
22f7a85cf2 | |||
86935068f5 | |||
00e12b776b | |||
3b96a9a8fa | |||
5ac5c767e0 | |||
f1d3d4a366 | |||
1160066f0d | |||
8d603d6162 | |||
076efc4cb2 | |||
2c62a34c2f | |||
2177aa2a6b | |||
e8a4902a3d | |||
e2952061af | |||
fcc4420cfe | |||
f5358aa1ca | |||
3d3f9a8609 | |||
1f176fcb7b | |||
3ca661127f | |||
407f9d9ef0 | |||
bff683e6d4 | |||
770da6317e | |||
cf3c2482c9 | |||
2001c5dec7 | |||
80cf716c98 | |||
37e1962845 | |||
f8c5d80c66 | |||
11841c47e6 | |||
71b1ac9f34 | |||
eda06df878 | |||
c4cb7ddc4f | |||
a8089b76c0 | |||
71516e6c72 | |||
88686ef065 | |||
0442b80a2c | |||
81c72c2038 | |||
3aa809b8c0 | |||
efa414c442 | |||
c39da093bf | |||
aa2c27bf69 | |||
1f92125a7f | |||
5c48b7dfab | |||
d664361b15 | |||
813de1c703 | |||
02f24117f0 | |||
7a7a937f1e | |||
0211ee3ef1 | |||
c569bfbe6d | |||
b925338688 | |||
2cf04d034a | |||
049aafd0a1 | |||
e0a04c5031 | |||
9d23ac562f | |||
0065a29901 | |||
8ea1ebaf1b | |||
5c2d3e430d | |||
b710b719a8 | |||
7df5091fdc | |||
5abb97362f | |||
b34239ebc6 | |||
7ef6c586c5 | |||
9d36cf4b5a | |||
04be2404ce | |||
7f4fd04cfe | |||
b2bcdb9d9b | |||
d81e2bb0b0 | |||
177c10bb0f | |||
304775952f | |||
ca00103ee2 | |||
3aa9f5c376 | |||
efc44c56a6 | |||
8b790a6dd9 | |||
f36930d812 | |||
232295bda7 | |||
451768ccf9 | |||
c1aaf89baa | |||
5ac528f141 | |||
204e3dca22 | |||
33aac2985a | |||
361ce7818e | |||
ad6e3a0868 | |||
fd2269ac15 | |||
14a8ead6b4 | |||
bbf0508846 | |||
79314ee67b | |||
86b0637ef7 | |||
1c982b0182 | |||
cd5faee7d7 | |||
ec1e27031a | |||
02889b7a11 | |||
0eff21a4f1 | |||
0680945839 | |||
631e670775 | |||
4edd2cff9f | |||
0235eb5c28 | |||
8804b035b2 | |||
54e3438e37 | |||
ddfed7bb87 | |||
70c04745ee | |||
63d4486855 | |||
1d0e6bf453 | |||
a2d88f6df4 | |||
019c77f9f7 | |||
5b5c5afc3a | |||
af20b5ee0e | |||
a1b779da15 | |||
8b31c638f3 | |||
6961a39cd2 | |||
3da69d8e53 | |||
dd76fb0ec7 | |||
caeab926bc | |||
35caa3c21a | |||
7022d3d401 | |||
6d22794cf9 | |||
b50e584369 | |||
affc2521aa | |||
63098b6f19 | |||
83e1dd285a | |||
b9beb3c7d2 | |||
2dd2555a63 | |||
126e6d13aa | |||
236c0166f6 | |||
9a33fb1f49 | |||
2c2c22ccf8 | |||
55597b458c | |||
f55297eca9 | |||
0bc8baf117 | |||
5f9270ed4b | |||
81fe41a038 | |||
0316cf88aa | |||
917f8a31e3 | |||
aa770b63fb | |||
c1bf31cb27 | |||
86d99f80c3 | |||
975f77756d | |||
8172dcd2d5 | |||
b95c27ceef | |||
f78bb90ed9 | |||
dc129fd886 | |||
621e0ba4a8 | |||
f6de472da2 | |||
4b37c46889 | |||
c371558883 | |||
0bbd0ac0b9 | |||
ac93c64cd4 | |||
6cd4375aff | |||
a606b47a22 | |||
a62155c1c9 | |||
b4f750e7db | |||
b19e315615 | |||
41dba376a8 | |||
2896f70cd8 | |||
1a8c972aef | |||
cdaa397dcf | |||
9e6fa8f29a | |||
4d599eb118 | |||
4e9039be2d | |||
395e265564 | |||
b07853c9ef | |||
b635a7e693 | |||
f84fc783b6 | |||
2301a934b0 | |||
60e9d2754a | |||
d06c2cacb1 | |||
49c2bd477c | |||
46a3b4de6e | |||
6ecc8c5496 | |||
a1ff3b1ee3 | |||
d4b522b6cb | |||
3b524e99cc | |||
3329d94c9b | |||
a12118f1a0 | |||
5fe33a98a2 | |||
1d8196e11a | |||
c7f6f94930 | |||
131615811b | |||
3fa6e22430 | |||
c86ac772c8 | |||
52420963cf | |||
addf5f4e52 | |||
03d7300732 | |||
a97d0a36f4 | |||
e9c52ec696 | |||
75f2dab3c8 |
17
.clang-format
Normal file
17
.clang-format
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: Chromium
|
||||||
|
IndentWidth: 4
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
ColumnLimit: 140
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AlignConsecutiveMacros: None
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
BraceWrapping:
|
||||||
|
AfterFunction: true
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: false
|
||||||
|
SplitEmptyNamespace: false
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
Cpp11BracedListStyle: false
|
4
.clang-tidy
Normal file
4
.clang-tidy
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Checks:
|
||||||
|
- modernize-use-using
|
||||||
|
|
||||||
|
SystemHeaders: false
|
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# EditorConfig specs and documentation: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# C++ Code Style settings
|
||||||
|
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||||
|
cpp_generate_documentation_comments = doxygen_slash_star
|
4
.git-blame-ignore-revs
Normal file
4
.git-blame-ignore-revs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# .git-blame-ignore-revs
|
||||||
|
|
||||||
|
# tabs -> spaces
|
||||||
|
bbb3b3e6f6e3c0f95873f22e6d0a4aaf350f49d9
|
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
open_collective: prismlauncher
|
20
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
20
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
description: File a bug report
|
description: File a bug report
|
||||||
labels: [bug, needs-triage]
|
labels: [bug]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
@ -8,9 +8,9 @@ body:
|
|||||||
If you need help with running Minecraft, please visit us on our Discord before making a bug report.
|
If you need help with running Minecraft, please visit us on our Discord before making a bug report.
|
||||||
|
|
||||||
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
||||||
* You have read the [FAQ](https://github.com/PolyMC/PolyMC/wiki/FAQ) and it has not answered your question
|
* You have read the [Prism Launcher wiki](https://prismlauncher.org/wiki/) and it has not answered your question.
|
||||||
* Your bug is not caused by Minecraft or any mods you have installed.
|
* Your bug is not caused by Minecraft or any mods you have installed.
|
||||||
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PolyMC/PolyMC/issues)
|
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PrismLauncher/PrismLauncher/issues)
|
||||||
|
|
||||||
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
|
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
@ -23,6 +23,20 @@ body:
|
|||||||
- macOS
|
- macOS
|
||||||
- Linux
|
- Linux
|
||||||
- Other
|
- Other
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Version of Prism Launcher
|
||||||
|
description: The version of Prism Launcher used in the bug report.
|
||||||
|
placeholder: Prism Launcher 5.0
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Version of Qt
|
||||||
|
description: The version of Qt used in the bug report. You can find it in Help -> About Prism Launcher -> About Qt.
|
||||||
|
placeholder: Qt 6.3.0
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Description of bug
|
label: Description of bug
|
||||||
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,5 +1,5 @@
|
|||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: PolyMC Matrix Support Room
|
- name: Prism Launcher Matrix Support Room
|
||||||
url: https://matrix.to/#/#support:polymc.org
|
url: https://matrix.to/#/#prism-support:matrix.org
|
||||||
about: Please ask for support here before opening an issue.
|
about: Please ask for support here before opening an issue.
|
||||||
|
68
.github/ISSUE_TEMPLATE/rfc.yml
vendored
Normal file
68
.github/ISSUE_TEMPLATE/rfc.yml
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# Template based on https://gitlab.archlinux.org/archlinux/rfcs/-/blob/0ba3b61e987e197f8d1901709409b8564958f78a/rfcs/0000-template.rst
|
||||||
|
name: Request for Comment (RFC)
|
||||||
|
description: Propose a larger change and start a discussion.
|
||||||
|
labels: [rfc]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
### Use this form to suggest a larger change for Prism Launcher.
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Goal
|
||||||
|
description: Short description, 1-2 sentences.
|
||||||
|
placeholder: Remove the cat from the launcher.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Motivation
|
||||||
|
description: |
|
||||||
|
Introduce the topic. If this is a not-well-known section of Prism Launcher, a detailed explanation of the background is recommended.
|
||||||
|
Some example points of discussion:
|
||||||
|
- What specific problems are you facing right now that you're trying to address?
|
||||||
|
- Are there any previous discussions? Link to them and summarize them (don't force your readers to read them though!).
|
||||||
|
- Is there any precedent set by other software? If so, link to resources.
|
||||||
|
placeholder: I don't like cats. I think many users also don't like cats.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Specification
|
||||||
|
description: A concrete, thorough explanation of what is being planned.
|
||||||
|
placeholder: Remove the cat button and all references to the cat from the codebase. Including resource files.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Drawbacks
|
||||||
|
description: Carefully consider every possible objection and issue with your proposal. This section should be updated as feedback comes in from discussion.
|
||||||
|
placeholder: Some users might like cats.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Unresolved Questions
|
||||||
|
description: |
|
||||||
|
Are there any portions of your proposal which need to be discussed with the community before the RFC can proceed?
|
||||||
|
Be careful here -- an RFC with a lot of remaining questions is likely to be stalled.
|
||||||
|
If your RFC is mostly unresolved questions and not too much substance, it may not be ready.
|
||||||
|
placeholder: Do a lot of users care about the cat?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Alternatives Considered
|
||||||
|
description: A list of alternatives, that have been considered and offer equal or similar features to the proposed change.
|
||||||
|
placeholder: Maybe the cat could be replaced with an axolotl?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: This suggestion is unique
|
||||||
|
options:
|
||||||
|
- label: I have searched the issue tracker and did not find an issue describing my suggestion, especially not one that has been rejected.
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: You may use the editor below to elaborate further.
|
10
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
10
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@ -1,29 +1,29 @@
|
|||||||
name: Suggestion
|
name: Suggestion
|
||||||
description: Make a suggestion
|
description: Make a suggestion
|
||||||
labels: [idea, needs-triage]
|
labels: [enhancement]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
### Use this form to suggest a feature for PolyMC.
|
### Use this form to suggest a feature for Prism Launcher.
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Role
|
label: Role
|
||||||
description: In what way do you use PolyMC that needs this feature?
|
description: In what way do you use Prism Launcher that needs this feature?
|
||||||
placeholder: I play modded Minecraft.
|
placeholder: I play modded Minecraft.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Suggestion
|
label: Suggestion
|
||||||
description: What do you want PolyMC to do?
|
description: What do you want Prism Launcher to do?
|
||||||
placeholder: I want the cat button to meow.
|
placeholder: I want the cat button to meow.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Benefit
|
label: Benefit
|
||||||
description: Why do you need PolyMC to do this?
|
description: Why do you need Prism Launcher to do this?
|
||||||
placeholder: so that I can always hear a cat when I need to.
|
placeholder: so that I can always hear a cat when I need to.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
3
.github/codeql/codeql-config.yml
vendored
Normal file
3
.github/codeql/codeql-config.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
query-filters:
|
||||||
|
- exclude:
|
||||||
|
id: cpp/fixme-comment
|
2
.github/dco.yml
vendored
Normal file
2
.github/dco.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
allowRemediationCommits:
|
||||||
|
individual: true
|
9
.github/pull_request_template.md
vendored
Normal file
9
.github/pull_request_template.md
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<!--
|
||||||
|
Hey there! Thanks for your contribution.
|
||||||
|
|
||||||
|
Please make sure that your commits are signed off first.
|
||||||
|
If you don't know how that works, check out our contribution guidelines: https://github.com/PrismLauncher/PrismLauncher/blob/develop/CONTRIBUTING.md#signing-your-work
|
||||||
|
If you already created your commits, you can run `git rebase --signoff develop` to retroactively sign-off all your commits and `git push --force` to override what you have pushed already.
|
||||||
|
|
||||||
|
Note that signing and signing-off are two different things!
|
||||||
|
-->
|
41
.github/scripts/prepare_JREs.sh
vendored
Executable file
41
.github/scripts/prepare_JREs.sh
vendored
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
URL_JDK8="https://api.adoptium.net/v3/binary/version/jdk8u312-b07/linux/x64/jre/hotspot/normal/eclipse"
|
||||||
|
URL_JDK17="https://api.adoptium.net/v3/binary/latest/17/ga/linux/x64/jre/hotspot/normal/eclipse"
|
||||||
|
|
||||||
|
mkdir -p JREs
|
||||||
|
pushd JREs
|
||||||
|
|
||||||
|
wget --content-disposition "$URL_JDK8"
|
||||||
|
wget --content-disposition "$URL_JDK17"
|
||||||
|
|
||||||
|
for file in *;
|
||||||
|
do
|
||||||
|
mkdir temp
|
||||||
|
|
||||||
|
re='(OpenJDK([[:digit:]]+)U-jre_x64_linux_hotspot_([[:digit:]]+)(.*).tar.gz)'
|
||||||
|
if [[ $file =~ $re ]];
|
||||||
|
then
|
||||||
|
version_major=${BASH_REMATCH[2]}
|
||||||
|
version_trailing=${BASH_REMATCH[4]}
|
||||||
|
|
||||||
|
if [ $version_major = 17 ];
|
||||||
|
then
|
||||||
|
hyphen='-'
|
||||||
|
else
|
||||||
|
hyphen=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
version_edit=$(echo $version_trailing | sed -e 's/_/+/g' | sed -e 's/b/-b/g')
|
||||||
|
dir_name=jdk$hyphen$version_major$version_edit-jre
|
||||||
|
mkdir jre$version_major
|
||||||
|
tar -xzf $file -C temp
|
||||||
|
pushd temp/$dir_name
|
||||||
|
cp -r . ../../jre$version_major
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf temp
|
||||||
|
done
|
||||||
|
|
||||||
|
popd
|
32
.github/workflows/backport.yml
vendored
Normal file
32
.github/workflows/backport.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: Backport
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed, labeled]
|
||||||
|
|
||||||
|
# WARNING:
|
||||||
|
# When extending this action, be aware that $GITHUB_TOKEN allows write access to
|
||||||
|
# the GitHub repository. This means that it should not evaluate user input in a
|
||||||
|
# way that allows code injection.
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
backport:
|
||||||
|
permissions:
|
||||||
|
contents: write # for korthout/backport-action to create branch
|
||||||
|
pull-requests: write # for korthout/backport-action to create PR to backport
|
||||||
|
name: Backport Pull Request
|
||||||
|
if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
- name: Create backport PRs
|
||||||
|
uses: korthout/backport-action@v2.1.0
|
||||||
|
with:
|
||||||
|
# Config README: https://github.com/korthout/backport-action#backport-action
|
||||||
|
pull_description: |-
|
||||||
|
Bot-based backport to `${target_branch}`, triggered by a label in #${pull_number}.
|
||||||
|
|
610
.github/workflows/build.yml
vendored
Normal file
610
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,610 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
build_type:
|
||||||
|
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
|
||||||
|
type: string
|
||||||
|
default: Debug
|
||||||
|
is_qt_cached:
|
||||||
|
description: Enable Qt caching or not
|
||||||
|
type: string
|
||||||
|
default: true
|
||||||
|
secrets:
|
||||||
|
SPARKLE_ED25519_KEY:
|
||||||
|
description: Private key for signing Sparkle updates
|
||||||
|
required: false
|
||||||
|
WINDOWS_CODESIGN_CERT:
|
||||||
|
description: Certificate for signing Windows builds
|
||||||
|
required: false
|
||||||
|
WINDOWS_CODESIGN_PASSWORD:
|
||||||
|
description: Password for signing Windows builds
|
||||||
|
required: false
|
||||||
|
CACHIX_AUTH_TOKEN:
|
||||||
|
description: Private token for authenticating against Cachix cache
|
||||||
|
required: false
|
||||||
|
GPG_PRIVATE_KEY:
|
||||||
|
description: Private key for AppImage signing
|
||||||
|
required: false
|
||||||
|
GPG_PRIVATE_KEY_ID:
|
||||||
|
description: ID for the GPG_PRIVATE_KEY, to select the signing key
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
qt_ver: 5
|
||||||
|
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
qt_ver: 6
|
||||||
|
qt_host: linux
|
||||||
|
qt_arch: ""
|
||||||
|
qt_version: "6.2.4"
|
||||||
|
qt_modules: "qt5compat qtimageformats"
|
||||||
|
qt_tools: ""
|
||||||
|
|
||||||
|
- os: windows-2022
|
||||||
|
name: "Windows-MinGW-w64"
|
||||||
|
msystem: clang64
|
||||||
|
vcvars_arch: "amd64_x86"
|
||||||
|
|
||||||
|
- os: windows-2022
|
||||||
|
name: "Windows-MSVC"
|
||||||
|
msystem: ""
|
||||||
|
architecture: "x64"
|
||||||
|
vcvars_arch: "amd64"
|
||||||
|
qt_ver: 6
|
||||||
|
qt_host: windows
|
||||||
|
qt_arch: ''
|
||||||
|
qt_version: '6.6.0'
|
||||||
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
|
qt_tools: ''
|
||||||
|
|
||||||
|
- os: windows-2022
|
||||||
|
name: "Windows-MSVC-arm64"
|
||||||
|
msystem: ""
|
||||||
|
architecture: "arm64"
|
||||||
|
vcvars_arch: "amd64_arm64"
|
||||||
|
qt_ver: 6
|
||||||
|
qt_host: windows
|
||||||
|
qt_arch: 'win64_msvc2019_arm64'
|
||||||
|
qt_version: '6.6.0'
|
||||||
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
|
qt_tools: ''
|
||||||
|
|
||||||
|
- os: macos-12
|
||||||
|
name: macOS
|
||||||
|
macosx_deployment_target: 11.0
|
||||||
|
qt_ver: 6
|
||||||
|
qt_host: mac
|
||||||
|
qt_arch: ''
|
||||||
|
qt_version: '6.6.0'
|
||||||
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
|
qt_tools: ''
|
||||||
|
|
||||||
|
- os: macos-12
|
||||||
|
name: macOS-Legacy
|
||||||
|
macosx_deployment_target: 10.13
|
||||||
|
qt_ver: 5
|
||||||
|
qt_host: mac
|
||||||
|
qt_version: "5.15.2"
|
||||||
|
qt_modules: ""
|
||||||
|
qt_tools: ""
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||||
|
INSTALL_DIR: "install"
|
||||||
|
INSTALL_PORTABLE_DIR: "install-portable"
|
||||||
|
INSTALL_APPIMAGE_DIR: "install-appdir"
|
||||||
|
BUILD_DIR: "build"
|
||||||
|
CCACHE_VAR: ""
|
||||||
|
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||||
|
|
||||||
|
steps:
|
||||||
|
##
|
||||||
|
# PREPARE
|
||||||
|
##
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: "true"
|
||||||
|
|
||||||
|
- name: "Setup MSYS2"
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: ${{ matrix.msystem }}
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
git
|
||||||
|
mingw-w64-x86_64-binutils
|
||||||
|
pacboy: >-
|
||||||
|
toolchain:p
|
||||||
|
cmake:p
|
||||||
|
extra-cmake-modules:p
|
||||||
|
ninja:p
|
||||||
|
qt6-base:p
|
||||||
|
qt6-svg:p
|
||||||
|
qt6-imageformats:p
|
||||||
|
quazip-qt6:p
|
||||||
|
ccache:p
|
||||||
|
qt6-5compat:p
|
||||||
|
cmark:p
|
||||||
|
|
||||||
|
- name: Force newer ccache
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug'
|
||||||
|
run: |
|
||||||
|
choco install ccache --version 4.7.1
|
||||||
|
|
||||||
|
- name: Setup ccache
|
||||||
|
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
|
||||||
|
uses: hendrikmuhs/ccache-action@v1.2.10
|
||||||
|
with:
|
||||||
|
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
|
||||||
|
|
||||||
|
- name: Retrieve ccache cache (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
||||||
|
uses: actions/cache@v3.3.2
|
||||||
|
with:
|
||||||
|
path: '${{ github.workspace }}\.ccache'
|
||||||
|
key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ matrix.os }}-mingw-w64-ccache
|
||||||
|
|
||||||
|
- name: Setup ccache (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
|
||||||
|
ccache --set-config=max_size='500M'
|
||||||
|
ccache --set-config=compression=true
|
||||||
|
ccache -p # Show config
|
||||||
|
ccache -z # Zero stats
|
||||||
|
|
||||||
|
- name: Use ccache on Debug builds only
|
||||||
|
if: inputs.build_type == 'Debug'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set short version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
ver_short=`git rev-parse --short HEAD`
|
||||||
|
echo "VERSION=$ver_short" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Install Dependencies (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install ninja-build extra-cmake-modules scdoc appstream
|
||||||
|
|
||||||
|
- name: Install Dependencies (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
brew update
|
||||||
|
brew install ninja extra-cmake-modules
|
||||||
|
|
||||||
|
- name: Install Qt (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
||||||
|
|
||||||
|
- name: Install host Qt (Windows MSVC arm64)
|
||||||
|
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
aqtversion: "==3.1.*"
|
||||||
|
py7zrversion: ">=0.20.2"
|
||||||
|
version: ${{ matrix.qt_version }}
|
||||||
|
host: "windows"
|
||||||
|
target: "desktop"
|
||||||
|
arch: ""
|
||||||
|
modules: ${{ matrix.qt_modules }}
|
||||||
|
tools: ${{ matrix.qt_tools }}
|
||||||
|
cache: ${{ inputs.is_qt_cached }}
|
||||||
|
cache-key-prefix: host-qt-arm64-windows
|
||||||
|
dir: ${{ github.workspace }}\HostQt
|
||||||
|
set-env: false
|
||||||
|
|
||||||
|
- name: Install Qt (macOS, Linux, Qt 6 & Windows MSVC)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '')
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
aqtversion: "==3.1.*"
|
||||||
|
py7zrversion: ">=0.20.2"
|
||||||
|
version: ${{ matrix.qt_version }}
|
||||||
|
host: ${{ matrix.qt_host }}
|
||||||
|
target: "desktop"
|
||||||
|
arch: ${{ matrix.qt_arch }}
|
||||||
|
modules: ${{ matrix.qt_modules }}
|
||||||
|
tools: ${{ matrix.qt_tools }}
|
||||||
|
cache: ${{ inputs.is_qt_cached }}
|
||||||
|
|
||||||
|
- name: Install MSVC (Windows MSVC)
|
||||||
|
if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
with:
|
||||||
|
vsversion: 2022
|
||||||
|
arch: ${{ matrix.vcvars_arch }}
|
||||||
|
|
||||||
|
- name: Prepare AppImage (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
|
run: |
|
||||||
|
wget "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
||||||
|
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage"
|
||||||
|
wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
|
||||||
|
|
||||||
|
wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage"
|
||||||
|
|
||||||
|
${{ github.workspace }}/.github/scripts/prepare_JREs.sh
|
||||||
|
sudo apt install libopengl0
|
||||||
|
|
||||||
|
- name: Add QT_HOST_PATH var (Windows MSVC arm64)
|
||||||
|
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
|
||||||
|
run: |
|
||||||
|
echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2019_64" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
|
##
|
||||||
|
# CONFIGURE
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Configure CMake (macOS)
|
||||||
|
if: runner.os == 'macOS' && matrix.qt_ver == 6
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -G Ninja
|
||||||
|
|
||||||
|
- name: Configure CMake (macOS-Legacy)
|
||||||
|
if: runner.os == 'macOS' && matrix.qt_ver == 5
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja
|
||||||
|
|
||||||
|
- name: Configure CMake (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja
|
||||||
|
|
||||||
|
- name: Configure CMake (Windows MSVC)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }}
|
||||||
|
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
|
||||||
|
if ("${{ env.CCACHE_VAR }}")
|
||||||
|
{
|
||||||
|
Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe
|
||||||
|
echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV
|
||||||
|
echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV
|
||||||
|
echo "TrackFileAccess=false" >> $env:GITHUB_ENV
|
||||||
|
}
|
||||||
|
# Needed for ccache, but also speeds up compile
|
||||||
|
echo "UseMultiToolTask=true" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Configure CMake (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=official -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja
|
||||||
|
|
||||||
|
##
|
||||||
|
# BUILD
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
run: |
|
||||||
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
- name: Build (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake --build ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
- name: Build (Windows MSVC)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||||
|
run: |
|
||||||
|
cmake --build ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
|
||||||
|
|
||||||
|
##
|
||||||
|
# TEST
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
run: |
|
||||||
|
ctest -E "^example64|example$" --test-dir build --output-on-failure
|
||||||
|
|
||||||
|
- name: Test (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
ctest -E "^example64|example$" --test-dir build --output-on-failure
|
||||||
|
|
||||||
|
- name: Test (Windows MSVC)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64'
|
||||||
|
run: |
|
||||||
|
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
|
||||||
|
|
||||||
|
##
|
||||||
|
# PACKAGE BUILDS
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Package (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }}
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
chmod +x "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||||
|
sudo codesign --sign - --deep --force --entitlements "../program_info/App.entitlements" --options runtime "PrismLauncher.app/Contents/MacOS/prismlauncher"
|
||||||
|
mv "PrismLauncher.app" "Prism Launcher.app"
|
||||||
|
tar -czf ../PrismLauncher.tar.gz *
|
||||||
|
|
||||||
|
- name: Make Sparkle signature (macOS)
|
||||||
|
if: matrix.name == 'macOS'
|
||||||
|
run: |
|
||||||
|
if [ '${{ secrets.SPARKLE_ED25519_KEY }}' != '' ]; then
|
||||||
|
brew install openssl@3
|
||||||
|
echo '${{ secrets.SPARKLE_ED25519_KEY }}' > ed25519-priv.pem
|
||||||
|
signature=$(/usr/local/opt/openssl@3/bin/openssl pkeyutl -sign -rawin -in ${{ github.workspace }}/PrismLauncher.tar.gz -inkey ed25519-priv.pem | openssl base64 | tr -d \\n)
|
||||||
|
rm ed25519-priv.pem
|
||||||
|
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||||
|
### Artifact Information :information_source:
|
||||||
|
- :memo: Sparkle Signature (ed25519): \`$signature\`
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat >> $GITHUB_STEP_SUMMARY << EOF
|
||||||
|
### Artifact Information :information_source:
|
||||||
|
- :warning: Sparkle Signature (ed25519): No private key available (likely a pull request or fork)
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Package (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }}
|
||||||
|
touch ${{ env.INSTALL_DIR }}/manifest.txt
|
||||||
|
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt
|
||||||
|
|
||||||
|
- name: Package (Windows MSVC)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
if ("${{ matrix.qt_ver }}" -eq "5")
|
||||||
|
{
|
||||||
|
Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
|
||||||
|
Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
|
||||||
|
}
|
||||||
|
cd ${{ github.workspace }}
|
||||||
|
|
||||||
|
Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||||
|
|
||||||
|
- name: Fetch codesign certificate (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: bash # yes, we are not using MSYS2 or PowerShell here
|
||||||
|
run: |
|
||||||
|
echo '${{ secrets.WINDOWS_CODESIGN_CERT }}' | base64 --decode > codesign.pfx
|
||||||
|
|
||||||
|
- name: Sign executable (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: |
|
||||||
|
if (Get-Content ./codesign.pfx){
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
# We ship the exact same executable for portable and non-portable editions, so signing just once is fine
|
||||||
|
SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_updater.exe prismlauncher_filelink.exe
|
||||||
|
} else {
|
||||||
|
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Package (Windows MinGW-w64, portable)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||||
|
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
|
||||||
|
|
||||||
|
- name: Package (Windows MSVC, portable)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem == ''
|
||||||
|
run: |
|
||||||
|
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||||
|
|
||||||
|
Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt
|
||||||
|
|
||||||
|
- name: Package (Windows, installer)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: |
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
makensis -NOCD "${{ github.workspace }}/${{ env.BUILD_DIR }}/program_info/win_install.nsi"
|
||||||
|
|
||||||
|
- name: Sign installer (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: |
|
||||||
|
if (Get-Content ./codesign.pfx){
|
||||||
|
SignTool sign /fd sha256 /td sha256 /f codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com PrismLauncher-Setup.exe
|
||||||
|
} else {
|
||||||
|
":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Package (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }}
|
||||||
|
for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_DIR }}/manifest.txt
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_DIR }}
|
||||||
|
tar --owner root --group root -czf ../PrismLauncher.tar.gz *
|
||||||
|
|
||||||
|
- name: Package (Linux, portable)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }}
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
|
||||||
|
for l in $(find ${{ env.INSTALL_PORTABLE_DIR }} -type f); do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_PORTABLE_DIR }}/}; l=${l#./}; echo $l; done > ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt
|
||||||
|
|
||||||
|
|
||||||
|
cd ${{ env.INSTALL_PORTABLE_DIR }}
|
||||||
|
tar -czf ../PrismLauncher-portable.tar.gz *
|
||||||
|
|
||||||
|
- name: Package AppImage (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
run: |
|
||||||
|
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr
|
||||||
|
|
||||||
|
mv ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.metainfo.xml ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/metainfo/org.prismlauncher.PrismLauncher.appdata.xml
|
||||||
|
export "NO_APPSTREAM=1" # we have to skip appstream checking because appstream on ubuntu 20.04 is outdated
|
||||||
|
|
||||||
|
export OUTPUT="PrismLauncher-Linux-x86_64.AppImage"
|
||||||
|
|
||||||
|
chmod +x linuxdeploy-*.AppImage
|
||||||
|
|
||||||
|
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-{8,17}-openjdk
|
||||||
|
mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
|
||||||
|
|
||||||
|
cp -r ${{ github.workspace }}/JREs/jre8/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk
|
||||||
|
|
||||||
|
cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk
|
||||||
|
|
||||||
|
cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines
|
||||||
|
|
||||||
|
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||||
|
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||||
|
cp /usr/lib/x86_64-linux-gnu/libOpenGL.so.0* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64/server"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-8-openjdk/lib/amd64"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib/server"
|
||||||
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib"
|
||||||
|
export LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
chmod +x AppImageUpdate-x86_64.AppImage
|
||||||
|
cp AppImageUpdate-x86_64.AppImage ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin
|
||||||
|
|
||||||
|
export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync"
|
||||||
|
|
||||||
|
if [ '${{ secrets.GPG_PRIVATE_KEY_ID }}' != '' ]; then
|
||||||
|
export SIGN=1
|
||||||
|
export SIGN_KEY=${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||||
|
mkdir -p ~/.gnupg/
|
||||||
|
echo "$GPG_PRIVATE_KEY" > ~/.gnupg/private.key
|
||||||
|
gpg --import ~/.gnupg/private.key
|
||||||
|
else
|
||||||
|
echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
|
||||||
|
./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg
|
||||||
|
|
||||||
|
mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage"
|
||||||
|
|
||||||
|
##
|
||||||
|
# UPLOAD BUILDS
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Upload binary tarball (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PrismLauncher.tar.gz
|
||||||
|
|
||||||
|
- name: Upload binary zip (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ matrix.name }}-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: ${{ env.INSTALL_DIR }}/**
|
||||||
|
|
||||||
|
- name: Upload binary zip (Windows, portable)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ matrix.name }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: ${{ env.INSTALL_PORTABLE_DIR }}/**
|
||||||
|
|
||||||
|
- name: Upload installer (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ matrix.name }}-Setup-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PrismLauncher-Setup.exe
|
||||||
|
|
||||||
|
- name: Upload binary tarball (Linux, Qt 5)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ runner.os }}-Qt5-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PrismLauncher.tar.gz
|
||||||
|
|
||||||
|
- name: Upload binary tarball (Linux, portable, Qt 5)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 6
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PrismLauncher-portable.tar.gz
|
||||||
|
|
||||||
|
- name: Upload binary tarball (Linux, Qt 6)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver !=5
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ runner.os }}-Qt6-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PrismLauncher.tar.gz
|
||||||
|
|
||||||
|
- name: Upload binary tarball (Linux, portable, Qt 6)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ runner.os }}-Qt6-Portable-${{ env.VERSION }}-${{ inputs.build_type }}
|
||||||
|
path: PrismLauncher-portable.tar.gz
|
||||||
|
|
||||||
|
- name: Upload AppImage (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
|
path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage
|
||||||
|
|
||||||
|
- name: Upload AppImage Zsync (Linux)
|
||||||
|
if: runner.os == 'Linux' && matrix.qt_ver != 5
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync
|
||||||
|
path: PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||||
|
|
||||||
|
- name: ccache stats (Windows MinGW-w64)
|
||||||
|
if: runner.os == 'Windows' && matrix.msystem != ''
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
ccache -s
|
||||||
|
|
||||||
|
flatpak:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
|
||||||
|
options: --privileged
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
if: inputs.build_type == 'Debug'
|
||||||
|
with:
|
||||||
|
submodules: "true"
|
||||||
|
- name: Build Flatpak (Linux)
|
||||||
|
if: inputs.build_type == 'Debug'
|
||||||
|
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||||
|
with:
|
||||||
|
bundle: "Prism Launcher.flatpak"
|
||||||
|
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
|
35
.github/workflows/codeql.yml
vendored
Normal file
35
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: "CodeQL Code Scanning"
|
||||||
|
|
||||||
|
on: [ push, pull_request, workflow_dispatch ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
CodeQL:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
|
queries: security-and-quality
|
||||||
|
languages: cpp, java
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run:
|
||||||
|
sudo apt-get -y update
|
||||||
|
|
||||||
|
sudo apt-get -y install ninja-build extra-cmake-modules scdoc qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
|
||||||
|
|
||||||
|
- name: Configure and Build
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DLauncher_QT_VERSION_MAJOR=5 -G Ninja
|
||||||
|
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
37
.github/workflows/trigger_builds.yml
vendored
Normal file
37
.github/workflows/trigger_builds.yml
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
name: Build Application
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- "renovate/**"
|
||||||
|
paths-ignore:
|
||||||
|
- "**.md"
|
||||||
|
- "**/LICENSE"
|
||||||
|
- "flake.lock"
|
||||||
|
- "packages/**"
|
||||||
|
- ".github/ISSUE_TEMPLATE/**"
|
||||||
|
- ".markdownlint**"
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- "**.md"
|
||||||
|
- "**/LICENSE"
|
||||||
|
- "flake.lock"
|
||||||
|
- "packages/**"
|
||||||
|
- ".github/ISSUE_TEMPLATE/**"
|
||||||
|
- ".markdownlint**"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_debug:
|
||||||
|
name: Build Debug
|
||||||
|
uses: ./.github/workflows/build.yml
|
||||||
|
with:
|
||||||
|
build_type: Debug
|
||||||
|
is_qt_cached: true
|
||||||
|
secrets:
|
||||||
|
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||||
|
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
|
||||||
|
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
|
||||||
|
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||||
|
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
107
.github/workflows/trigger_release.yml
vendored
Normal file
107
.github/workflows/trigger_release.yml
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
name: Build Application and Make Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_release:
|
||||||
|
name: Build Release
|
||||||
|
uses: ./.github/workflows/build.yml
|
||||||
|
with:
|
||||||
|
build_type: Release
|
||||||
|
is_qt_cached: false
|
||||||
|
secrets:
|
||||||
|
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
|
||||||
|
WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }}
|
||||||
|
WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }}
|
||||||
|
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||||
|
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }}
|
||||||
|
|
||||||
|
create_release:
|
||||||
|
needs: build_release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: "true"
|
||||||
|
path: "PrismLauncher-source"
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
- name: Grab and store version
|
||||||
|
run: |
|
||||||
|
tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$")
|
||||||
|
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
||||||
|
- name: Package artifacts properly
|
||||||
|
run: |
|
||||||
|
mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }}
|
||||||
|
mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||||
|
mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||||
|
mv PrismLauncher-Linux-Qt5-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
|
||||||
|
mv PrismLauncher-Linux-Qt5*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt5-${{ env.VERSION }}.tar.gz
|
||||||
|
mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage
|
||||||
|
mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||||
|
mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||||
|
mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
|
||||||
|
|
||||||
|
tar --exclude='.git' -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
|
||||||
|
|
||||||
|
for d in PrismLauncher-Windows-MSVC*; do
|
||||||
|
cd "${d}" || continue
|
||||||
|
LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
|
||||||
|
ARM64="$(echo -n ${d} | grep -o arm64 || true)"
|
||||||
|
INST="$(echo -n ${d} | grep -o Setup || true)"
|
||||||
|
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||||
|
NAME="PrismLauncher-Windows-MSVC"
|
||||||
|
test -z "${LEGACY}" || NAME="${NAME}-Legacy"
|
||||||
|
test -z "${ARM64}" || NAME="${NAME}-arm64"
|
||||||
|
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||||
|
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||||
|
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
|
||||||
|
for d in PrismLauncher-Windows-MinGW-w64*; do
|
||||||
|
cd "${d}" || continue
|
||||||
|
INST="$(echo -n ${d} | grep -o Setup || true)"
|
||||||
|
PORT="$(echo -n ${d} | grep -o Portable || true)"
|
||||||
|
NAME="PrismLauncher-Windows-MinGW-w64"
|
||||||
|
test -z "${PORT}" || NAME="${NAME}-Portable"
|
||||||
|
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
|
||||||
|
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
id: create_release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
name: Prism Launcher ${{ env.VERSION }}
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
files: |
|
||||||
|
PrismLauncher-Linux-Qt5-${{ env.VERSION }}.tar.gz
|
||||||
|
PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz
|
||||||
|
PrismLauncher-Linux-x86_64.AppImage
|
||||||
|
PrismLauncher-Linux-x86_64.AppImage.zsync
|
||||||
|
PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
|
||||||
|
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
|
||||||
|
PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip
|
||||||
|
PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
|
||||||
|
PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
|
||||||
|
PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip
|
||||||
|
PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
|
||||||
|
PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
|
||||||
|
PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip
|
||||||
|
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
|
||||||
|
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe
|
||||||
|
PrismLauncher-macOS-${{ env.VERSION }}.tar.gz
|
||||||
|
PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz
|
||||||
|
PrismLauncher-${{ env.VERSION }}.tar.gz
|
30
.github/workflows/update-flake.yml
vendored
Normal file
30
.github/workflows/update-flake.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
name: Update Flake Lockfile
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# run weekly on sunday
|
||||||
|
- cron: "0 0 * * 0"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-flake:
|
||||||
|
if: github.repository == 'PrismLauncher/PrismLauncher'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23
|
||||||
|
|
||||||
|
- uses: DeterminateSystems/update-flake-lock@v20
|
||||||
|
with:
|
||||||
|
commit-msg: "chore(nix): update lockfile"
|
||||||
|
pr-title: "chore(nix): update lockfile"
|
||||||
|
pr-labels: |
|
||||||
|
Linux
|
||||||
|
packaging
|
||||||
|
simple change
|
||||||
|
changelog:omit
|
15
.github/workflows/winget.yml
vendored
Normal file
15
.github/workflows/winget.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
name: Publish to WinGet
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [released]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: vedantmgoyal2009/winget-releaser@v2
|
||||||
|
with:
|
||||||
|
identifier: PrismLauncher.PrismLauncher
|
||||||
|
version: ${{ github.event.release.tag_name }}
|
||||||
|
installers-regex: 'PrismLauncher-Windows-MSVC(:?-arm64|-Legacy)?-Setup-.+\.exe$'
|
||||||
|
token: ${{ secrets.WINGET_TOKEN }}
|
22
.gitignore
vendored
22
.gitignore
vendored
@ -11,9 +11,14 @@ html/
|
|||||||
*.pro.user
|
*.pro.user
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
CMakeLists.txt.user.*
|
CMakeLists.txt.user.*
|
||||||
|
CMakeSettings.json
|
||||||
|
/CMakeFiles
|
||||||
|
CMakeCache.txt
|
||||||
/.project
|
/.project
|
||||||
/.settings
|
/.settings
|
||||||
/.idea
|
/.idea
|
||||||
|
/.vscode
|
||||||
|
/.vs
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
Debug
|
Debug
|
||||||
|
|
||||||
@ -40,13 +45,14 @@ run/
|
|||||||
|
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
# Flatpak builds
|
# Nix/NixOS
|
||||||
|
.direnv/
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
result
|
||||||
|
|
||||||
|
# Flatpak
|
||||||
.flatpak-builder
|
.flatpak-builder
|
||||||
flatbuild
|
flatbuild
|
||||||
builddir
|
|
||||||
# Deb
|
# Snap
|
||||||
packages/debian/polymc/usr/
|
*.snap
|
||||||
packages/debian/polymc.deb
|
|
||||||
packages/debian/polymc/DEBIAN/control
|
|
||||||
# Nix/NixOS
|
|
||||||
result/
|
|
||||||
|
30
.gitmodules
vendored
30
.gitmodules
vendored
@ -1,8 +1,24 @@
|
|||||||
[submodule "depends/libnbtplusplus"]
|
|
||||||
path = libraries/libnbtplusplus
|
|
||||||
url = https://github.com/MultiMC/libnbtplusplus.git
|
|
||||||
pushurl = git@github.com:MultiMC/libnbtplusplus.git
|
|
||||||
[submodule "libraries/quazip"]
|
[submodule "libraries/quazip"]
|
||||||
path = libraries/quazip
|
path = libraries/quazip
|
||||||
url = https://github.com/PolyMC/quazip.git
|
url = https://github.com/stachenov/quazip.git
|
||||||
pushurl = git@github.com:PolyMC/quazip.git
|
[submodule "libraries/tomlplusplus"]
|
||||||
|
path = libraries/tomlplusplus
|
||||||
|
url = https://github.com/marzer/tomlplusplus.git
|
||||||
|
[submodule "libraries/filesystem"]
|
||||||
|
path = libraries/filesystem
|
||||||
|
url = https://github.com/gulrak/filesystem
|
||||||
|
[submodule "libraries/libnbtplusplus"]
|
||||||
|
path = libraries/libnbtplusplus
|
||||||
|
url = https://github.com/PrismLauncher/libnbtplusplus.git
|
||||||
|
[submodule "libraries/zlib"]
|
||||||
|
path = libraries/zlib
|
||||||
|
url = https://github.com/madler/zlib.git
|
||||||
|
[submodule "libraries/extra-cmake-modules"]
|
||||||
|
path = libraries/extra-cmake-modules
|
||||||
|
url = https://github.com/KDE/extra-cmake-modules
|
||||||
|
[submodule "libraries/cmark"]
|
||||||
|
path = libraries/cmark
|
||||||
|
url = https://github.com/commonmark/cmark.git
|
||||||
|
[submodule "flatpak/shared-modules"]
|
||||||
|
path = flatpak/shared-modules
|
||||||
|
url = https://github.com/flathub/shared-modules.git
|
||||||
|
12
.markdownlint.yaml
Normal file
12
.markdownlint.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# MD013/line-length - Line length
|
||||||
|
MD013: false
|
||||||
|
|
||||||
|
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
|
||||||
|
MD024:
|
||||||
|
siblings-only: true
|
||||||
|
|
||||||
|
# MD033/no-inline-html Inline HTML
|
||||||
|
MD033: false
|
||||||
|
|
||||||
|
# MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading
|
||||||
|
MD041: false
|
2
.markdownlintignore
Normal file
2
.markdownlintignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
libraries/nbtplusplus
|
||||||
|
libraries/quazip
|
245
BUILD.md
245
BUILD.md
@ -1,244 +1,3 @@
|
|||||||
Build Instructions
|
# Build Instructions
|
||||||
==================
|
|
||||||
|
|
||||||
# Contents
|
Full build instructions are available on [the website](https://prismlauncher.org/wiki/development/build-instructions/).
|
||||||
|
|
||||||
* [Note](#note)
|
|
||||||
* [Getting the source](#source)
|
|
||||||
* [Linux](#linux)
|
|
||||||
* [Windows](#windows)
|
|
||||||
* [macOS](#macos)
|
|
||||||
|
|
||||||
|
|
||||||
# Getting the source
|
|
||||||
|
|
||||||
Clone the source code using git and grab all the submodules:
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/PolyMC/PolyMC.git
|
|
||||||
git submodule init
|
|
||||||
git submodule update
|
|
||||||
```
|
|
||||||
|
|
||||||
# Linux
|
|
||||||
|
|
||||||
Getting the project to build and run on Linux is easy if you use any modern and up-to-date linux distribution.
|
|
||||||
|
|
||||||
## Build dependencies
|
|
||||||
* A C++ compiler capable of building C++11 code.
|
|
||||||
* Qt Development tools 5.6 or newer (`qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5` on Debian-based system)
|
|
||||||
* cmake 3.1 or newer (`cmake` on Debian-based system)
|
|
||||||
* zlib (`zlib1g-dev` on Debian-based system)
|
|
||||||
* Java JDK (`openjdk-17-jdk`on Debian-based system)
|
|
||||||
* GL headers (`libgl1-mesa-dev` on Debian-based system)
|
|
||||||
|
|
||||||
### Building a .deb
|
|
||||||
|
|
||||||
You need to install the build dependencies first
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/PolyMC/PolyMC.git
|
|
||||||
git submodule init && git submodule update
|
|
||||||
cd packages/debian
|
|
||||||
./makedeb.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
If everything works correctly, the .deb will be next to the build script, in `PolyMC/packages/debian`
|
|
||||||
|
|
||||||
### Building a .rpm
|
|
||||||
|
|
||||||
You don't need to install the build dependencies, as the script will use `dnf` to install them for you.
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/PolyMC/PolyMC.git
|
|
||||||
cd packages/rpm
|
|
||||||
./makerpm.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
If everything works correctly, the .rpm will be next to the build script, in `PolyMC/packages/rpm`
|
|
||||||
|
|
||||||
### Building from command line
|
|
||||||
You need a source folder, a build folder and an install folder.
|
|
||||||
|
|
||||||
```
|
|
||||||
# make all the folders
|
|
||||||
mkdir ~/PolyMC && cd ~/PolyMC
|
|
||||||
mkdir build
|
|
||||||
mkdir install
|
|
||||||
# clone the complete source
|
|
||||||
git clone --recursive https://github.com/PolyMC/PolyMC.git src
|
|
||||||
# configure the project
|
|
||||||
cd build
|
|
||||||
cmake -DCMAKE_INSTALL_PREFIX=../install ../src
|
|
||||||
make -j$(nproc) install
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use IDEs like KDevelop or QtCreator to open the CMake project if you want to work on the code.
|
|
||||||
|
|
||||||
### Building & Installing to the System
|
|
||||||
This is the preferred method for installation, and is suitable for packages.
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone --recursive https://github.com/PolyMC/PolyMC.git && cd PolyMC
|
|
||||||
|
|
||||||
# configure everything
|
|
||||||
cmake -S . -B build \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DCMAKE_INSTALL_PREFIX="/usr" \ # Use "/usr" for packages, otherwise, leave it at the default "/usr/local".
|
|
||||||
-DLauncher_LAYOUT=lin-system
|
|
||||||
|
|
||||||
make -j$(nproc) install # Optionally specify DESTDIR for packages (i.e. DESTDIR=${pkgdir})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installing Qt using the installer (optional)
|
|
||||||
1. Run the Qt installer.
|
|
||||||
2. Choose a place to install Qt.
|
|
||||||
3. Choose the components you want to install.
|
|
||||||
- You need Qt 5.6.x 64-bit ticked.
|
|
||||||
- You need Tools/Qt Creator ticked.
|
|
||||||
- Other components are selected by default, you can untick them if you don't need them.
|
|
||||||
4. Accept the license agreements.
|
|
||||||
5. Double check the install details and then click "Install".
|
|
||||||
- Installation can take a very long time, go grab a cup of tea or something and let it work.
|
|
||||||
|
|
||||||
### Loading the project in Qt Creator (optional)
|
|
||||||
1. Open Qt Creator.
|
|
||||||
2. Choose `File->Open File or Project`.
|
|
||||||
3. Navigate to the Launcher source folder you cloned and choose CMakeLists.txt.
|
|
||||||
4. Read the instructions that just popped up about a build location and choose one.
|
|
||||||
5. You should see "Run CMake" in the window.
|
|
||||||
- Make sure that Generator is set to "Unix Generator (Desktop Qt 5.6.x GCC 64bit)".
|
|
||||||
- Hit the "Run CMake" button.
|
|
||||||
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
|
||||||
- Hit "Finish" if CMake ran successfully.
|
|
||||||
6. Cross your fingers and press the Run button (bottom left of Qt Creator).
|
|
||||||
- If the project builds successfully it will run and the Launcher window will pop up.
|
|
||||||
|
|
||||||
**If this doesn't work for you, let us know on our Discord.**
|
|
||||||
|
|
||||||
# Windows
|
|
||||||
|
|
||||||
Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt Creator. The project will simply not compile using Microsoft build tools, because that's not something we do. If it does compile, it is by chance only.
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
* [Qt 5.6+ Development tools](http://qt-project.org/downloads) -- Qt Online Installer for Windows
|
|
||||||
- http://download.qt.io/new_archive/qt/5.6/5.6.0/qt-opensource-windows-x86-mingw492-5.6.0.exe
|
|
||||||
- Download the MinGW version (MSVC version does not work).
|
|
||||||
* [OpenSSL](https://github.com/IndySockets/OpenSSL-Binaries/tree/master/Archive/) -- Win32 OpenSSL, version 1.0.2g (from 2016)
|
|
||||||
- https://github.com/IndySockets/OpenSSL-Binaries/raw/master/Archive/openssl-1.0.2g-i386-win32.zip
|
|
||||||
- the usual OpenSSL for Windows (http://slproweb.com/products/Win32OpenSSL.html) only provides the newest version of OpenSSL, and we need the 1.0.2g version
|
|
||||||
- **Download the 32-bit version, not 64-bit.**
|
|
||||||
- Microsoft Visual C++ 2008 Redist is required for this, there's a link on the OpenSSL download page above next to the main download.
|
|
||||||
- We use a custom build of OpenSSL that doesn't have this dependency. For normal development, the custom build is not necessary though.
|
|
||||||
* [zlib 1.2+](http://gnuwin32.sourceforge.net/packages/zlib.htm) - the Setup is fine
|
|
||||||
* [Java JDK 8](https://adoptium.net/releases.html?variant=openjdk8) - Use the MSI installer.
|
|
||||||
* [CMake](http://www.cmake.org/cmake/resources/software.html) -- Windows (Win32 Installer)
|
|
||||||
|
|
||||||
Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
|
|
||||||
|
|
||||||
## Getting set up
|
|
||||||
|
|
||||||
### Installing Qt
|
|
||||||
1. Run the Qt installer
|
|
||||||
2. Choose a place to install Qt (C:\Qt is the default),
|
|
||||||
3. Choose the components you want to install
|
|
||||||
- You need Qt 5.6 (32 bit) ticked,
|
|
||||||
- You need Tools/Qt Creator ticked,
|
|
||||||
- Other components are selected by default, you can untick them if you don't need them.
|
|
||||||
4. Accept the license agreements,
|
|
||||||
5. Double check the install details and then click "Install"
|
|
||||||
- Installation can take a very long time, go grab a cup of tea or something and let it work.
|
|
||||||
|
|
||||||
### Installing OpenSSL
|
|
||||||
1. Download .zip file from the link above.
|
|
||||||
2. Unzip and add the directory to PATH, so CMake can find it.
|
|
||||||
|
|
||||||
### Installing CMake
|
|
||||||
1. Run the CMake installer,
|
|
||||||
2. It's easiest if you choose to add CMake to the PATH for all users,
|
|
||||||
- If you don't choose to do this, remember where you installed CMake.
|
|
||||||
|
|
||||||
### Loading the project
|
|
||||||
1. Open Qt Creator,
|
|
||||||
2. Choose File->Open File or Project,
|
|
||||||
3. Navigate to the Launcher source folder you cloned and choose CMakeLists.txt,
|
|
||||||
4. Read the instructions that just popped up about a build location and choose one,
|
|
||||||
5. If you chose not to add CMake to the system PATH, tell Qt Creator where you installed it,
|
|
||||||
- Otherwise you can skip this step.
|
|
||||||
6. You should see "Run CMake" in the window,
|
|
||||||
- Make sure that Generator is set to "MinGW Generator (Desktop Qt 5.6.x MinGW 32bit)",
|
|
||||||
- Hit the "Run CMake" button,
|
|
||||||
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
|
||||||
- Hit "Finish" if CMake ran successfully.
|
|
||||||
7. Cross your fingers and press the Run button (bottom left of Qt Creator)!
|
|
||||||
- If the project builds successfully it will run and the Launcher window will pop up,
|
|
||||||
- Test OpenSSL by making an instance and trying to log in. If Qt Creator couldn't find OpenSSL during the CMake stage, login will fail and you'll get an error.
|
|
||||||
|
|
||||||
The following .dlls are needed for the app to run (copy them to build directory if you want to be able to move the build to another pc):
|
|
||||||
```
|
|
||||||
platforms/qwindows.dll
|
|
||||||
libeay32.dll
|
|
||||||
libgcc_s_dw2-1.dll
|
|
||||||
libssp-0.dll
|
|
||||||
libstdc++-6.dll
|
|
||||||
libwinpthread-1.dll
|
|
||||||
Qt5Core.dll
|
|
||||||
Qt5Gui.dll
|
|
||||||
Qt5Network.dll
|
|
||||||
Qt5Svg.dll
|
|
||||||
Qt5Widgets.dll
|
|
||||||
Qt5Xml.dll
|
|
||||||
ssleay32.dll
|
|
||||||
zlib1.dll
|
|
||||||
```
|
|
||||||
|
|
||||||
**These build instructions worked for me (Drayshak) on a fresh Windows 8 x64 Professional install. If they don't work for you, let us know on our Discord.**
|
|
||||||
### Compile from command line on Windows
|
|
||||||
1. If you installed Qt with the web installer, there should be a shortcut called `Qt 5.4 for Desktop (MinGW 4.9 32-bit)` in the Start menu on Windows 7 and 10. Best way to find it is to search for it. Do note you cannot just use cmd.exe, you have to use the shortcut, otherwise the proper MinGW software will not be on the PATH.
|
|
||||||
2. Once that is open, change into your user directory, and clone PolyMC by doing `git clone --recursive https://github.com/PolyMC/PolyMC.git`, and change directory to the folder you cloned to.
|
|
||||||
3. Make a build directory, and change directory to the directory and do `cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=C:\Path\that\makes\sense\for\you`. By default, it will install to C:\Program Files (x86), which you might not want, if you want a local installation. If you want to install it to that directory, make sure to run the command window as administrator.
|
|
||||||
3. Do `mingw32-make -jX`, where X is the number of cores your CPU has plus one.
|
|
||||||
4. Now to wait for it to compile. This could take some time. Hopefully it compiles properly.
|
|
||||||
5. Run the command `mingw32-make install`, and it should install PolyMC, to whatever the `-DCMAKE_INSTALL_PREFIX` was.
|
|
||||||
6. In most cases, whenever compiling, the OpenSSL dll's aren't put into the directory to where PolyMC installs, meaning you cannot log in. The best way to fix this is just to do `copy C:\OpenSSL-Win32\*.dll C:\Where\you\installed\PolyMC\to`. This should copy the required OpenSSL dll's to log in.
|
|
||||||
|
|
||||||
# macOS
|
|
||||||
|
|
||||||
### Install prerequisites:
|
|
||||||
- Install XCode Command Line tools
|
|
||||||
- Install the official build of CMake (https://cmake.org/download/)
|
|
||||||
- Install JDK 8 (https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html)
|
|
||||||
- Get Qt 5.6 and install it (https://download.qt.io/new_archive/qt/5.6/5.6.3/)
|
|
||||||
|
|
||||||
### XCode Command Line tools
|
|
||||||
|
|
||||||
If you don't have XCode CommandLine tools installed, you can install them by using this command in the Terminal App
|
|
||||||
|
|
||||||
```bash
|
|
||||||
xcode-select --install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
Pick an installation path - this is where the final `.app` will be constructed when you run `make install`. Supply it as the `CMAKE_INSTALL_PREFIX` argument during CMake configuration.
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone --recursive https://github.com/PolyMC/PolyMC.git
|
|
||||||
cd Launcher
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake \
|
|
||||||
-DCMAKE_C_COMPILER=/usr/bin/clang \
|
|
||||||
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH="$(dirname $PWD)/dist/" \
|
|
||||||
-DCMAKE_PREFIX_PATH="/path/to/Qt5.6/" \
|
|
||||||
-DQt5_DIR="/path/to/Qt5.6/" \
|
|
||||||
-DLauncher_LAYOUT=mac-bundle \
|
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \
|
|
||||||
..
|
|
||||||
make install
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** The final app bundle may not run due to code signing issues, which
|
|
||||||
need to be fixed with `codesign -fs -`.
|
|
||||||
|
514
CMakeLists.txt
514
CMakeLists.txt
@ -1,19 +1,12 @@
|
|||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
|
||||||
cmake_policy(SET CMP0020 OLD)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
project(Launcher)
|
project(Launcher)
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
||||||
if(IS_IN_SOURCE_BUILD)
|
if(IS_IN_SOURCE_BUILD)
|
||||||
message(FATAL_ERROR "You are building the Launcher in-source. Please separate the build tree from the source tree.")
|
message(FATAL_ERROR "You are building the Launcher in-source. Please separate the build tree from the source tree.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
##################################### Set CMake options #####################################
|
##################################### Set CMake options #####################################
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
@ -31,198 +24,412 @@ set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars)
|
|||||||
######## Set compiler flags ########
|
######## Set compiler flags ########
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED true)
|
set(CMAKE_C_STANDARD_REQUIRED true)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
set(CMAKE_CXX_FLAGS " -Wall -pedantic -Werror -Wno-deprecated-declarations -D_GLIBCXX_USE_CXX11_ABI=0 -fstack-protector-strong --param=ssp-buffer-size=4 -O3 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS}")
|
if(MSVC)
|
||||||
if(UNIX AND APPLE)
|
# /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag
|
||||||
set(CMAKE_CXX_FLAGS " -stdlib=libc++ ${CMAKE_CXX_FLAGS}")
|
# /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20
|
||||||
|
# Use /W4 as /Wall includes unnesserey warnings such as added padding to structs
|
||||||
|
set(CMAKE_CXX_FLAGS "/GS /permissive- /W4 ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
|
# /EHs Enables stack unwind semantics for standard C++ exceptions to ensure stackframes are unwound
|
||||||
|
# and object deconstructors are called when an exception is caught.
|
||||||
|
# without it memory leaks and a warning is printed
|
||||||
|
# /EHc tells the compiler to assume that functions declared as extern "C" never throw a C++ exception
|
||||||
|
# This appears to not always be a defualt compiler option in CMAKE
|
||||||
|
set(CMAKE_CXX_FLAGS "/EHsc ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
|
# LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs
|
||||||
|
# This implicitly selects an entrypoint specific to the subsystem selected
|
||||||
|
# qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs
|
||||||
|
# Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM
|
||||||
|
# This allows tests to still use have console without using seperate linker flags
|
||||||
|
# /LTCG allows for linking wholy optimizated programs
|
||||||
|
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
|
||||||
|
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "/LTCG /MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}")
|
||||||
|
|
||||||
|
# /GL enables whole program optimizations
|
||||||
|
# /Gw helps reduce binary size
|
||||||
|
# /Gy allows the compiler to package individual functions
|
||||||
|
# /guard:cf enables control flow guard
|
||||||
|
foreach(lang C CXX)
|
||||||
|
set("CMAKE_${lang}_FLAGS_RELEASE" "/GL /Gw /Gy /guard:cf")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# See https://github.com/ccache/ccache/issues/1040
|
||||||
|
# Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
||||||
|
# See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html
|
||||||
|
foreach(config DEBUG RELWITHDEBINFO)
|
||||||
|
foreach(lang C CXX)
|
||||||
|
set(flags_var "CMAKE_${lang}_FLAGS_${config}")
|
||||||
|
string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}")
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL")
|
||||||
|
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "")
|
||||||
|
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
|
# ATL's pack list needs more than the default 1 Mib stack on windows
|
||||||
|
if(WIN32)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror=return-type")
|
|
||||||
|
|
||||||
# Fix build with Qt 5.13
|
# Fix build with Qt 5.13
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_DISABLE_DEPRECATED_BEFORE=0x050C00")
|
||||||
|
|
||||||
|
# Fix aarch64 build for toml++
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0")
|
||||||
|
|
||||||
|
# set CXXFLAGS for build targets
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||||
|
|
||||||
|
option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF)
|
||||||
|
|
||||||
|
# If this is a Debug build turn on address sanitiser
|
||||||
|
if ((CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") AND DEBUG_ADDRESS_SANITIZER)
|
||||||
|
message(STATUS "Address Sanitizer enabled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off")
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
|
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
||||||
|
# using clang with clang-cl front end
|
||||||
|
message(STATUS "Address Sanitizer available on Clang MSVC frontend")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-")
|
||||||
|
else()
|
||||||
|
# AppleClang and Clang
|
||||||
|
message(STATUS "Address Sanitizer available on Clang")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
endif()
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
# GCC
|
||||||
|
message(STATUS "Address Sanitizer available on GCC")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
link_libraries("asan")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
message(STATUS "Address Sanitizer available on MSVC")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-")
|
||||||
|
else()
|
||||||
|
message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
option(ENABLE_LTO "Enable Link Time Optimization" off)
|
||||||
|
|
||||||
|
if(ENABLE_LTO)
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
|
||||||
|
|
||||||
|
if(ipo_supported)
|
||||||
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
||||||
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
|
||||||
|
if(CMAKE_BUILD_TYPE)
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
||||||
|
message(STATUS "IPO / LTO enabled")
|
||||||
|
else()
|
||||||
|
message(STATUS "Not enabling IPO / LTO on debug builds")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "IPO / LTO will only be enabled for release builds")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "IPO / LTO not supported: <${ipo_error}>")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(BUILD_TESTING "Build the testing tree." ON)
|
||||||
|
|
||||||
|
find_package(ECM QUIET NO_MODULE)
|
||||||
|
if(NOT ECM_FOUND)
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/CMakeLists.txt")
|
||||||
|
message(STATUS "Using bundled ECM")
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/modules;${CMAKE_MODULE_PATH}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
" Could not find ECM\n \n"
|
||||||
|
" Either install ECM using the system package manager or clone submodules\n"
|
||||||
|
" Submodules can be cloned with 'git submodule update --init --recursive'")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
|
||||||
|
endif()
|
||||||
|
include(CTest)
|
||||||
|
include(ECMAddTests)
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
enable_testing()
|
||||||
|
endif()
|
||||||
|
|
||||||
##################################### Set Application options #####################################
|
##################################### Set Application options #####################################
|
||||||
|
|
||||||
######## Set URLs ########
|
######## Set URLs ########
|
||||||
set(Launcher_NEWS_RSS_URL "https://multimc.org/rss.xml" CACHE STRING "URL to fetch Launcher's news RSS feed from.")
|
set(Launcher_NEWS_RSS_URL "https://prismlauncher.org/feed/feed.xml" CACHE STRING "URL to fetch Prism Launcher's news RSS feed from.")
|
||||||
|
set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
|
||||||
|
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
|
||||||
|
|
||||||
######## Set version numbers ########
|
######## Set version numbers ########
|
||||||
set(Launcher_VERSION_MAJOR 1)
|
set(Launcher_VERSION_MAJOR 8)
|
||||||
set(Launcher_VERSION_MINOR 0)
|
set(Launcher_VERSION_MINOR 0)
|
||||||
set(Launcher_VERSION_HOTFIX 5)
|
|
||||||
|
|
||||||
# Build number
|
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
|
||||||
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0")
|
||||||
|
set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},0,0")
|
||||||
|
|
||||||
# Build platform.
|
# Build platform.
|
||||||
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
set(Launcher_BUILD_PLATFORM "unknown" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.")
|
||||||
|
|
||||||
# Channel list URL
|
# Github repo URL with releases for updater
|
||||||
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
|
set(Launcher_UPDATER_GITHUB_REPO "https://github.com/PrismLauncher/PrismLauncher" CACHE STRING "Base github URL for the updater.")
|
||||||
|
|
||||||
# Notification URL
|
# Name to help updater identify valid artifacts
|
||||||
set(Launcher_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
set(Launcher_BUILD_ARTIFACT "" CACHE STRING "Artifact name to help the updater identify valid artifacts.")
|
||||||
|
|
||||||
# The metadata server
|
# The metadata server
|
||||||
set(Launcher_META_URL "https://meta.multimc.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
||||||
|
|
||||||
# paste.ee API key
|
|
||||||
set(Launcher_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE STRING "API key you can get from paste.ee when you register an account")
|
|
||||||
|
|
||||||
# Imgur API Client ID
|
# Imgur API Client ID
|
||||||
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
||||||
|
|
||||||
# MSA Client ID
|
|
||||||
set(Launcher_MSA_CLIENT_ID "17b47edd-c884-4997-926d-9e7f9a6b4647" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
|
|
||||||
|
|
||||||
# Bug tracker URL
|
# Bug tracker URL
|
||||||
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.")
|
set(Launcher_BUG_TRACKER_URL "https://github.com/PrismLauncher/PrismLauncher/issues" CACHE STRING "URL for the bug tracker.")
|
||||||
|
|
||||||
|
# Translations Platform URL
|
||||||
|
set(Launcher_TRANSLATIONS_URL "https://hosted.weblate.org/projects/prismlauncher/launcher/" CACHE STRING "URL for the translations platform.")
|
||||||
|
|
||||||
|
# Matrix Space
|
||||||
|
set(Launcher_MATRIX_URL "https://prismlauncher.org/matrix" CACHE STRING "URL to the Matrix Space")
|
||||||
|
|
||||||
# Discord URL
|
# Discord URL
|
||||||
set(Launcher_DISCORD_URL "https://discord.gg/Z52pwxWCHP" CACHE STRING "URL for the Discord guild.")
|
set(Launcher_DISCORD_URL "https://prismlauncher.org/discord" CACHE STRING "URL for the Discord guild.")
|
||||||
|
|
||||||
# Subreddit URL
|
# Subreddit URL
|
||||||
set(Launcher_SUBREDDIT_URL "" CACHE STRING "URL for the subreddit.")
|
set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL for the subreddit.")
|
||||||
|
|
||||||
|
# Builds
|
||||||
|
set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules")
|
||||||
|
set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against")
|
||||||
|
|
||||||
|
# Native libraries
|
||||||
|
if(UNIX AND APPLE)
|
||||||
|
set(Launcher_GLFW_LIBRARY_NAME "libglfw.dylib" CACHE STRING "Name of native glfw library")
|
||||||
|
set(Launcher_OPENAL_LIBRARY_NAME "libopenal.dylib" CACHE STRING "Name of native openal library")
|
||||||
|
elseif(UNIX)
|
||||||
|
set(Launcher_GLFW_LIBRARY_NAME "libglfw.so" CACHE STRING "Name of native glfw library")
|
||||||
|
set(Launcher_OPENAL_LIBRARY_NAME "libopenal.so" CACHE STRING "Name of native openal library")
|
||||||
|
elseif(WIN32)
|
||||||
|
set(Launcher_GLFW_LIBRARY_NAME "glfw.dll" CACHE STRING "Name of native glfw library")
|
||||||
|
set(Launcher_OPENAL_LIBRARY_NAME "OpenAL.dll" CACHE STRING "Name of native openal library")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# API Keys
|
||||||
|
# NOTE: These API keys are here for convenience. If you rebrand this software or intend to break the terms of service
|
||||||
|
# of these platforms, please change these API keys beforehand.
|
||||||
|
# Be aware that if you were to use these API keys for malicious purposes they might get revoked, which might cause
|
||||||
|
# breakage to thousands of users.
|
||||||
|
# If you don't plan to use these features of this software, you can just remove these values.
|
||||||
|
|
||||||
|
# By using this key in your builds you accept the terms of use laid down in
|
||||||
|
# https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use
|
||||||
|
set(Launcher_MSA_CLIENT_ID "c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
|
||||||
|
|
||||||
|
# By using this key in your builds you accept the terms and conditions laid down in
|
||||||
|
# https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions
|
||||||
|
# NOTE: CurseForge requires you to change this if you make any kind of derivative work.
|
||||||
|
# This key was issued specifically for Prism Launcher
|
||||||
|
set(Launcher_CURSEFORGE_API_KEY "$2a$10$wuAJuNZuted3NORVmpgUC.m8sI.pv1tOPKZyBgLFGjxFp/br0lZCC" CACHE STRING "API key for the CurseForge platform")
|
||||||
|
|
||||||
|
set(Launcher_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID})
|
||||||
|
set(Launcher_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
|
||||||
|
set(Launcher_COMPILER_TARGET_SYSTEM ${CMAKE_SYSTEM_NAME})
|
||||||
|
set(Launcher_COMPILER_TARGET_SYSTEM_VERSION ${CMAKE_SYSTEM_VERSION})
|
||||||
|
set(Launcher_COMPILER_TARGET_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR})
|
||||||
|
|
||||||
#### Check the current Git commit and branch
|
#### Check the current Git commit and branch
|
||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
|
git_get_exact_tag(Launcher_GIT_TAG)
|
||||||
get_git_head_revision(Launcher_GIT_REFSPEC Launcher_GIT_COMMIT)
|
get_git_head_revision(Launcher_GIT_REFSPEC Launcher_GIT_COMMIT)
|
||||||
|
|
||||||
message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
|
message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
|
||||||
|
message(STATUS "Git tag: ${Launcher_GIT_TAG}")
|
||||||
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
|
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
|
||||||
|
|
||||||
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
|
string(TIMESTAMP TODAY "%Y-%m-%d")
|
||||||
|
set(Launcher_BUILD_TIMESTAMP "${TODAY}")
|
||||||
#### Custom target to just print the version.
|
|
||||||
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
|
|
||||||
add_custom_target(tcversion echo "\\#\\#teamcity[setParameter name=\\'env.LAUNCHER_VERSION\\' value=\\'${Launcher_RELEASE_VERSION_NAME}\\']")
|
|
||||||
|
|
||||||
################################ 3rd Party Libs ################################
|
################################ 3rd Party Libs ################################
|
||||||
|
|
||||||
|
# Successive configurations of cmake without cleaning the build dir will cause zlib fallback to fail due to cached values
|
||||||
|
# Record when fallback triggered and skip this find_package
|
||||||
|
if(NOT Launcher_FORCE_BUNDLED_LIBS AND NOT FORCE_BUNDLED_ZLIB)
|
||||||
|
find_package(ZLIB QUIET)
|
||||||
|
endif()
|
||||||
|
if(NOT ZLIB_FOUND)
|
||||||
|
set(FORCE_BUNDLED_ZLIB TRUE CACHE BOOL "")
|
||||||
|
mark_as_advanced(FORCE_BUNDLED_ZLIB)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Find the required Qt parts
|
# Find the required Qt parts
|
||||||
find_package(Qt5Core REQUIRED)
|
include(QtVersionlessBackport)
|
||||||
find_package(Qt5Widgets REQUIRED)
|
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||||
find_package(Qt5Concurrent REQUIRED)
|
set(QT_VERSION_MAJOR 5)
|
||||||
find_package(Qt5Network REQUIRED)
|
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml)
|
||||||
find_package(Qt5Test REQUIRED)
|
|
||||||
find_package(Qt5Xml REQUIRED)
|
|
||||||
|
|
||||||
# The Qt5 cmake files don't provide its install paths, so ask qmake.
|
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||||
include(QMakeQuery)
|
find_package(QuaZip-Qt5 1.3 QUIET)
|
||||||
query_qmake(QT_INSTALL_PLUGINS QT_PLUGINS_DIR)
|
endif()
|
||||||
query_qmake(QT_INSTALL_IMPORTS QT_IMPORTS_DIR)
|
if (NOT QuaZip-Qt5_FOUND)
|
||||||
query_qmake(QT_INSTALL_LIBS QT_LIBS_DIR)
|
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
|
||||||
query_qmake(QT_INSTALL_LIBEXECS QT_LIBEXECS_DIR)
|
set(FORCE_BUNDLED_QUAZIP 1)
|
||||||
query_qmake(QT_HOST_DATA QT_DATA_DIR)
|
endif()
|
||||||
set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs)
|
|
||||||
|
|
||||||
|
# Qt 6 sets these by default. Notably causes Windows APIs to use UNICODE strings.
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
|
||||||
|
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
set(QT_VERSION_MAJOR 6)
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat)
|
||||||
|
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
|
||||||
|
|
||||||
|
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||||
|
find_package(QuaZip-Qt6 1.3 QUIET)
|
||||||
|
endif()
|
||||||
|
if (NOT QuaZip-Qt6_FOUND)
|
||||||
|
set(QUAZIP_QT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (4, 5 or 6), defaults to ${QT_VERSION_MAJOR}" FORCE)
|
||||||
|
set(FORCE_BUNDLED_QUAZIP 1)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
include(ECMQueryQt)
|
||||||
|
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
|
||||||
|
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
|
||||||
|
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
|
||||||
|
else()
|
||||||
|
set(QT_PLUGINS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_PLUGINS})
|
||||||
|
set(QT_LIBS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBS})
|
||||||
|
set(QT_LIBEXECS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBEXECS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# NOTE: Qt 6 already sets this by default
|
||||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
||||||
|
# Find toml++
|
||||||
|
find_package(tomlplusplus 3.2.0 QUIET)
|
||||||
|
|
||||||
|
# Find ghc_filesystem
|
||||||
|
find_package(ghc_filesystem QUIET)
|
||||||
|
|
||||||
|
# Find cmark
|
||||||
|
find_package(cmark QUIET)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(ECMQtDeclareLoggingCategory)
|
||||||
|
|
||||||
####################################### Program Info #######################################
|
####################################### Program Info #######################################
|
||||||
|
|
||||||
set(Launcher_APP_BINARY_NAME "polymc" CACHE STRING "Name of the Launcher binary")
|
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
|
||||||
add_subdirectory(program_info)
|
add_subdirectory(program_info)
|
||||||
|
|
||||||
####################################### Install layout #######################################
|
####################################### Install layout #######################################
|
||||||
|
|
||||||
# How to install the build results
|
set(Launcher_ENABLE_UPDATER NO)
|
||||||
set(Launcher_LAYOUT "auto" CACHE STRING "The layout for the launcher installation (auto, win-bundle, lin-nodeps, lin-system, mac-bundle)")
|
set(Launcher_BUILD_UPDATER NO)
|
||||||
set_property(CACHE Launcher_LAYOUT PROPERTY STRINGS auto win-bundle lin-nodeps lin-system mac-bundle)
|
|
||||||
|
|
||||||
if(Launcher_LAYOUT STREQUAL "auto")
|
if (NOT APPLE AND (NOT Launcher_UPDATER_GITHUB_REPO STREQUAL "" AND NOT Launcher_BUILD_ARTIFACT STREQUAL ""))
|
||||||
if(UNIX AND APPLE)
|
set(Launcher_BUILD_UPDATER YES)
|
||||||
set(Launcher_LAYOUT_REAL "mac-bundle")
|
|
||||||
elseif(UNIX)
|
|
||||||
set(Launcher_LAYOUT_REAL "lin-nodeps")
|
|
||||||
elseif(WIN32)
|
|
||||||
set(Launcher_LAYOUT_REAL "win-bundle")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Cannot choose a sensible install layout for your platform.")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(Launcher_LAYOUT_REAL ${Launcher_LAYOUT})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
|
if(NOT (UNIX AND APPLE))
|
||||||
|
# Install "portable.txt" if selected component is "portable"
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_Portable_File}" DESTINATION "." COMPONENT portable EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX AND APPLE)
|
||||||
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
||||||
set(LIBRARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(LIBRARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
||||||
set(PLUGIN_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(PLUGIN_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
||||||
|
set(FRAMEWORK_DEST_DIR "${Launcher_Name}.app/Contents/Frameworks")
|
||||||
set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources")
|
set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources")
|
||||||
set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
||||||
|
|
||||||
set(BUNDLE_DEST_DIR ".")
|
|
||||||
|
|
||||||
# Apps to bundle
|
# Apps to bundle
|
||||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
||||||
|
|
||||||
# Mac bundle settings
|
# Mac bundle settings
|
||||||
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}")
|
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_DisplayName}")
|
||||||
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: Minecraft launcher and management utility.")
|
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_DisplayName}: A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.")
|
||||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.${Launcher_Name}")
|
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.prismlauncher.${Launcher_Name}")
|
||||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_NAME}")
|
||||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_NAME}")
|
||||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_NAME}")
|
||||||
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
|
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
|
||||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2021 ${Launcher_Copyright}")
|
set(MACOSX_BUNDLE_COPYRIGHT "© 2022-2023 ${Launcher_Copyright_Mac}")
|
||||||
|
set(MACOSX_SPARKLE_UPDATE_PUBLIC_KEY "v55ZWWD6QlPoXGV6VLzOTZxZUggWeE51X8cRQyQh6vA=" CACHE STRING "Public key for Sparkle update feed")
|
||||||
|
set(MACOSX_SPARKLE_UPDATE_FEED_URL "https://prismlauncher.org/feed/appcast.xml" CACHE STRING "URL for Sparkle update feed")
|
||||||
|
|
||||||
|
set(MACOSX_SPARKLE_DOWNLOAD_URL "https://github.com/sparkle-project/Sparkle/releases/download/2.1.0/Sparkle-2.1.0.tar.xz" CACHE STRING "URL to Sparkle release archive")
|
||||||
|
set(MACOSX_SPARKLE_SHA256 "bf6ac1caa9f8d321d5784859c88da874f28412f37fb327bc21b7b14c5d61ef94" CACHE STRING "SHA256 checksum for Sparkle release archive")
|
||||||
|
set(MACOSX_SPARKLE_DIR "${CMAKE_BINARY_DIR}/frameworks/Sparkle")
|
||||||
|
|
||||||
# directories to look for dependencies
|
# directories to look for dependencies
|
||||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${MACOSX_SPARKLE_DIR})
|
||||||
|
|
||||||
|
if(NOT MACOSX_SPARKLE_UPDATE_PUBLIC_KEY STREQUAL "" AND NOT MACOSX_SPARKLE_UPDATE_FEED_URL STREQUAL "")
|
||||||
|
set(Launcher_ENABLE_UPDATER YES)
|
||||||
|
endif()
|
||||||
|
|
||||||
# install as bundle
|
# install as bundle
|
||||||
set(INSTALL_BUNDLE "full")
|
set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies")
|
||||||
|
|
||||||
# Add the icon
|
# Add the icon
|
||||||
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-nodeps")
|
elseif(UNIX)
|
||||||
|
include(KDEInstallDirs)
|
||||||
|
|
||||||
set(BINARY_DEST_DIR "bin")
|
set(BINARY_DEST_DIR "bin")
|
||||||
set(LIBRARY_DEST_DIR "bin")
|
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
|
||||||
set(PLUGIN_DEST_DIR "plugins")
|
set(JARS_DEST_DIR "share/${Launcher_Name}")
|
||||||
set(BUNDLE_DEST_DIR ".")
|
|
||||||
set(RESOURCES_DEST_DIR ".")
|
|
||||||
set(JARS_DEST_DIR "bin/jars")
|
|
||||||
|
|
||||||
# install as bundle with no dependencies included
|
# install as bundle with no dependencies included
|
||||||
set(INSTALL_BUNDLE "nodeps")
|
set(INSTALL_BUNDLE "nodeps" CACHE STRING "Use fixup_bundle to bundle dependencies")
|
||||||
|
|
||||||
# Set RPATH
|
# Set RPATH
|
||||||
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
||||||
|
|
||||||
# Install basic runner script
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${KDE_INSTALL_APPDIR})
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR})
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps")
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
|
||||||
|
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/launcher/qtlogging.ini" DESTINATION "share/${Launcher_Name}")
|
||||||
|
|
||||||
|
if(Launcher_ManPage)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Install basic runner script if component "portable" is selected
|
||||||
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
|
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
|
||||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION ${BUNDLE_DEST_DIR} RENAME ${Launcher_Name})
|
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION "." RENAME ${Launcher_Name} COMPONENT portable EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-system")
|
elseif(WIN32)
|
||||||
set(Launcher_BINARY_DEST_DIR "bin" CACHE STRING "Path to the binary directory")
|
|
||||||
set(Launcher_LIBRARY_DEST_DIR "lib${LIB_SUFFIX}" CACHE STRING "Path to the library directory")
|
|
||||||
set(Launcher_SHARE_DEST_DIR "share/polymc" CACHE STRING "Path to the shared data directory")
|
|
||||||
set(JARS_DEST_DIR "${Launcher_SHARE_DEST_DIR}/jars")
|
|
||||||
set(Launcher_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory")
|
|
||||||
set(Launcher_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory")
|
|
||||||
set(Launcher_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory")
|
|
||||||
|
|
||||||
set(BINARY_DEST_DIR ${Launcher_BINARY_DEST_DIR})
|
|
||||||
set(LIBRARY_DEST_DIR ${Launcher_LIBRARY_DEST_DIR})
|
|
||||||
|
|
||||||
MESSAGE(STATUS "Compiling for linux system with ${Launcher_SHARE_DEST_DIR} and LAUNCHER_LINUX_DATADIR")
|
|
||||||
SET(Launcher_APP_BINARY_DEFS "-DMULTIMC_JARS_LOCATION=${CMAKE_INSTALL_PREFIX}/${JARS_DEST_DIR}" "-DLAUNCHER_LINUX_DATADIR")
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${Launcher_DESKTOP_DEST_DIR})
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${Launcher_METAINFO_DEST_DIR})
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${Launcher_ICON_DEST_DIR})
|
|
||||||
|
|
||||||
# install as bundle with no dependencies included
|
|
||||||
set(INSTALL_BUNDLE "nodeps")
|
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
|
|
||||||
set(BINARY_DEST_DIR ".")
|
set(BINARY_DEST_DIR ".")
|
||||||
set(LIBRARY_DEST_DIR ".")
|
set(LIBRARY_DEST_DIR ".")
|
||||||
set(PLUGIN_DEST_DIR ".")
|
set(PLUGIN_DEST_DIR ".")
|
||||||
set(BUNDLE_DEST_DIR ".")
|
|
||||||
set(RESOURCES_DEST_DIR ".")
|
set(RESOURCES_DEST_DIR ".")
|
||||||
set(JARS_DEST_DIR "jars")
|
set(JARS_DEST_DIR "jars")
|
||||||
|
|
||||||
@ -233,40 +440,95 @@ elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
|
|||||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
|
|
||||||
# install as bundle
|
# install as bundle
|
||||||
set(INSTALL_BUNDLE "full")
|
set(INSTALL_BUNDLE "full" CACHE STRING "Use fixup_bundle to bundle dependencies")
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "No sensible install layout set.")
|
message(FATAL_ERROR "Platform not supported")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
################################ Included Libs ################################
|
################################ Included Libs ################################
|
||||||
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
set_directory_properties(PROPERTIES EP_BASE External)
|
set_directory_properties(PROPERTIES EP_BASE External)
|
||||||
|
|
||||||
option(NBT_BUILD_SHARED "Build NBT shared library" ON)
|
option(NBT_BUILD_SHARED "Build NBT shared library" OFF)
|
||||||
option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
|
option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
|
||||||
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
|
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
|
||||||
set(NBT_NAME Launcher_nbt++)
|
|
||||||
set(NBT_DEST_DIR ${LIBRARY_DEST_DIR})
|
|
||||||
add_subdirectory(libraries/libnbtplusplus)
|
add_subdirectory(libraries/libnbtplusplus)
|
||||||
|
|
||||||
add_subdirectory(libraries/systeminfo) # system information library
|
add_subdirectory(libraries/systeminfo) # system information library
|
||||||
add_subdirectory(libraries/hoedown) # markdown parser
|
|
||||||
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
||||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||||
add_subdirectory(libraries/xz-embedded) # xz compression
|
if(FORCE_BUNDLED_ZLIB)
|
||||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
message(STATUS "Using bundled zlib")
|
||||||
|
|
||||||
|
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # Suppress cmake warnings and allow INTERPROCEDURAL_OPTIMIZATION for zlib
|
||||||
|
set(SKIP_INSTALL_ALL ON)
|
||||||
|
add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
# On OS where unistd.h exists, zlib's generated header defines `Z_HAVE_UNISTD_H`, while the included header does not.
|
||||||
|
# We cannot safely undo the rename on those systems, and they generally have packages for zlib anyway.
|
||||||
|
check_include_file(unistd.h NEED_GENERATED_ZCONF)
|
||||||
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" AND NOT NEED_GENERATED_ZCONF)
|
||||||
|
# zlib's cmake script renames a file, dirtying the submodule, see https://github.com/madler/zlib/issues/162
|
||||||
|
message(STATUS "Undoing Rename")
|
||||||
|
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
|
||||||
|
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h.included" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib/zconf.h")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib" "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" CACHE STRING "" FORCE)
|
||||||
|
set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
|
||||||
|
add_library(ZLIB::ZLIB ALIAS zlibstatic)
|
||||||
|
set(ZLIB_LIBRARY ZLIB::ZLIB CACHE STRING "zlib library name")
|
||||||
|
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system zlib")
|
||||||
|
endif()
|
||||||
|
if (FORCE_BUNDLED_QUAZIP)
|
||||||
|
message(STATUS "Using bundled QuaZip")
|
||||||
|
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.
|
||||||
|
set(QUAZIP_INSTALL 0)
|
||||||
|
add_subdirectory(libraries/quazip) # zip manipulation library
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system QuaZip")
|
||||||
|
endif()
|
||||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||||
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
|
||||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||||
add_subdirectory(libraries/classparser) # class parser library
|
if(NOT tomlplusplus_FOUND)
|
||||||
add_subdirectory(libraries/optional-bare)
|
message(STATUS "Using bundled tomlplusplus")
|
||||||
add_subdirectory(libraries/tomlc99) # toml parser
|
add_subdirectory(libraries/tomlplusplus) # toml parser
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system tomlplusplus")
|
||||||
|
endif()
|
||||||
|
if(NOT cmark_FOUND)
|
||||||
|
message(STATUS "Using bundled cmark")
|
||||||
|
set(CMARK_STATIC ON CACHE BOOL "Build static libcmark library" FORCE)
|
||||||
|
set(CMARK_SHARED OFF CACHE BOOL "Build shared libcmark library" FORCE)
|
||||||
|
set(CMARK_TESTS OFF CACHE BOOL "Build cmark tests and enable testing" FORCE)
|
||||||
|
add_subdirectory(libraries/cmark EXCLUDE_FROM_ALL) # Markdown parser
|
||||||
|
add_library(cmark::cmark ALIAS cmark_static)
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system cmark")
|
||||||
|
endif()
|
||||||
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
||||||
|
add_subdirectory(libraries/gamemode)
|
||||||
|
add_subdirectory(libraries/murmur2) # Hash for usage with the CurseForge API
|
||||||
|
if (NOT ghc_filesystem_FOUND)
|
||||||
|
message(STATUS "Using bundled ghc_filesystem")
|
||||||
|
add_subdirectory(libraries/filesystem) # Implementation of std::filesystem for old C++, for usage in old macOS
|
||||||
|
else()
|
||||||
|
message(STATUS "Using system ghc_filesystem")
|
||||||
|
endif()
|
||||||
|
add_subdirectory(libraries/qdcss) # css parser
|
||||||
|
|
||||||
############################### Built Artifacts ###############################
|
############################### Built Artifacts ###############################
|
||||||
|
|
||||||
add_subdirectory(buildconfig)
|
add_subdirectory(buildconfig)
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
# NOTE: this must always be last to appease the CMake deity of quirky install command evaluation order.
|
# NOTE: this must always be last to appease the CMake deity of quirky install command evaluation order.
|
||||||
add_subdirectory(launcher)
|
add_subdirectory(launcher)
|
||||||
|
136
CODE_OF_CONDUCT.md
Normal file
136
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
This is a modified version of the Contributor Covenant.
|
||||||
|
See commit history to see our changes.
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the overall
|
||||||
|
community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
|
any kind
|
||||||
|
* Trolling (antagonistic, inflammatory, insincere behaviour), insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email address,
|
||||||
|
without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement via email at
|
||||||
|
[coc@scrumplex.net](mailto:coc@scrumplex.net) (Email
|
||||||
|
address subject to change).
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series of
|
||||||
|
actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or permanent
|
||||||
|
ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||||
|
community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.1, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||||
|
[https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
69
CONTRIBUTING.md
Normal file
69
CONTRIBUTING.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Contributions Guidelines
|
||||||
|
|
||||||
|
## Code formatting
|
||||||
|
|
||||||
|
Try to follow the existing formatting.
|
||||||
|
If there is no existing formatting, you may use `clang-format` with our included `.clang-format` configuration.
|
||||||
|
|
||||||
|
In general, in order of importance:
|
||||||
|
|
||||||
|
- Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
|
||||||
|
- Prefer readability over dogma.
|
||||||
|
- Keep to the existing formatting.
|
||||||
|
- Indent with 4 space unless it's in a submodule.
|
||||||
|
- Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
|
||||||
|
|
||||||
|
## Signing your work
|
||||||
|
|
||||||
|
In an effort to ensure that the code you contribute is actually compatible with the licenses in this codebase, we require you to sign-off all your contributions.
|
||||||
|
|
||||||
|
This can be done by appending `-s` to your `git commit` call, or by manually appending the following text to your commit message:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<commit message>
|
||||||
|
|
||||||
|
Signed-off-by: Author name <Author email>
|
||||||
|
```
|
||||||
|
|
||||||
|
By signing off your work, you agree to the terms below:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Developer's Certificate of Origin 1.1
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
(a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the open source license
|
||||||
|
indicated in the file; or
|
||||||
|
|
||||||
|
(b) The contribution is based upon previous work that, to the best
|
||||||
|
of my knowledge, is covered under an appropriate open source
|
||||||
|
license and I have the right under that license to submit that
|
||||||
|
work with modifications, whether created in whole or in part
|
||||||
|
by me, under the same open source license (unless I am
|
||||||
|
permitted to submit under a different license), as indicated
|
||||||
|
in the file; or
|
||||||
|
|
||||||
|
(c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a), (b) or (c) and I have not modified
|
||||||
|
it.
|
||||||
|
|
||||||
|
(d) I understand and agree that this project and the contribution
|
||||||
|
are public and that a record of the contribution (including all
|
||||||
|
personal information I submit with it, including my sign-off) is
|
||||||
|
maintained indefinitely and may be redistributed consistent with
|
||||||
|
this project or the open source license(s) involved.
|
||||||
|
```
|
||||||
|
|
||||||
|
These terms will be enforced once you create a pull request, and you will be informed automatically if any of your commits aren't signed-off by you.
|
||||||
|
|
||||||
|
As a bonus, you can also [cryptographically sign your commits][gh-signing-commits] and enable [vigilant mode][gh-vigilant-mode] on GitHub.
|
||||||
|
|
||||||
|
[gh-signing-commits]: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits
|
||||||
|
[gh-vigilant-mode]: https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits
|
||||||
|
|
||||||
|
## Backporting to Release Branches
|
||||||
|
|
||||||
|
We use [automated backports](https://github.com/PrismLauncher/PrismLauncher/blob/develop/.github/workflows/backport.yml) to merge specific contributions from develop into `release` branches.
|
||||||
|
|
||||||
|
This is done when pull requests are merged and have labels such as `backport release-7.x` - which should be added along with the milestone for the release.
|
446
COPYING.md
446
COPYING.md
@ -1,51 +1,121 @@
|
|||||||
# PolyMC
|
## Prism Launcher
|
||||||
|
|
||||||
Copyright (C) 2012-2021 MultiMC Contributors
|
Prism Launcher - Minecraft Launcher
|
||||||
Copyright (C) 2021 PolyMC Contributors
|
Copyright (C) 2022-2023 Prism Launcher Contributors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, version 3.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# MinGW runtime (Windows)
|
This file incorporates work covered by the following copyright and
|
||||||
|
permission notice:
|
||||||
|
|
||||||
Copyright (c) 2012 MinGW.org project
|
Copyright 2013-2021 MultiMC Contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
copy of this software and associated documentation files (the "Software"),
|
you may not use this file except in compliance with the License.
|
||||||
to deal in the Software without restriction, including without limitation
|
You may obtain a copy of the License at
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice, this permission notice and the below disclaimer
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
Unless required by applicable law or agreed to in writing, software
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
See the License for the specific language governing permissions and
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
limitations under the License.
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
# Qt 5
|
## PolyMC
|
||||||
|
|
||||||
Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
PolyMC - Minecraft Launcher
|
||||||
Contact: http://www.qt-project.org/legal
|
Copyright (C) 2021-2022 PolyMC Contributors
|
||||||
|
|
||||||
Licensed under LGPL v2.1
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3.
|
||||||
|
|
||||||
# libnbt++
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
This file incorporates work covered by the following copyright and
|
||||||
|
permission notice:
|
||||||
|
|
||||||
|
Copyright 2013-2021 MultiMC Contributors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
## MinGW-w64 runtime (Windows)
|
||||||
|
|
||||||
|
Copyright (c) 2009, 2010, 2011, 2012, 2013 by the mingw-w64 project
|
||||||
|
|
||||||
|
This license has been certified as open source. It has also been designated
|
||||||
|
as GPL compatible by the Free Software Foundation (FSF).
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions in source code must retain the accompanying copyright
|
||||||
|
notice, this list of conditions, and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the accompanying
|
||||||
|
copyright notice, this list of conditions, and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
3. Names of the copyright holders must not be used to endorse or promote
|
||||||
|
products derived from this software without prior written permission
|
||||||
|
from the copyright holders.
|
||||||
|
4. The right to distribute this software or to use it for any purpose does
|
||||||
|
not give you the right to use Servicemarks (sm) or Trademarks (tm) of
|
||||||
|
the copyright holders. Use of them is covered by separate agreement
|
||||||
|
with the copyright holders.
|
||||||
|
5. If any files are modified, you must cause the modified files to carry
|
||||||
|
prominent notices stating that you changed the files and the date of
|
||||||
|
any change.
|
||||||
|
|
||||||
|
Disclaimer
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
|
||||||
|
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Information on third party licenses used in MinGW-w64 can be found in its COPYING.MinGW-w64-runtime.txt.
|
||||||
|
|
||||||
|
## Qt 5/6
|
||||||
|
|
||||||
|
Copyright (C) 2022 The Qt Company Ltd and other contributors.
|
||||||
|
Contact: https://www.qt.io/licensing
|
||||||
|
|
||||||
|
Licensed under LGPL v3
|
||||||
|
|
||||||
|
## libnbt++
|
||||||
|
|
||||||
libnbt++ - A library for the Minecraft Named Binary Tag format.
|
libnbt++ - A library for the Minecraft Named Binary Tag format.
|
||||||
Copyright (C) 2013, 2015 ljfa-ag
|
Copyright (C) 2013, 2015 ljfa-ag
|
||||||
@ -63,7 +133,7 @@
|
|||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with libnbt++. If not, see <http://www.gnu.org/licenses/>.
|
along with libnbt++. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# rainbow (KGuiAddons)
|
## rainbow (KGuiAddons)
|
||||||
|
|
||||||
Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
|
Copyright (C) 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
|
||||||
Copyright (C) 2007 Olaf Schmidt <ojschmidt@kde.org>
|
Copyright (C) 2007 Olaf Schmidt <ojschmidt@kde.org>
|
||||||
@ -86,25 +156,36 @@
|
|||||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
Boston, MA 02110-1301, USA.
|
Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
# Hoedown
|
## cmark
|
||||||
|
|
||||||
Copyright (c) 2008, Natacha Porté
|
Copyright (c) 2014, John MacFarlane
|
||||||
Copyright (c) 2011, Vicent Martí
|
|
||||||
Copyright (c) 2014, Xavier Mendez, Devin Torres and the Hoedown authors
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
All rights reserved.
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
Redistribution and use in source and binary forms, with or without
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
modification, are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
# Batch icon set
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
## Batch icon set
|
||||||
|
|
||||||
You are free to use Batch (the "icon set") or any part thereof (the "icons")
|
You are free to use Batch (the "icon set") or any part thereof (the "icons")
|
||||||
in any personal, open-source or commercial work without obligation of payment
|
in any personal, open-source or commercial work without obligation of payment
|
||||||
@ -120,7 +201,7 @@
|
|||||||
PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THE USE OF THE ICONS,
|
PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THE USE OF THE ICONS,
|
||||||
EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
# Material Design Icons
|
## Material Design Icons
|
||||||
|
|
||||||
Copyright (c) 2014, Austin Andrews (http://materialdesignicons.com/),
|
Copyright (c) 2014, Austin Andrews (http://materialdesignicons.com/),
|
||||||
with Reserved Font Name Material Design Icons.
|
with Reserved Font Name Material Design Icons.
|
||||||
@ -131,76 +212,82 @@
|
|||||||
This license is copied below, and is also available with a FAQ at:
|
This license is copied below, and is also available with a FAQ at:
|
||||||
http://scripts.sil.org/OFL
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
# Quazip
|
## Quazip
|
||||||
|
|
||||||
Copyright (C) 2005-2011 Sergey A. Tachenov
|
Copyright (C) 2005-2021 Sergey A. Tachenov
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
The QuaZip library is licensed under the GNU Lesser General Public
|
||||||
under the terms of the GNU Lesser General Public License as published by
|
License V2.1 plus a static linking exception.
|
||||||
the Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
The original ZIP/UNZIP package (MiniZip) is copyrighted by Gilles
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
Vollant and contributors, see quazip/(un)zip.h files for details.
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
Basically it's the zlib license.
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
STATIC LINKING EXCEPTION
|
||||||
along with this program; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
The copyright holders give you permission to link this library with
|
||||||
|
independent modules to produce an executable, regardless of the license
|
||||||
|
terms of these independent modules, and to copy and distribute the
|
||||||
|
resulting executable under terms of your choice, provided that you also
|
||||||
|
meet, for each linked independent module, the terms and conditions of
|
||||||
|
the license of that module. An independent module is a module which is
|
||||||
|
not derived from or based on this library. If you modify this library,
|
||||||
|
you must extend this exception to your version of the library.
|
||||||
|
|
||||||
See COPYING file for the full LGPL text.
|
See COPYING file for the full LGPL text.
|
||||||
|
|
||||||
Original ZIP package is copyrighted by Gilles Vollant, see
|
## launcher (`libraries/launcher`)
|
||||||
quazip/(un)zip.h files for details, basically it's zlib license.
|
|
||||||
|
|
||||||
# xz-minidec
|
PolyMC - Minecraft Launcher
|
||||||
|
Copyright (C) 2021-2022 PolyMC Contributors
|
||||||
|
|
||||||
XZ decompressor
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3.
|
||||||
|
|
||||||
Authors: Lasse Collin <lasse.collin@tukaani.org>
|
This program is distributed in the hope that it will be useful,
|
||||||
Igor Pavlov <http://7-zip.org/>
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
This file has been put into the public domain.
|
Linking this library statically or dynamically with other modules is
|
||||||
You can do whatever you want with this file.
|
making a combined work based on this library. Thus, the terms and
|
||||||
|
conditions of the GNU General Public License cover the whole
|
||||||
|
combination.
|
||||||
|
|
||||||
# ColumnResizer
|
As a special exception, the copyright holders of this library give
|
||||||
|
you permission to link this library with independent modules to
|
||||||
|
produce an executable, regardless of the license terms of these
|
||||||
|
independent modules, and to copy and distribute the resulting
|
||||||
|
executable under terms of your choice, provided that you also meet,
|
||||||
|
for each linked independent module, the terms and conditions of the
|
||||||
|
license of that module. An independent module is a module which is
|
||||||
|
not derived from or based on this library. If you modify this
|
||||||
|
library, you may extend this exception to your version of the
|
||||||
|
library, but you are not obliged to do so. If you do not wish to do
|
||||||
|
so, delete this exception statement from your version.
|
||||||
|
|
||||||
Copyright (c) 2011-2016 Aurélien Gâteau and contributors.
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
All rights reserved.
|
This file incorporates work covered by the following copyright and
|
||||||
|
permission notice:
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Copyright 2013-2021 MultiMC Contributors
|
||||||
modification, are permitted (subject to the limitations in the
|
|
||||||
disclaimer below) provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
notice, this list of conditions and the following disclaimer.
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
* The name of the contributors may not be used to endorse or
|
Unless required by applicable law or agreed to in writing, software
|
||||||
promote products derived from this software without specific prior
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
written permission.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
|
## lionshead
|
||||||
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
|
|
||||||
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
||||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
||||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
||||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
# lionshead
|
|
||||||
|
|
||||||
Code has been taken from https://github.com/natefoo/lionshead and loosely
|
Code has been taken from https://github.com/natefoo/lionshead and loosely
|
||||||
translated to C++ laced with Qt.
|
translated to C++ laced with Qt.
|
||||||
@ -227,60 +314,26 @@
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
# optional-bare
|
## tomlplusplus
|
||||||
|
|
||||||
Code from https://github.com/martinmoene/optional-bare/
|
|
||||||
|
|
||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
|
||||||
obtaining a copy of the software and accompanying documentation covered by
|
|
||||||
this license (the "Software") to use, reproduce, display, distribute,
|
|
||||||
execute, and transmit the Software, and to prepare derivative works of the
|
|
||||||
Software, and to permit third-parties to whom the Software is furnished to
|
|
||||||
do so, all subject to the following:
|
|
||||||
|
|
||||||
The copyright notices in the Software and this entire statement, including
|
|
||||||
the above license grant, this restriction and the following disclaimer,
|
|
||||||
must be included in all copies of the Software, in whole or in part, and
|
|
||||||
all derivative works of the Software, unless such copies or derivative
|
|
||||||
works are solely in the form of machine-executable object code generated by
|
|
||||||
a source language processor.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
# tomlc99
|
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 CK Tan
|
Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||||
https://github.com/cktan/tomlc99
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||||
in the Software without restriction, including without limitation the rights
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||||
copies or substantial portions of the Software.
|
Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
# O2 (Katabasis fork)
|
## O2 (Katabasis fork)
|
||||||
|
|
||||||
Copyright (c) 2012, Akos Polster
|
Copyright (c) 2012, Akos Polster
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
@ -305,3 +358,96 @@
|
|||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
## Gamemode
|
||||||
|
|
||||||
|
Copyright (c) 2017-2022, Feral Interactive
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of Feral Interactive nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
## gulrak/filesystem
|
||||||
|
|
||||||
|
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
## Breeze icons
|
||||||
|
|
||||||
|
Copyright (C) 2014 Uri Herrera <uri_herrera@nitrux.in> and others
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
## Oxygen Icons
|
||||||
|
|
||||||
|
The Oxygen Icon Theme
|
||||||
|
Copyright (C) 2007 Nuno Pinheiro <nuno@oxygen-icons.org>
|
||||||
|
Copyright (C) 2007 David Vignoni <david@icon-king.com>
|
||||||
|
Copyright (C) 2007 David Miller <miller@oxygen-icons.org>
|
||||||
|
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
|
||||||
|
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
|
||||||
|
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
|
||||||
|
|
||||||
|
and others
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
138
README.md
138
README.md
@ -1,66 +1,112 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="/program_info/polymc-light.png#gh-light-mode-only" alt="PolyMC logo"/>
|
<picture>
|
||||||
<img src="/program_info/polymc-dark.png#gh-dark-mode-only" alt="PolyMC logo"/>
|
<source media="(prefers-color-scheme: dark)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo-darkmode.svg">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="/program_info/org.prismlauncher.PrismLauncher.logo.svg">
|
||||||
|
<img alt="Prism Launcher" src="/program_info/org.prismlauncher.PrismLauncher.logo.svg" width="40%">
|
||||||
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
<br>
|
|
||||||
PolyMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
|
|
||||||
|
|
||||||
This is a **fork** of the MultiMC Launcher and not endorsed by MultiMC. The PolyMC community felt that the maintainer was not acting in the spirit of Free Software so this fork was made. Read "[Why was this fork made?](https://github.com/PolyMC/PolyMC/wiki/FAQ)" on the wiki for more details.
|
<p align="center">
|
||||||
|
Prism Launcher is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once.<br />
|
||||||
|
<br />This is a <b>fork</b> of the MultiMC Launcher and is <b>not</b> endorsed by it.
|
||||||
|
</p>
|
||||||
|
|
||||||
## Packages
|
## Installation
|
||||||
Several source build packages are available, along with experimental pre-built generic packages.
|
|
||||||
|
|
||||||
<a href='https://flathub.org/apps/details/org.polymc.PolyMC'><img width='240' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/></a>
|
<a href="https://repology.org/project/prismlauncher/versions">
|
||||||
<br>
|
<img src="https://repology.org/badge/vertical-allrepos/prismlauncher.svg" alt="Packaging status" align="right">
|
||||||
[](https://aur.archlinux.org/packages/polymc-git/)
|
</a>
|
||||||
- A [Nix](packages/nix/NIX.md) derivation is available in repo.
|
|
||||||
- A Gentoo ebuild is available in the [swirl](https://git.swurl.xyz/swirl/ebuilds) overlay, named `games-action/polymc`. Check the README for instructions on how to add the overlay.
|
|
||||||
- The Flatpak can be built using [this source](https://github.com/flathub/org.polymc.PolyMC).
|
|
||||||
- An RPM package is available on [COPR](https://copr.fedorainfracloud.org/coprs/sentry/polymc/), or can be built by going to the `packages/rpm` directory and running `rpmbuild -bb polymc.spec`.
|
|
||||||
- Generic, prebuilt packages (archived by version) can be found [here](https://packages.polymc.org/) ([latest](https://packages.polymc.org/latest)).
|
|
||||||
- Last build status: https://jenkins.polymc.org/job/PolyMC/lastBuild/
|
|
||||||
- [Linux (AMD64) System](https://packages.polymc.org/latest/lin64-system/lin64-system.tar.zst) ([SHA256](https://packages.polymc.org/latest/lin64-system/lin64-system.tar.zst.sha256)) - this is a generic system package intended to be used as a base for making distro-specific packages.
|
|
||||||
- [Windows (32-bit)](https://packages.polymc.org/latest/win32/win32.zip) ([SHA256](https://packages.polymc.org/latest/win32/win32.zip.sha256)) - this is a portable package, you can extract it anywhere and run it. This package needs testing.
|
|
||||||
- [Debian (AMD64)](https://packages.polymc.org/latest/deb/polymc-amd64.deb) ([SHA256](https://packages.polymc.org/latest/deb/polymc-amd64.deb.sha256)) - this is intended to be installed with `dpkg -i`. Alternatively, you may build the `.deb` yourself, by going to `packages/debian` and running `./makedeb.sh`.
|
|
||||||
- [AppImage (AMD64)](https://packages.polymc.org/latest/appimage/PolyMC-latest-x86_64.AppImage) ([SHA256](https://packages.polymc.org/latest/appimage/PolyMC-latest-x86_64.AppImage.sha256)) - `chmod +x` must be run on this file before usage. This should work on any distribution.
|
|
||||||
- MacOS currently does not have any packages. We are still working on setting up MacOS packaging.
|
|
||||||
|
|
||||||
## Development
|
- All downloads and instructions for Prism Launcher can be found on our [Website](https://prismlauncher.org/download).
|
||||||
If you want to contribute to PolyMC you might find it useful to join [#development:polymc.org on Matrix](https://matrix.to/#/#development:polymc.org) or join [our Discord server](https://discord.gg/xq7fxrgtMP), which is bridged with the PolyMC Matrix rooms. Thank you!
|
- Last build status can be found in the [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) tab (this also includes the pull requests status).
|
||||||
|
|
||||||
### Building
|
### Development Builds
|
||||||
If you want to build PolyMC yourself, check [BUILD.md](BUILD.md) for build instructions.
|
|
||||||
|
|
||||||
You can build the flatpak using [this source](https://github.com/flathub/org.polymc.PolyMC).
|
Please understand that these builds are not intended for most users. There may be bugs, and other instabilities. You have been warned.
|
||||||
|
|
||||||
### Code formatting
|
There are development builds available through:
|
||||||
Just follow the existing formatting.
|
|
||||||
|
|
||||||
In general, in order of importance:
|
- [GitHub Actions](https://github.com/PrismLauncher/PrismLauncher/actions) (includes builds from pull requests opened by contribuitors)
|
||||||
* Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
|
- [nightly.link](https://nightly.link/PrismLauncher/PrismLauncher/workflows/trigger_builds/develop) (this will always point only to the latest version of develop)
|
||||||
* Prefer readability over dogma.
|
|
||||||
* Keep to the existing formatting.
|
These have debug information in the binaries, so their file sizes are relatively larger.
|
||||||
* Indent with 4 space unless it's in a submodule.
|
|
||||||
* Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
|
Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS**.
|
||||||
|
|
||||||
|
For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions:
|
||||||
|
|
||||||
|
[](https://aur.archlinux.org/packages/prismlauncher-git) [](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [](https://mpr.makedeb.org/packages/prismlauncher-git)<br />[](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [](https://build.opensuse.org/project/show/home:getchoo) [](https://packages.gentoo.org/packages/games-action/prismlauncher)
|
||||||
|
|
||||||
|
These packages are also available to all the distributions based on the ones mentioned above.
|
||||||
|
|
||||||
|
## Community & Support
|
||||||
|
|
||||||
|
Feel free to create a GitHub issue if you find a bug or want to suggest a new feature. We have multiple community spaces where other community members can help you:
|
||||||
|
|
||||||
|
- **Our Discord server:**
|
||||||
|
|
||||||
|
[](https://prismlauncher.org/discord)
|
||||||
|
|
||||||
|
- **Our Matrix space:**
|
||||||
|
|
||||||
|
[](https://prismlauncher.org/matrix)
|
||||||
|
|
||||||
|
- **Our Subreddit:**
|
||||||
|
|
||||||
|
[](https://prismlauncher.org/reddit)
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
TODO
|
|
||||||
|
The translation effort for Prism Launcher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at <https://github.com/PrismLauncher/Translations>.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
If you want to build Prism Launcher yourself, check the [Build Instructions](https://prismlauncher.org/wiki/development/build-instructions/).
|
||||||
|
|
||||||
|
## Sponsors & Partners
|
||||||
|
|
||||||
|
We thank all the wonderful backers over at Open Collective! Support Prism Launcher by [becoming a backer](https://opencollective.com/prismlauncher).
|
||||||
|
|
||||||
|
[](https://opencollective.com/prismlauncher#backers)
|
||||||
|
|
||||||
|
Thanks to JetBrains for providing us a few licenses for all their products, as part of their [Open Source program](https://www.jetbrains.com/opensource/).
|
||||||
|
|
||||||
|
[](https://www.jetbrains.com/opensource/)
|
||||||
|
|
||||||
|
Thanks to Weblate for hosting our translation efforts.
|
||||||
|
|
||||||
|
<a href="https://hosted.weblate.org/engage/prismlauncher/">
|
||||||
|
<img src="https://hosted.weblate.org/widgets/prismlauncher/-/open-graph.png" alt="Translation status" width="300" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
Thanks to Netlify for providing us their excellent web services, as part of their [Open Source program](https://www.netlify.com/open-source/).
|
||||||
|
|
||||||
|
<a href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-accent.svg" alt="Deploys by Netlify" /> </a>
|
||||||
|
|
||||||
|
Thanks to the awesome people over at [MacStadium](https://www.macstadium.com/), for providing M1-Macs for development purposes!
|
||||||
|
|
||||||
|
<a href="https://www.macstadium.com"><img src="https://uploads-ssl.webflow.com/5ac3c046c82724970fc60918/5c019d917bba312af7553b49_MacStadium-developerlogo.png" alt="Powered by MacStadium" width="300"></a>
|
||||||
|
|
||||||
## Forking/Redistributing/Custom builds policy
|
## Forking/Redistributing/Custom builds policy
|
||||||
Do whatever you want, we don't care. Just follow the license. If you have any questions about this feel free to ask in an issue.
|
|
||||||
|
|
||||||
## Help & Support
|
You are free to fork, redistribute and provide custom builds as long as you follow the terms of the [license](LICENSE) (this is a legal responsibility), and if you made code changes rather than just packaging a custom build, please do the following as a basic courtesy:
|
||||||
Feel free to create an issue if you need help. However, you might find it easier to ask in the Discord server.
|
|
||||||
|
|
||||||
[](https://discord.gg/xq7fxrgtMP)
|
- Make it clear that your fork is not Prism Launcher and is not endorsed by or affiliated with the Prism Launcher project (<https://prismlauncher.org>).
|
||||||
|
- Go through [CMakeLists.txt](CMakeLists.txt) and change Prism Launcher's API keys to your own or set them to empty strings (`""`) to disable them (this way the program will still compile but the functionality requiring those keys will be disabled).
|
||||||
|
|
||||||
For people who don't want to use Discord, we have a Matrix Space which is bridged to the Discord server:
|
If you have any questions or want any clarification on the above conditions please make an issue and ask us.
|
||||||
|
|
||||||
[](https://matrix.to/#/#polymc:polymc.org)
|
If you are just building Prism Launcher for your distribution, please make sure to set the `Launcher_BUILD_PLATFORM` to a slug representing your distribution. Examples are `archlinux`, `fedora` and `nixpkgs`.
|
||||||
|
|
||||||
If there are any issues with the space or you are using a client that does not support the feature here are the individual rooms:
|
Note that if you build this software without removing the provided API keys in [CMakeLists.txt](CMakeLists.txt) you are accepting the following terms and conditions:
|
||||||
|
|
||||||
[](https://matrix.to/#/#support:polymc.org)
|
- [Microsoft Identity Platform Terms of Use](https://docs.microsoft.com/en-us/legal/microsoft-identity-platform/terms-of-use)
|
||||||
[](https://matrix.to/#/#discussion:polymc.org)
|
- [CurseForge 3rd Party API Terms and Conditions](https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions)
|
||||||
[](https://matrix.to/#/#development:polymc.org)
|
|
||||||
[](https://matrix.to/#/#news:polymc.org)
|
If you do not agree with these terms and conditions, then remove the associated API keys from the [CMakeLists.txt](CMakeLists.txt) file by setting them to an empty string (`""`).
|
||||||
|
|
||||||
|
## License [](LICENSE)
|
||||||
|
|
||||||
|
All launcher code is available under the GPL-3.0-only license.
|
||||||
|
|
||||||
|
The logo and related assets are under the CC BY-SA 4.0 license.
|
||||||
|
@ -1,3 +1,39 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qstringliteral.h>
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
@ -7,11 +43,14 @@ Config::Config()
|
|||||||
{
|
{
|
||||||
// Name and copyright
|
// Name and copyright
|
||||||
LAUNCHER_NAME = "@Launcher_Name@";
|
LAUNCHER_NAME = "@Launcher_Name@";
|
||||||
|
LAUNCHER_APP_BINARY_NAME = "@Launcher_APP_BINARY_NAME@";
|
||||||
LAUNCHER_DISPLAYNAME = "@Launcher_DisplayName@";
|
LAUNCHER_DISPLAYNAME = "@Launcher_DisplayName@";
|
||||||
LAUNCHER_COPYRIGHT = "@Launcher_Copyright@";
|
LAUNCHER_COPYRIGHT = "@Launcher_Copyright@";
|
||||||
LAUNCHER_DOMAIN = "@Launcher_Domain@";
|
LAUNCHER_DOMAIN = "@Launcher_Domain@";
|
||||||
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
|
LAUNCHER_CONFIGFILE = "@Launcher_ConfigFile@";
|
||||||
LAUNCHER_GIT = "@Launcher_Git@";
|
LAUNCHER_GIT = "@Launcher_Git@";
|
||||||
|
LAUNCHER_DESKTOPFILENAME = "@Launcher_DesktopFileName@";
|
||||||
|
LAUNCHER_SVGFILENAME = "@Launcher_SVGFileName@";
|
||||||
|
|
||||||
USER_AGENT = "@Launcher_UserAgent@";
|
USER_AGENT = "@Launcher_UserAgent@";
|
||||||
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
|
USER_AGENT_UNCACHED = USER_AGENT + " (Uncached)";
|
||||||
@ -19,53 +58,102 @@ Config::Config()
|
|||||||
// Version information
|
// Version information
|
||||||
VERSION_MAJOR = @Launcher_VERSION_MAJOR@;
|
VERSION_MAJOR = @Launcher_VERSION_MAJOR@;
|
||||||
VERSION_MINOR = @Launcher_VERSION_MINOR@;
|
VERSION_MINOR = @Launcher_VERSION_MINOR@;
|
||||||
VERSION_HOTFIX = @Launcher_VERSION_HOTFIX@;
|
|
||||||
VERSION_BUILD = @Launcher_VERSION_BUILD@;
|
|
||||||
|
|
||||||
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
||||||
UPDATER_BASE = "@Launcher_UPDATER_BASE@";
|
BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@";
|
||||||
NOTIFICATION_URL = "@Launcher_NOTIFICATION_URL@";
|
BUILD_DATE = "@Launcher_BUILD_TIMESTAMP@";
|
||||||
FULL_VERSION_STR = "@Launcher_VERSION_MAJOR@.@Launcher_VERSION_MINOR@.@Launcher_VERSION_BUILD@";
|
UPDATER_GITHUB_REPO = "@Launcher_UPDATER_GITHUB_REPO@";
|
||||||
|
|
||||||
|
COMPILER_NAME = "@Launcher_COMPILER_NAME@";
|
||||||
|
COMPILER_VERSION = "@Launcher_COMPILER_VERSION@";
|
||||||
|
|
||||||
|
COMPILER_TARGET_SYSTEM = "@Launcher_COMPILER_TARGET_SYSTEM@";
|
||||||
|
COMPILER_TARGET_SYSTEM_VERSION = "@Launcher_COMPILER_TARGET_SYSTEM_VERSION@";
|
||||||
|
COMPILER_TARGET_SYSTEM_PROCESSOR = "@Launcher_COMPILER_TARGET_PROCESSOR@";
|
||||||
|
|
||||||
|
MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@";
|
||||||
|
MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@";
|
||||||
|
|
||||||
|
if (!MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty())
|
||||||
|
{
|
||||||
|
UPDATER_ENABLED = true;
|
||||||
|
} else if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) {
|
||||||
|
UPDATER_ENABLED = true;
|
||||||
|
}
|
||||||
|
|
||||||
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
|
||||||
|
GIT_TAG = "@Launcher_GIT_TAG@";
|
||||||
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
|
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
|
||||||
if(GIT_REFSPEC.startsWith("refs/heads/") && !UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty() && VERSION_BUILD >= 0)
|
|
||||||
|
// Assume that builds outside of Git repos are "stable"
|
||||||
|
if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
|
||||||
|
|| GIT_TAG == QStringLiteral("GITDIR-NOTFOUND")
|
||||||
|
|| GIT_REFSPEC == QStringLiteral("")
|
||||||
|
|| GIT_TAG == QStringLiteral("GIT-NOTFOUND"))
|
||||||
|
{
|
||||||
|
GIT_REFSPEC = "refs/heads/stable";
|
||||||
|
GIT_TAG = versionString();
|
||||||
|
GIT_COMMIT = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GIT_REFSPEC.startsWith("refs/heads/"))
|
||||||
{
|
{
|
||||||
VERSION_CHANNEL = GIT_REFSPEC;
|
VERSION_CHANNEL = GIT_REFSPEC;
|
||||||
VERSION_CHANNEL.remove("refs/heads/");
|
VERSION_CHANNEL.remove("refs/heads/");
|
||||||
UPDATER_ENABLED = true;
|
}
|
||||||
|
else if (!GIT_COMMIT.isEmpty())
|
||||||
|
{
|
||||||
|
VERSION_CHANNEL = GIT_COMMIT.mid(0, 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VERSION_CHANNEL = QObject::tr("custom");
|
VERSION_CHANNEL = "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
VERSION_STR = "@Launcher_VERSION_STRING@";
|
|
||||||
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
|
NEWS_RSS_URL = "@Launcher_NEWS_RSS_URL@";
|
||||||
PASTE_EE_KEY = "@Launcher_PASTE_EE_API_KEY@";
|
NEWS_OPEN_URL = "@Launcher_NEWS_OPEN_URL@";
|
||||||
|
HELP_URL = "@Launcher_HELP_URL@";
|
||||||
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
|
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
|
||||||
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
|
||||||
|
FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
|
||||||
META_URL = "@Launcher_META_URL@";
|
META_URL = "@Launcher_META_URL@";
|
||||||
|
|
||||||
|
GLFW_LIBRARY_NAME = "@Launcher_GLFW_LIBRARY_NAME@";
|
||||||
|
OPENAL_LIBRARY_NAME = "@Launcher_OPENAL_LIBRARY_NAME@";
|
||||||
|
|
||||||
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
|
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
|
||||||
|
TRANSLATIONS_URL = "@Launcher_TRANSLATIONS_URL@";
|
||||||
|
MATRIX_URL = "@Launcher_MATRIX_URL@";
|
||||||
DISCORD_URL = "@Launcher_DISCORD_URL@";
|
DISCORD_URL = "@Launcher_DISCORD_URL@";
|
||||||
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
|
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Config::versionString() const
|
||||||
|
{
|
||||||
|
return QString("%1.%2").arg(VERSION_MAJOR).arg(VERSION_MINOR);
|
||||||
|
}
|
||||||
|
|
||||||
QString Config::printableVersionString() const
|
QString Config::printableVersionString() const
|
||||||
{
|
{
|
||||||
QString vstr = QString("%1.%2.%3").arg(QString::number(VERSION_MAJOR), QString::number(VERSION_MINOR), QString::number(VERSION_HOTFIX));
|
QString vstr = versionString();
|
||||||
|
|
||||||
// If the build is not a main release, append the channel
|
// If the build is not a main release, append the channel
|
||||||
if(VERSION_CHANNEL != "stable")
|
if(VERSION_CHANNEL != "stable" && GIT_TAG != vstr)
|
||||||
{
|
{
|
||||||
vstr += "-" + VERSION_CHANNEL;
|
vstr += "-" + VERSION_CHANNEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if a build number is set, also add it to the end
|
|
||||||
if(VERSION_BUILD >= 0)
|
|
||||||
{
|
|
||||||
vstr += "-" + QString::number(VERSION_BUILD);
|
|
||||||
}
|
|
||||||
return vstr;
|
return vstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Config::compilerID() const
|
||||||
|
{
|
||||||
|
if (COMPILER_VERSION.isEmpty())
|
||||||
|
return COMPILER_NAME;
|
||||||
|
return QStringLiteral("%1 - %2").arg(COMPILER_NAME).arg(COMPILER_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Config::systemID() const
|
||||||
|
{
|
||||||
|
return QStringLiteral("%1 %2 %3").arg(COMPILER_TARGET_SYSTEM, COMPILER_TARGET_SYSTEM_VERSION, COMPILER_TARGET_SYSTEM_PROCESSOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,28 +1,64 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <QList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief The Config class holds all the build-time information passed from the build system.
|
* \brief The Config class holds all the build-time information passed from the build system.
|
||||||
*/
|
*/
|
||||||
class Config
|
class Config {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
Config();
|
Config();
|
||||||
QString LAUNCHER_NAME;
|
QString LAUNCHER_NAME;
|
||||||
|
QString LAUNCHER_APP_BINARY_NAME;
|
||||||
QString LAUNCHER_DISPLAYNAME;
|
QString LAUNCHER_DISPLAYNAME;
|
||||||
QString LAUNCHER_COPYRIGHT;
|
QString LAUNCHER_COPYRIGHT;
|
||||||
QString LAUNCHER_DOMAIN;
|
QString LAUNCHER_DOMAIN;
|
||||||
QString LAUNCHER_CONFIGFILE;
|
QString LAUNCHER_CONFIGFILE;
|
||||||
QString LAUNCHER_GIT;
|
QString LAUNCHER_GIT;
|
||||||
|
QString LAUNCHER_DESKTOPFILENAME;
|
||||||
|
QString LAUNCHER_SVGFILENAME;
|
||||||
|
|
||||||
/// The major version number.
|
/// The major version number.
|
||||||
int VERSION_MAJOR;
|
int VERSION_MAJOR;
|
||||||
/// The minor version number.
|
/// The minor version number.
|
||||||
int VERSION_MINOR;
|
int VERSION_MINOR;
|
||||||
/// The hotfix number.
|
|
||||||
int VERSION_HOTFIX;
|
|
||||||
/// The build number.
|
|
||||||
int VERSION_BUILD;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The version channel
|
* The version channel
|
||||||
@ -32,12 +68,38 @@ public:
|
|||||||
|
|
||||||
bool UPDATER_ENABLED = false;
|
bool UPDATER_ENABLED = false;
|
||||||
|
|
||||||
/// A short string identifying this build's platform. For example, "lin64" or "win32".
|
/// A short string identifying this build's platform or distribution.
|
||||||
QString BUILD_PLATFORM;
|
QString BUILD_PLATFORM;
|
||||||
|
|
||||||
/// URL for the updater's channel
|
/// A short string identifying this build's valid artifacts int he updater. For example, "lin64" or "win32".
|
||||||
QString UPDATER_BASE;
|
QString BUILD_ARTIFACT;
|
||||||
|
|
||||||
|
/// A string containing the build timestamp
|
||||||
|
QString BUILD_DATE;
|
||||||
|
|
||||||
|
/// A string identifying the compiler use to build
|
||||||
|
QString COMPILER_NAME;
|
||||||
|
|
||||||
|
/// A string identifying the compiler version used to build
|
||||||
|
QString COMPILER_VERSION;
|
||||||
|
|
||||||
|
/// A string identifying the compiler target system os
|
||||||
|
QString COMPILER_TARGET_SYSTEM;
|
||||||
|
|
||||||
|
/// A String identifying the compiler target system version
|
||||||
|
QString COMPILER_TARGET_SYSTEM_VERSION;
|
||||||
|
|
||||||
|
/// A String identifying the compiler target processor
|
||||||
|
QString COMPILER_TARGET_SYSTEM_PROCESSOR;
|
||||||
|
|
||||||
|
/// URL for the updater's channel
|
||||||
|
QString UPDATER_GITHUB_REPO;
|
||||||
|
|
||||||
|
/// The public key used to sign releases for the Sparkle updater appcast
|
||||||
|
QString MAC_SPARKLE_PUB_KEY;
|
||||||
|
|
||||||
|
/// URL for the Sparkle updater's appcast
|
||||||
|
QString MAC_SPARKLE_APPCAST_URL;
|
||||||
|
|
||||||
/// User-Agent to use.
|
/// User-Agent to use.
|
||||||
QString USER_AGENT;
|
QString USER_AGENT;
|
||||||
@ -45,22 +107,15 @@ public:
|
|||||||
/// User-Agent to use for uncached requests.
|
/// User-Agent to use for uncached requests.
|
||||||
QString USER_AGENT_UNCACHED;
|
QString USER_AGENT_UNCACHED;
|
||||||
|
|
||||||
|
|
||||||
/// URL for notifications
|
|
||||||
QString NOTIFICATION_URL;
|
|
||||||
|
|
||||||
/// Used for matching notifications
|
|
||||||
QString FULL_VERSION_STR;
|
|
||||||
|
|
||||||
/// The git commit hash of this build
|
/// The git commit hash of this build
|
||||||
QString GIT_COMMIT;
|
QString GIT_COMMIT;
|
||||||
|
|
||||||
|
/// The git tag of this build
|
||||||
|
QString GIT_TAG;
|
||||||
|
|
||||||
/// The git refspec of this build
|
/// The git refspec of this build
|
||||||
QString GIT_REFSPEC;
|
QString GIT_REFSPEC;
|
||||||
|
|
||||||
/// This is printed on start to standard output
|
|
||||||
QString VERSION_STR;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used to fetch the news RSS feed.
|
* This is used to fetch the news RSS feed.
|
||||||
* It defaults in CMakeLists.txt to "https://multimc.org/rss.xml"
|
* It defaults in CMakeLists.txt to "https://multimc.org/rss.xml"
|
||||||
@ -68,9 +123,14 @@ public:
|
|||||||
QString NEWS_RSS_URL;
|
QString NEWS_RSS_URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API key you can get from paste.ee when you register an account
|
* URL that gets opened when the user clicks "More News"
|
||||||
*/
|
*/
|
||||||
QString PASTE_EE_KEY;
|
QString NEWS_OPEN_URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help
|
||||||
|
*/
|
||||||
|
QString HELP_URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client ID you can get from Imgur when you register an application
|
* Client ID you can get from Imgur when you register an application
|
||||||
@ -82,12 +142,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
QString MSA_CLIENT_ID;
|
QString MSA_CLIENT_ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client API key for CurseForge
|
||||||
|
*/
|
||||||
|
QString FLAME_API_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata repository URL prefix
|
* Metadata repository URL prefix
|
||||||
*/
|
*/
|
||||||
QString META_URL;
|
QString META_URL;
|
||||||
|
|
||||||
|
QString GLFW_LIBRARY_NAME;
|
||||||
|
QString OPENAL_LIBRARY_NAME;
|
||||||
|
|
||||||
QString BUG_TRACKER_URL;
|
QString BUG_TRACKER_URL;
|
||||||
|
QString TRANSLATIONS_URL;
|
||||||
|
QString MATRIX_URL;
|
||||||
QString DISCORD_URL;
|
QString DISCORD_URL;
|
||||||
QString SUBREDDIT_URL;
|
QString SUBREDDIT_URL;
|
||||||
|
|
||||||
@ -95,21 +165,46 @@ public:
|
|||||||
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
|
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
|
||||||
QString AUTH_BASE = "https://authserver.mojang.com/";
|
QString AUTH_BASE = "https://authserver.mojang.com/";
|
||||||
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
|
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
|
||||||
QString FMLLIBS_BASE_URL = "https://files.multimc.org/fmllibs/";
|
QString FMLLIBS_BASE_URL = "https://files.prismlauncher.org/fmllibs/"; // FIXME: move into CMakeLists
|
||||||
QString TRANSLATIONS_BASE_URL = "https://files.multimc.org/translations/";
|
QString TRANSLATIONS_BASE_URL = "https://i18n.prismlauncher.org/"; // FIXME: move into CMakeLists
|
||||||
|
|
||||||
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
|
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";
|
||||||
|
|
||||||
QString LEGACY_FTB_CDN_BASE_URL = "https://dist.creeper.host/FTB2/";
|
QString LEGACY_FTB_CDN_BASE_URL = "https://dist.creeper.host/FTB2/";
|
||||||
|
|
||||||
QString ATL_DOWNLOAD_SERVER_URL = "https://download.nodecdn.net/containers/atl/";
|
QString ATL_DOWNLOAD_SERVER_URL = "https://download.nodecdn.net/containers/atl/";
|
||||||
|
QString ATL_API_BASE_URL = "https://api.atlauncher.com/v1/";
|
||||||
|
|
||||||
|
QString TECHNIC_API_BASE_URL = "https://api.technicpack.net/";
|
||||||
|
/**
|
||||||
|
* The build that is reported to the Technic API.
|
||||||
|
*/
|
||||||
|
QString TECHNIC_API_BUILD = "multimc";
|
||||||
|
|
||||||
|
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
|
||||||
|
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
|
||||||
|
QStringList MODRINTH_MRPACK_HOSTS{ "cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com" };
|
||||||
|
|
||||||
|
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
|
||||||
|
|
||||||
|
QString versionString() const;
|
||||||
/**
|
/**
|
||||||
* \brief Converts the Version to a string.
|
* \brief Converts the Version to a string.
|
||||||
* \return The version number in string format (major.minor.revision.build).
|
* \return The version number in string format (major.minor.revision.build).
|
||||||
*/
|
*/
|
||||||
QString printableVersionString() const;
|
QString printableVersionString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compiler ID String
|
||||||
|
* \return a string of the form "Name - Version" of just "Name" if the version is empty
|
||||||
|
*/
|
||||||
|
QString compilerID() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief System ID String
|
||||||
|
* \return a string of the form "OS Verison Processor"
|
||||||
|
*/
|
||||||
|
QString systemID() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const Config BuildConfig;
|
extern const Config BuildConfig;
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@ add_library(BuildConfig STATIC
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}/BuildConfig.cpp
|
${CMAKE_CURRENT_BINARY_DIR}/BuildConfig.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(BuildConfig Qt5::Core)
|
target_link_libraries(BuildConfig Qt${QT_VERSION_MAJOR}::Core)
|
||||||
target_include_directories(BuildConfig PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
target_include_directories(BuildConfig PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
1532
changelog.md
1532
changelog.md
File diff suppressed because it is too large
Load Diff
@ -1,786 +0,0 @@
|
|||||||
# - Functions to help assemble a standalone bundle application.
|
|
||||||
# A collection of CMake utility functions useful for dealing with .app
|
|
||||||
# bundles on the Mac and bundle-like directories on any OS.
|
|
||||||
#
|
|
||||||
# The following functions are provided by this module:
|
|
||||||
# fixup_bundle
|
|
||||||
# copy_and_fixup_bundle
|
|
||||||
# verify_app
|
|
||||||
# get_bundle_main_executable
|
|
||||||
# get_dotapp_dir
|
|
||||||
# get_bundle_and_executable
|
|
||||||
# get_bundle_all_executables
|
|
||||||
# get_item_key
|
|
||||||
# clear_bundle_keys
|
|
||||||
# set_bundle_key_values
|
|
||||||
# get_bundle_keys
|
|
||||||
# copy_resolved_item_into_bundle
|
|
||||||
# copy_resolved_framework_into_bundle
|
|
||||||
# fixup_bundle_item
|
|
||||||
# verify_bundle_prerequisites
|
|
||||||
# verify_bundle_symlinks
|
|
||||||
# Requires CMake 2.6 or greater because it uses function, break and
|
|
||||||
# PARENT_SCOPE. Also depends on GetPrerequisites.cmake.
|
|
||||||
#
|
|
||||||
# FIXUP_BUNDLE(<app> <libs> <dirs>)
|
|
||||||
# Fix up a bundle in-place and make it standalone, such that it can be
|
|
||||||
# drag-n-drop copied to another machine and run on that machine as long as all
|
|
||||||
# of the system libraries are compatible.
|
|
||||||
#
|
|
||||||
# If you pass plugins to fixup_bundle as the libs parameter, you should install
|
|
||||||
# them or copy them into the bundle before calling fixup_bundle. The "libs"
|
|
||||||
# parameter is a list of libraries that must be fixed up, but that cannot be
|
|
||||||
# determined by otool output analysis. (i.e., plugins)
|
|
||||||
#
|
|
||||||
# Gather all the keys for all the executables and libraries in a bundle, and
|
|
||||||
# then, for each key, copy each prerequisite into the bundle. Then fix each one
|
|
||||||
# up according to its own list of prerequisites.
|
|
||||||
#
|
|
||||||
# Then clear all the keys and call verify_app on the final bundle to ensure
|
|
||||||
# that it is truly standalone.
|
|
||||||
#
|
|
||||||
# COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
|
|
||||||
# Makes a copy of the bundle <src> at location <dst> and then fixes up the
|
|
||||||
# new copied bundle in-place at <dst>...
|
|
||||||
#
|
|
||||||
# VERIFY_APP(<app>)
|
|
||||||
# Verifies that an application <app> appears valid based on running analysis
|
|
||||||
# tools on it. Calls "message(FATAL_ERROR" if the application is not verified.
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
|
|
||||||
# The result will be the full path name of the bundle's main executable file
|
|
||||||
# or an "error:" prefixed string if it could not be determined.
|
|
||||||
#
|
|
||||||
# GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
|
|
||||||
# Returns the nearest parent dir whose name ends with ".app" given the full
|
|
||||||
# path to an executable. If there is no such parent dir, then simply return
|
|
||||||
# the dir containing the executable.
|
|
||||||
#
|
|
||||||
# The returned directory may or may not exist.
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
|
|
||||||
# Takes either a ".app" directory name or the name of an executable
|
|
||||||
# nested inside a ".app" directory and returns the path to the ".app"
|
|
||||||
# directory in <bundle_var> and the path to its main executable in
|
|
||||||
# <executable_var>
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
|
|
||||||
# Scans the given bundle recursively for all executable files and accumulates
|
|
||||||
# them into a variable.
|
|
||||||
#
|
|
||||||
# GET_ITEM_KEY(<item> <key_var>)
|
|
||||||
# Given a file (item) name, generate a key that should be unique considering
|
|
||||||
# the set of libraries that need copying or fixing up to make a bundle
|
|
||||||
# standalone. This is essentially the file name including extension with "."
|
|
||||||
# replaced by "_"
|
|
||||||
#
|
|
||||||
# This key is used as a prefix for CMake variables so that we can associate a
|
|
||||||
# set of variables with a given item based on its key.
|
|
||||||
#
|
|
||||||
# CLEAR_BUNDLE_KEYS(<keys_var>)
|
|
||||||
# Loop over the list of keys, clearing all the variables associated with each
|
|
||||||
# key. After the loop, clear the list of keys itself.
|
|
||||||
#
|
|
||||||
# Caller of get_bundle_keys should call clear_bundle_keys when done with list
|
|
||||||
# of keys.
|
|
||||||
#
|
|
||||||
# SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
|
|
||||||
# <copyflag>)
|
|
||||||
# Add a key to the list (if necessary) for the given item. If added,
|
|
||||||
# also set all the variables associated with that key.
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
|
|
||||||
# Loop over all the executable and library files within the bundle (and given
|
|
||||||
# as extra <libs>) and accumulate a list of keys representing them. Set
|
|
||||||
# values associated with each key such that we can loop over all of them and
|
|
||||||
# copy prerequisite libs into the bundle and then do appropriate
|
|
||||||
# install_name_tool fixups.
|
|
||||||
#
|
|
||||||
# COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
|
|
||||||
# Copy a resolved item into the bundle if necessary. Copy is not necessary if
|
|
||||||
# the resolved_item is "the same as" the resolved_embedded_item.
|
|
||||||
#
|
|
||||||
# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
|
|
||||||
# Copy a resolved framework into the bundle if necessary. Copy is not necessary
|
|
||||||
# if the resolved_item is "the same as" the resolved_embedded_item.
|
|
||||||
#
|
|
||||||
# By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set. If you want full
|
|
||||||
# frameworks embedded in your bundles, set BU_COPY_FULL_FRAMEWORK_CONTENTS to
|
|
||||||
# ON before calling fixup_bundle. By default,
|
|
||||||
# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework dylib itself plus
|
|
||||||
# the framework Resources directory.
|
|
||||||
#
|
|
||||||
# FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
|
|
||||||
# Get the direct/non-system prerequisites of the resolved embedded item. For
|
|
||||||
# each prerequisite, change the way it is referenced to the value of the
|
|
||||||
# _EMBEDDED_ITEM keyed variable for that prerequisite. (Most likely changing to
|
|
||||||
# an "@executable_path" style reference.)
|
|
||||||
#
|
|
||||||
# This function requires that the resolved_embedded_item be "inside" the bundle
|
|
||||||
# already. In other words, if you pass plugins to fixup_bundle as the libs
|
|
||||||
# parameter, you should install them or copy them into the bundle before
|
|
||||||
# calling fixup_bundle. The "libs" parameter is a list of libraries that must
|
|
||||||
# be fixed up, but that cannot be determined by otool output analysis. (i.e.,
|
|
||||||
# plugins)
|
|
||||||
#
|
|
||||||
# Also, change the id of the item being fixed up to its own _EMBEDDED_ITEM
|
|
||||||
# value.
|
|
||||||
#
|
|
||||||
# Accumulate changes in a local variable and make *one* call to
|
|
||||||
# install_name_tool at the end of the function with all the changes at once.
|
|
||||||
#
|
|
||||||
# If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be
|
|
||||||
# marked writable before install_name_tool tries to change them.
|
|
||||||
#
|
|
||||||
# VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
|
|
||||||
# Verifies that the sum of all prerequisites of all files inside the bundle
|
|
||||||
# are contained within the bundle or are "system" libraries, presumed to exist
|
|
||||||
# everywhere.
|
|
||||||
#
|
|
||||||
# VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
|
|
||||||
# Verifies that any symlinks found in the bundle point to other files that are
|
|
||||||
# already also in the bundle... Anything that points to an external file causes
|
|
||||||
# this function to fail the verification.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2008-2009 Kitware, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
# The functions defined in this file depend on the get_prerequisites function
|
|
||||||
# (and possibly others) found in:
|
|
||||||
#
|
|
||||||
get_filename_component(BundleUtilities_cmake_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
|
||||||
include("${BundleUtilities_cmake_dir}/GetPrerequisites.cmake")
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_main_executable bundle result_var)
|
|
||||||
set(result "error: '${bundle}/Contents/Info.plist' file does not exist")
|
|
||||||
|
|
||||||
if(EXISTS "${bundle}/Contents/Info.plist")
|
|
||||||
set(result "error: no CFBundleExecutable in '${bundle}/Contents/Info.plist' file")
|
|
||||||
set(line_is_main_executable 0)
|
|
||||||
set(bundle_executable "")
|
|
||||||
|
|
||||||
# Read Info.plist as a list of lines:
|
|
||||||
#
|
|
||||||
set(eol_char "E")
|
|
||||||
file(READ "${bundle}/Contents/Info.plist" info_plist)
|
|
||||||
string(REGEX REPLACE ";" "\\\\;" info_plist "${info_plist}")
|
|
||||||
string(REGEX REPLACE "\n" "${eol_char};" info_plist "${info_plist}")
|
|
||||||
|
|
||||||
# Scan the lines for "<key>CFBundleExecutable</key>" - the line after that
|
|
||||||
# is the name of the main executable.
|
|
||||||
#
|
|
||||||
foreach(line ${info_plist})
|
|
||||||
if(line_is_main_executable)
|
|
||||||
string(REGEX REPLACE "^.*<string>(.*)</string>.*$" "\\1" bundle_executable "${line}")
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(line MATCHES "^.*<key>CFBundleExecutable</key>.*$")
|
|
||||||
set(line_is_main_executable 1)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT "${bundle_executable}" STREQUAL "")
|
|
||||||
if(EXISTS "${bundle}/Contents/MacOS/${bundle_executable}")
|
|
||||||
set(result "${bundle}/Contents/MacOS/${bundle_executable}")
|
|
||||||
else()
|
|
||||||
|
|
||||||
# Ultimate goal:
|
|
||||||
# If not in "Contents/MacOS" then scan the bundle for matching files. If
|
|
||||||
# there is only one executable file that matches, then use it, otherwise
|
|
||||||
# it's an error...
|
|
||||||
#
|
|
||||||
#file(GLOB_RECURSE file_list "${bundle}/${bundle_executable}")
|
|
||||||
|
|
||||||
# But for now, pragmatically, it's an error. Expect the main executable
|
|
||||||
# for the bundle to be in Contents/MacOS, it's an error if it's not:
|
|
||||||
#
|
|
||||||
set(result "error: '${bundle}/Contents/MacOS/${bundle_executable}' does not exist")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
#
|
|
||||||
# More inclusive technique... (This one would work on Windows and Linux
|
|
||||||
# too, if a developer followed the typical Mac bundle naming convention...)
|
|
||||||
#
|
|
||||||
# If there is no Info.plist file, try to find an executable with the same
|
|
||||||
# base name as the .app directory:
|
|
||||||
#
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_dotapp_dir exe dotapp_dir_var)
|
|
||||||
set(s "${exe}")
|
|
||||||
|
|
||||||
if(s MATCHES "^.*/.*\\.app/.*$")
|
|
||||||
# If there is a ".app" parent directory,
|
|
||||||
# ascend until we hit it:
|
|
||||||
# (typical of a Mac bundle executable)
|
|
||||||
#
|
|
||||||
set(done 0)
|
|
||||||
while(NOT ${done})
|
|
||||||
get_filename_component(snamewe "${s}" NAME_WE)
|
|
||||||
get_filename_component(sname "${s}" NAME)
|
|
||||||
get_filename_component(sdir "${s}" PATH)
|
|
||||||
set(s "${sdir}")
|
|
||||||
if(sname MATCHES "\\.app$")
|
|
||||||
set(done 1)
|
|
||||||
set(dotapp_dir "${sdir}/${sname}")
|
|
||||||
endif()
|
|
||||||
endwhile()
|
|
||||||
else()
|
|
||||||
# Otherwise use a directory containing the exe
|
|
||||||
# (typical of a non-bundle executable on Mac, Windows or Linux)
|
|
||||||
#
|
|
||||||
is_file_executable("${s}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
get_filename_component(sdir "${s}" PATH)
|
|
||||||
set(dotapp_dir "${sdir}")
|
|
||||||
else()
|
|
||||||
set(dotapp_dir "${s}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
set(${dotapp_dir_var} "${dotapp_dir}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_and_executable app bundle_var executable_var valid_var)
|
|
||||||
set(valid 0)
|
|
||||||
|
|
||||||
if(EXISTS "${app}")
|
|
||||||
# Is it a directory ending in .app?
|
|
||||||
if(IS_DIRECTORY "${app}")
|
|
||||||
if(app MATCHES "\\.app$")
|
|
||||||
get_bundle_main_executable("${app}" executable)
|
|
||||||
if(EXISTS "${app}" AND EXISTS "${executable}")
|
|
||||||
set(${bundle_var} "${app}" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "${executable}" PARENT_SCOPE)
|
|
||||||
set(valid 1)
|
|
||||||
#message(STATUS "info: handled .app directory case...")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - .app directory case...")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - directory but not .app case...")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# Is it an executable file?
|
|
||||||
is_file_executable("${app}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
get_dotapp_dir("${app}" dotapp_dir)
|
|
||||||
if(EXISTS "${dotapp_dir}")
|
|
||||||
set(${bundle_var} "${dotapp_dir}" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "${app}" PARENT_SCOPE)
|
|
||||||
set(valid 1)
|
|
||||||
#message(STATUS "info: handled executable file in .app dir case...")
|
|
||||||
else()
|
|
||||||
get_filename_component(app_dir "${app}" PATH)
|
|
||||||
set(${bundle_var} "${app_dir}" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "${app}" PARENT_SCOPE)
|
|
||||||
set(valid 1)
|
|
||||||
#message(STATUS "info: handled executable file in any dir case...")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - not .app dir, not executable file...")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - directory/file ${app} does not exist...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT valid)
|
|
||||||
set(${bundle_var} "error: not a bundle" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "error: not a bundle" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${valid_var} ${valid} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_all_executables bundle exes_var)
|
|
||||||
set(exes "")
|
|
||||||
|
|
||||||
file(GLOB_RECURSE file_list "${bundle}/*")
|
|
||||||
foreach(f ${file_list})
|
|
||||||
is_file_executable("${f}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
set(exes ${exes} "${f}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(${exes_var} "${exes}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_item_key item key_var)
|
|
||||||
get_filename_component(item_name "${item}" NAME)
|
|
||||||
if(WIN32)
|
|
||||||
string(TOLOWER "${item_name}" item_name)
|
|
||||||
endif()
|
|
||||||
string(REGEX REPLACE "\\." "_" ${key_var} "${item_name}")
|
|
||||||
set(${key_var} ${${key_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(clear_bundle_keys keys_var)
|
|
||||||
foreach(key ${${keys_var}})
|
|
||||||
set(${key}_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_DEFAULT_EMBEDDED_PATH PARENT_SCOPE)
|
|
||||||
set(${key}_EMBEDDED_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_COPYFLAG PARENT_SCOPE)
|
|
||||||
endforeach()
|
|
||||||
set(${keys_var} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(set_bundle_key_values keys_var context item exepath dirs copyflag)
|
|
||||||
get_filename_component(item_name "${item}" NAME)
|
|
||||||
|
|
||||||
get_item_key("${item}" key)
|
|
||||||
|
|
||||||
list(LENGTH ${keys_var} length_before)
|
|
||||||
gp_append_unique(${keys_var} "${key}")
|
|
||||||
list(LENGTH ${keys_var} length_after)
|
|
||||||
|
|
||||||
if(NOT length_before EQUAL length_after)
|
|
||||||
gp_resolve_item("${context}" "${item}" "${exepath}" "${dirs}" resolved_item)
|
|
||||||
|
|
||||||
gp_item_default_embedded_path("${item}" default_embedded_path)
|
|
||||||
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
# For frameworks, construct the name under the embedded path from the
|
|
||||||
# opening "${item_name}.framework/" to the closing "/${item_name}":
|
|
||||||
#
|
|
||||||
string(REGEX REPLACE "^.*(${item_name}.framework/.*/?${item_name}).*$" "${default_embedded_path}/\\1" embedded_item "${item}")
|
|
||||||
else()
|
|
||||||
# For other items, just use the same name as the original, but in the
|
|
||||||
# embedded path:
|
|
||||||
#
|
|
||||||
set(embedded_item "${default_embedded_path}/${item_name}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Replace @executable_path and resolve ".." references:
|
|
||||||
#
|
|
||||||
string(REPLACE "@executable_path" "${exepath}" resolved_embedded_item "${embedded_item}")
|
|
||||||
get_filename_component(resolved_embedded_item "${resolved_embedded_item}" ABSOLUTE)
|
|
||||||
|
|
||||||
# *But* -- if we are not copying, then force resolved_embedded_item to be
|
|
||||||
# the same as resolved_item. In the case of multiple executables in the
|
|
||||||
# original bundle, using the default_embedded_path results in looking for
|
|
||||||
# the resolved executable next to the main bundle executable. This is here
|
|
||||||
# so that exes in the other sibling directories (like "bin") get fixed up
|
|
||||||
# properly...
|
|
||||||
#
|
|
||||||
if(NOT copyflag)
|
|
||||||
set(resolved_embedded_item "${resolved_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${keys_var} ${${keys_var}} PARENT_SCOPE)
|
|
||||||
set(${key}_ITEM "${item}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_ITEM "${resolved_item}" PARENT_SCOPE)
|
|
||||||
set(${key}_DEFAULT_EMBEDDED_PATH "${default_embedded_path}" PARENT_SCOPE)
|
|
||||||
set(${key}_EMBEDDED_ITEM "${embedded_item}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_EMBEDDED_ITEM "${resolved_embedded_item}" PARENT_SCOPE)
|
|
||||||
set(${key}_COPYFLAG "${copyflag}" PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
#message("warning: item key '${key}' already in the list, subsequent references assumed identical to first")
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_keys app libs dirs keys_var)
|
|
||||||
set(${keys_var} PARENT_SCOPE)
|
|
||||||
|
|
||||||
get_bundle_and_executable("${app}" bundle executable valid)
|
|
||||||
if(valid)
|
|
||||||
# Always use the exepath of the main bundle executable for @executable_path
|
|
||||||
# replacements:
|
|
||||||
#
|
|
||||||
get_filename_component(exepath "${executable}" PATH)
|
|
||||||
|
|
||||||
# But do fixups on all executables in the bundle:
|
|
||||||
#
|
|
||||||
get_bundle_all_executables("${bundle}" exes)
|
|
||||||
|
|
||||||
# For each extra lib, accumulate a key as well and then also accumulate
|
|
||||||
# any of its prerequisites. (Extra libs are typically dynamically loaded
|
|
||||||
# plugins: libraries that are prerequisites for full runtime functionality
|
|
||||||
# but that do not show up in otool -L output...)
|
|
||||||
#
|
|
||||||
foreach(lib ${libs})
|
|
||||||
set_bundle_key_values(${keys_var} "${lib}" "${lib}" "${exepath}" "${dirs}" 0)
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${lib}" prereqs 1 1 "${exepath}" "${dirs}")
|
|
||||||
foreach(pr ${prereqs})
|
|
||||||
set_bundle_key_values(${keys_var} "${lib}" "${pr}" "${exepath}" "${dirs}" 1)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# For each executable found in the bundle, accumulate keys as we go.
|
|
||||||
# The list of keys should be complete when all prerequisites of all
|
|
||||||
# binaries in the bundle have been analyzed.
|
|
||||||
#
|
|
||||||
foreach(exe ${exes})
|
|
||||||
# Add the exe itself to the keys:
|
|
||||||
#
|
|
||||||
set_bundle_key_values(${keys_var} "${exe}" "${exe}" "${exepath}" "${dirs}" 0)
|
|
||||||
|
|
||||||
# Add each prerequisite to the keys:
|
|
||||||
#
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${exe}" prereqs 1 1 "${exepath}" "${dirs}")
|
|
||||||
foreach(pr ${prereqs})
|
|
||||||
set_bundle_key_values(${keys_var} "${exe}" "${pr}" "${exepath}" "${dirs}" 1)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Propagate values to caller's scope:
|
|
||||||
#
|
|
||||||
set(${keys_var} ${${keys_var}} PARENT_SCOPE)
|
|
||||||
foreach(key ${${keys_var}})
|
|
||||||
set(${key}_ITEM "${${key}_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_ITEM "${${key}_RESOLVED_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_DEFAULT_EMBEDDED_PATH "${${key}_DEFAULT_EMBEDDED_PATH}" PARENT_SCOPE)
|
|
||||||
set(${key}_EMBEDDED_ITEM "${${key}_EMBEDDED_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_EMBEDDED_ITEM "${${key}_RESOLVED_EMBEDDED_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_COPYFLAG "${${key}_COPYFLAG}" PARENT_SCOPE)
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item)
|
|
||||||
if(WIN32)
|
|
||||||
# ignore case on Windows
|
|
||||||
string(TOLOWER "${resolved_item}" resolved_item_compare)
|
|
||||||
string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
|
|
||||||
else()
|
|
||||||
set(resolved_item_compare "${resolved_item}")
|
|
||||||
set(resolved_embedded_item_compare "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
|
|
||||||
message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
|
|
||||||
else()
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
file(RPATH_REMOVE FILE "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(copy_resolved_framework_into_bundle resolved_item resolved_embedded_item)
|
|
||||||
if(WIN32)
|
|
||||||
# ignore case on Windows
|
|
||||||
string(TOLOWER "${resolved_item}" resolved_item_compare)
|
|
||||||
string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
|
|
||||||
else()
|
|
||||||
set(resolved_item_compare "${resolved_item}")
|
|
||||||
set(resolved_embedded_item_compare "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
|
|
||||||
message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
|
|
||||||
else()
|
|
||||||
if(BU_COPY_FULL_FRAMEWORK_CONTENTS)
|
|
||||||
# Full Framework (everything):
|
|
||||||
get_filename_component(resolved_dir "${resolved_item}" PATH)
|
|
||||||
get_filename_component(resolved_dir "${resolved_dir}/../.." ABSOLUTE)
|
|
||||||
get_filename_component(resolved_embedded_dir "${resolved_embedded_item}" PATH)
|
|
||||||
get_filename_component(resolved_embedded_dir "${resolved_embedded_dir}/../.." ABSOLUTE)
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_dir}' '${resolved_embedded_dir}'")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_dir}" "${resolved_embedded_dir}")
|
|
||||||
else()
|
|
||||||
# Framework lib itself:
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
|
|
||||||
|
|
||||||
# Plus Resources, if they exist:
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+/[^/]+/[^/]+$" "\\1/Resources" resolved_resources "${resolved_item}")
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+/[^/]+/[^/]+$" "\\1/Resources" resolved_embedded_resources "${resolved_embedded_item}")
|
|
||||||
if(EXISTS "${resolved_resources}")
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_resources}' '${resolved_embedded_resources}'")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_resources}" "${resolved_embedded_resources}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
file(RPATH_REMOVE FILE "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(fixup_bundle_item resolved_embedded_item exepath dirs)
|
|
||||||
# This item's key is "ikey":
|
|
||||||
#
|
|
||||||
get_item_key("${resolved_embedded_item}" ikey)
|
|
||||||
|
|
||||||
# Ensure the item is "inside the .app bundle" -- it should not be fixed up if
|
|
||||||
# it is not in the .app bundle... Otherwise, we'll modify files in the build
|
|
||||||
# tree, or in other varied locations around the file system, with our call to
|
|
||||||
# install_name_tool. Make sure that doesn't happen here:
|
|
||||||
#
|
|
||||||
get_dotapp_dir("${exepath}" exe_dotapp_dir)
|
|
||||||
string(LENGTH "${exe_dotapp_dir}/" exe_dotapp_dir_length)
|
|
||||||
string(LENGTH "${resolved_embedded_item}" resolved_embedded_item_length)
|
|
||||||
set(path_too_short 0)
|
|
||||||
set(is_embedded 0)
|
|
||||||
if(${resolved_embedded_item_length} LESS ${exe_dotapp_dir_length})
|
|
||||||
set(path_too_short 1)
|
|
||||||
endif()
|
|
||||||
if(NOT path_too_short)
|
|
||||||
string(SUBSTRING "${resolved_embedded_item}" 0 ${exe_dotapp_dir_length} item_substring)
|
|
||||||
if("${exe_dotapp_dir}/" STREQUAL "${item_substring}")
|
|
||||||
set(is_embedded 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT is_embedded)
|
|
||||||
message(" exe_dotapp_dir/='${exe_dotapp_dir}/'")
|
|
||||||
message(" item_substring='${item_substring}'")
|
|
||||||
message(" resolved_embedded_item='${resolved_embedded_item}'")
|
|
||||||
message("")
|
|
||||||
message("Install or copy the item into the bundle before calling fixup_bundle.")
|
|
||||||
message("Or maybe there's a typo or incorrect path in one of the args to fixup_bundle?")
|
|
||||||
message("")
|
|
||||||
message(FATAL_ERROR "cannot fixup an item that is not in the bundle...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${resolved_embedded_item}" prereqs 1 0 "${exepath}" "${dirs}")
|
|
||||||
|
|
||||||
set(changes "")
|
|
||||||
|
|
||||||
foreach(pr ${prereqs})
|
|
||||||
# Each referenced item's key is "rkey" in the loop:
|
|
||||||
#
|
|
||||||
get_item_key("${pr}" rkey)
|
|
||||||
|
|
||||||
if(NOT "${${rkey}_EMBEDDED_ITEM}" STREQUAL "")
|
|
||||||
set(changes ${changes} "-change" "${pr}" "${${rkey}_EMBEDDED_ITEM}")
|
|
||||||
else()
|
|
||||||
message("warning: unexpected reference to '${pr}'")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(BU_CHMOD_BUNDLE_ITEMS)
|
|
||||||
execute_process(COMMAND chmod u+w "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Change this item's id and all of its references in one call
|
|
||||||
# to install_name_tool:
|
|
||||||
#
|
|
||||||
execute_process(COMMAND install_name_tool
|
|
||||||
${changes} -id "${${ikey}_EMBEDDED_ITEM}" "${resolved_embedded_item}"
|
|
||||||
)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(fixup_bundle app libs dirs)
|
|
||||||
message(STATUS "fixup_bundle")
|
|
||||||
message(STATUS " app='${app}'")
|
|
||||||
message(STATUS " libs='${libs}'")
|
|
||||||
message(STATUS " dirs='${dirs}'")
|
|
||||||
|
|
||||||
get_bundle_and_executable("${app}" bundle executable valid)
|
|
||||||
if(valid)
|
|
||||||
get_filename_component(exepath "${executable}" PATH)
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: preparing...")
|
|
||||||
get_bundle_keys("${app}" "${libs}" "${dirs}" keys)
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: copying...")
|
|
||||||
list(LENGTH keys n)
|
|
||||||
math(EXPR n ${n}*2)
|
|
||||||
|
|
||||||
set(i 0)
|
|
||||||
foreach(key ${keys})
|
|
||||||
math(EXPR i ${i}+1)
|
|
||||||
if(${${key}_COPYFLAG})
|
|
||||||
message(STATUS "${i}/${n}: copying '${${key}_RESOLVED_ITEM}'")
|
|
||||||
else()
|
|
||||||
message(STATUS "${i}/${n}: *NOT* copying '${${key}_RESOLVED_ITEM}'")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(show_status 0)
|
|
||||||
if(show_status)
|
|
||||||
message(STATUS "key='${key}'")
|
|
||||||
message(STATUS "item='${${key}_ITEM}'")
|
|
||||||
message(STATUS "resolved_item='${${key}_RESOLVED_ITEM}'")
|
|
||||||
message(STATUS "default_embedded_path='${${key}_DEFAULT_EMBEDDED_PATH}'")
|
|
||||||
message(STATUS "embedded_item='${${key}_EMBEDDED_ITEM}'")
|
|
||||||
message(STATUS "resolved_embedded_item='${${key}_RESOLVED_EMBEDDED_ITEM}'")
|
|
||||||
message(STATUS "copyflag='${${key}_COPYFLAG}'")
|
|
||||||
message(STATUS "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${${key}_COPYFLAG})
|
|
||||||
set(item "${${key}_ITEM}")
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
copy_resolved_framework_into_bundle("${${key}_RESOLVED_ITEM}"
|
|
||||||
"${${key}_RESOLVED_EMBEDDED_ITEM}")
|
|
||||||
else()
|
|
||||||
copy_resolved_item_into_bundle("${${key}_RESOLVED_ITEM}"
|
|
||||||
"${${key}_RESOLVED_EMBEDDED_ITEM}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: fixing...")
|
|
||||||
foreach(key ${keys})
|
|
||||||
math(EXPR i ${i}+1)
|
|
||||||
if(APPLE)
|
|
||||||
message(STATUS "${i}/${n}: fixing up '${${key}_RESOLVED_EMBEDDED_ITEM}'")
|
|
||||||
fixup_bundle_item("${${key}_RESOLVED_EMBEDDED_ITEM}" "${exepath}" "${dirs}")
|
|
||||||
else()
|
|
||||||
message(STATUS "${i}/${n}: fix-up not required on this platform '${${key}_RESOLVED_EMBEDDED_ITEM}'")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: cleaning up...")
|
|
||||||
clear_bundle_keys(keys)
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: verifying...")
|
|
||||||
verify_app("${app}")
|
|
||||||
else()
|
|
||||||
message(SEND_ERROR "error: fixup_bundle: not a valid bundle")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: done")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(copy_and_fixup_bundle src dst libs dirs)
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${src}" "${dst}")
|
|
||||||
fixup_bundle("${dst}" "${libs}" "${dirs}")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(verify_bundle_prerequisites bundle result_var info_var)
|
|
||||||
set(result 1)
|
|
||||||
set(info "")
|
|
||||||
set(count 0)
|
|
||||||
|
|
||||||
get_bundle_main_executable("${bundle}" main_bundle_exe)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE file_list "${bundle}/*")
|
|
||||||
foreach(f ${file_list})
|
|
||||||
is_file_executable("${f}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
get_filename_component(exepath "${f}" PATH)
|
|
||||||
math(EXPR count "${count} + 1")
|
|
||||||
|
|
||||||
message(STATUS "executable file ${count}: ${f}")
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${f}" prereqs 1 1 "${exepath}" "")
|
|
||||||
|
|
||||||
# On the Mac,
|
|
||||||
# "embedded" and "system" prerequisites are fine... anything else means
|
|
||||||
# the bundle's prerequisites are not verified (i.e., the bundle is not
|
|
||||||
# really "standalone")
|
|
||||||
#
|
|
||||||
# On Windows (and others? Linux/Unix/...?)
|
|
||||||
# "local" and "system" prereqs are fine...
|
|
||||||
#
|
|
||||||
set(external_prereqs "")
|
|
||||||
|
|
||||||
foreach(p ${prereqs})
|
|
||||||
set(p_type "")
|
|
||||||
gp_file_type("${f}" "${p}" p_type)
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
if(NOT "${p_type}" STREQUAL "embedded" AND NOT "${p_type}" STREQUAL "system")
|
|
||||||
set(external_prereqs ${external_prereqs} "${p}")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if(NOT "${p_type}" STREQUAL "local" AND NOT "${p_type}" STREQUAL "system")
|
|
||||||
set(external_prereqs ${external_prereqs} "${p}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(external_prereqs)
|
|
||||||
# Found non-system/somehow-unacceptable prerequisites:
|
|
||||||
set(result 0)
|
|
||||||
set(info ${info} "external prerequisites found:\nf='${f}'\nexternal_prereqs='${external_prereqs}'\n")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(result)
|
|
||||||
set(info "Verified ${count} executable files in '${bundle}'")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
|
||||||
set(${info_var} "${info}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(verify_bundle_symlinks bundle result_var info_var)
|
|
||||||
set(result 1)
|
|
||||||
set(info "")
|
|
||||||
set(count 0)
|
|
||||||
|
|
||||||
# TODO: implement this function for real...
|
|
||||||
# Right now, it is just a stub that verifies unconditionally...
|
|
||||||
|
|
||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
|
||||||
set(${info_var} "${info}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(verify_app app)
|
|
||||||
set(verified 0)
|
|
||||||
set(info "")
|
|
||||||
|
|
||||||
get_bundle_and_executable("${app}" bundle executable valid)
|
|
||||||
|
|
||||||
message(STATUS "===========================================================================")
|
|
||||||
message(STATUS "Analyzing app='${app}'")
|
|
||||||
message(STATUS "bundle='${bundle}'")
|
|
||||||
message(STATUS "executable='${executable}'")
|
|
||||||
message(STATUS "valid='${valid}'")
|
|
||||||
|
|
||||||
# Verify that the bundle does not have any "external" prerequisites:
|
|
||||||
#
|
|
||||||
verify_bundle_prerequisites("${bundle}" verified info)
|
|
||||||
message(STATUS "verified='${verified}'")
|
|
||||||
message(STATUS "info='${info}'")
|
|
||||||
message(STATUS "")
|
|
||||||
|
|
||||||
if(verified)
|
|
||||||
# Verify that the bundle does not have any symlinks to external files:
|
|
||||||
#
|
|
||||||
verify_bundle_symlinks("${bundle}" verified info)
|
|
||||||
message(STATUS "verified='${verified}'")
|
|
||||||
message(STATUS "info='${info}'")
|
|
||||||
message(STATUS "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT verified)
|
|
||||||
message(FATAL_ERROR "error: verify_app failed")
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
155
cmake/CompilerWarnings.cmake
Normal file
155
cmake/CompilerWarnings.cmake
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#
|
||||||
|
# Function to set compiler warnings with reasonable defaults at the project level.
|
||||||
|
# Taken from https://github.com/aminya/project_options/blob/main/src/CompilerWarnings.cmake
|
||||||
|
# under the folowing license:
|
||||||
|
#
|
||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022-2100 Amin Yahyaabadi
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
include_guard()
|
||||||
|
|
||||||
|
function(_set_project_warnings_add_target_link_option TARGET OPTIONS)
|
||||||
|
target_link_options(${_project_name} INTERFACE ${OPTIONS})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Set the compiler warnings
|
||||||
|
#
|
||||||
|
# https://clang.llvm.org/docs/DiagnosticsReference.html
|
||||||
|
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
|
||||||
|
function(
|
||||||
|
set_project_warnings
|
||||||
|
_project_name
|
||||||
|
MSVC_WARNINGS
|
||||||
|
CLANG_WARNINGS
|
||||||
|
GCC_WARNINGS
|
||||||
|
)
|
||||||
|
if("${MSVC_WARNINGS}" STREQUAL "")
|
||||||
|
set(MSVC_WARNINGS
|
||||||
|
/W4 # Baseline reasonable warnings
|
||||||
|
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
|
||||||
|
/w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||||
|
/w14263 # 'function': member function does not override any base class virtual member function
|
||||||
|
/w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not
|
||||||
|
# be destructed correctly
|
||||||
|
/w14287 # 'operator': unsigned/negative constant mismatch
|
||||||
|
/we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside
|
||||||
|
# the for-loop scope
|
||||||
|
/w14296 # 'operator': expression is always 'boolean_value'
|
||||||
|
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
|
||||||
|
/w14545 # expression before comma evaluates to a function which is missing an argument list
|
||||||
|
/w14546 # function call before comma missing argument list
|
||||||
|
/w14547 # 'operator': operator before comma has no effect; expected operator with side-effect
|
||||||
|
/w14549 # 'operator': operator before comma has no effect; did you intend 'operator'?
|
||||||
|
/w14555 # expression has no effect; expected expression with side- effect
|
||||||
|
/w14619 # pragma warning: there is no warning number 'number'
|
||||||
|
/w14640 # Enable warning on thread un-safe static member initialization
|
||||||
|
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
|
||||||
|
/w14905 # wide string literal cast to 'LPSTR'
|
||||||
|
/w14906 # string literal cast to 'LPWSTR'
|
||||||
|
/w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied
|
||||||
|
/permissive- # standards conformance mode for MSVC compiler.
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${CLANG_WARNINGS}" STREQUAL "")
|
||||||
|
set(CLANG_WARNINGS
|
||||||
|
-Wall
|
||||||
|
-Wextra # reasonable and standard
|
||||||
|
-Wshadow # warn the user if a variable declaration shadows one from a parent context
|
||||||
|
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
|
||||||
|
# catch hard to track down memory errors
|
||||||
|
-Wold-style-cast # warn for c-style casts
|
||||||
|
-Wcast-align # warn for potential performance problem casts
|
||||||
|
-Wunused # warn on anything being unused
|
||||||
|
-Woverloaded-virtual # warn if you overload (not override) a virtual function
|
||||||
|
-Wpedantic # warn if non-standard C++ is used
|
||||||
|
-Wconversion # warn on type conversions that may lose data
|
||||||
|
-Wsign-conversion # warn on sign conversions
|
||||||
|
-Wnull-dereference # warn if a null dereference is detected
|
||||||
|
-Wdouble-promotion # warn if float is implicit promoted to double
|
||||||
|
-Wformat=2 # warn on security issues around functions that format output (ie printf)
|
||||||
|
-Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation
|
||||||
|
# -Wgnu-zero-variadic-macro-arguments (part of -pedantic) is triggered by every qCDebug() call and therefore results
|
||||||
|
# in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour
|
||||||
|
# instead of the exact standard wording so we can safely ignore it
|
||||||
|
-Wno-gnu-zero-variadic-macro-arguments
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${GCC_WARNINGS}" STREQUAL "")
|
||||||
|
set(GCC_WARNINGS
|
||||||
|
${CLANG_WARNINGS}
|
||||||
|
-Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
|
||||||
|
-Wduplicated-cond # warn if if / else chain has duplicated conditions
|
||||||
|
-Wduplicated-branches # warn if if / else branches have duplicated code
|
||||||
|
-Wlogical-op # warn about logical operations being used where bitwise were probably wanted
|
||||||
|
-Wuseless-cast # warn if you perform a cast to the same type
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
set(PROJECT_WARNINGS_CXX ${MSVC_WARNINGS})
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||||
|
set(PROJECT_WARNINGS_CXX ${CLANG_WARNINGS})
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
set(PROJECT_WARNINGS_CXX ${GCC_WARNINGS})
|
||||||
|
else()
|
||||||
|
message(AUTHOR_WARNING "No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
|
||||||
|
# TODO support Intel compiler
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add C warnings
|
||||||
|
set(PROJECT_WARNINGS_C "${PROJECT_WARNINGS_CXX}")
|
||||||
|
list(
|
||||||
|
REMOVE_ITEM
|
||||||
|
PROJECT_WARNINGS_C
|
||||||
|
-Wnon-virtual-dtor
|
||||||
|
-Wold-style-cast
|
||||||
|
-Woverloaded-virtual
|
||||||
|
-Wuseless-cast
|
||||||
|
-Wextra-semi
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(
|
||||||
|
${_project_name}
|
||||||
|
INTERFACE # C++ warnings
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>
|
||||||
|
# C warnings
|
||||||
|
$<$<COMPILE_LANGUAGE:C>:${PROJECT_WARNINGS_C}>
|
||||||
|
)
|
||||||
|
|
||||||
|
# If we are using the compiler as a linker driver pass the warnings to it
|
||||||
|
# (most useful when using LTO or warnings as errors)
|
||||||
|
if(CMAKE_CXX_LINK_EXECUTABLE MATCHES "^<CMAKE_CXX_COMPILER>")
|
||||||
|
_set_project_warnings_add_target_link_option(
|
||||||
|
${_project_name} "$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_C_LINK_EXECUTABLE MATCHES "^<CMAKE_C_COMPILER>")
|
||||||
|
_set_project_warnings_add_target_link_option(
|
||||||
|
${_project_name} "$<$<COMPILE_LANGUAGE:C>:${PROJECT_WARNINGS_C}>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
100
cmake/ECMQueryQt.cmake
Normal file
100
cmake/ECMQueryQt.cmake
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 Rohan Garg <rohan16garg@gmail.com>
|
||||||
|
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2014-2016 Aleix Pol <aleixpol@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2022 Ahmad Samir <a.samir78@gmail.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
ECMQueryQt
|
||||||
|
---------------
|
||||||
|
This module can be used to query the installation paths used by Qt.
|
||||||
|
|
||||||
|
For Qt5 this uses ``qmake``, and for Qt6 this used ``qtpaths`` (the latter has built-in
|
||||||
|
support to query the paths of a target platform when cross-compiling).
|
||||||
|
|
||||||
|
This module defines the following function:
|
||||||
|
::
|
||||||
|
|
||||||
|
ecm_query_qt(<result_variable> <qt_variable> [TRY])
|
||||||
|
|
||||||
|
Passing ``TRY`` will result in the method not making the build fail if the executable
|
||||||
|
used for querying has not been found, but instead simply print a warning message and
|
||||||
|
return an empty string.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
include(ECMQueryQt)
|
||||||
|
ecm_query_qt(bin_dir QT_INSTALL_BINS)
|
||||||
|
|
||||||
|
If the call succeeds ``${bin_dir}`` will be set to ``<prefix>/path/to/bin/dir`` (e.g.
|
||||||
|
``/usr/lib64/qt/bin/``).
|
||||||
|
|
||||||
|
Since: 5.93
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/QtVersionOption.cmake)
|
||||||
|
include(CheckLanguage)
|
||||||
|
check_language(CXX)
|
||||||
|
if (CMAKE_CXX_COMPILER)
|
||||||
|
# Enable the CXX language to let CMake look for config files in library dirs.
|
||||||
|
# See: https://gitlab.kitware.com/cmake/cmake/-/issues/23266
|
||||||
|
enable_language(CXX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||||
|
# QUIET to accommodate the TRY option
|
||||||
|
find_package(Qt${QT_MAJOR_VERSION}Core QUIET)
|
||||||
|
if(TARGET Qt5::qmake)
|
||||||
|
get_target_property(_qmake_executable_default Qt5::qmake LOCATION)
|
||||||
|
|
||||||
|
set(QUERY_EXECUTABLE ${_qmake_executable_default}
|
||||||
|
CACHE FILEPATH "Location of the Qt5 qmake executable")
|
||||||
|
set(_exec_name_text "Qt5 qmake")
|
||||||
|
set(_cli_option "-query")
|
||||||
|
endif()
|
||||||
|
elseif(QT_MAJOR_VERSION STREQUAL "6")
|
||||||
|
# QUIET to accommodate the TRY option
|
||||||
|
find_package(Qt6 COMPONENTS CoreTools QUIET CONFIG)
|
||||||
|
if (TARGET Qt6::qtpaths)
|
||||||
|
get_target_property(_qtpaths_executable Qt6::qtpaths LOCATION)
|
||||||
|
|
||||||
|
set(QUERY_EXECUTABLE ${_qtpaths_executable}
|
||||||
|
CACHE FILEPATH "Location of the Qt6 qtpaths executable")
|
||||||
|
set(_exec_name_text "Qt6 qtpaths")
|
||||||
|
set(_cli_option "--query")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(ecm_query_qt result_variable qt_variable)
|
||||||
|
set(options TRY)
|
||||||
|
set(oneValueArgs)
|
||||||
|
set(multiValueArgs)
|
||||||
|
|
||||||
|
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT QUERY_EXECUTABLE)
|
||||||
|
if(ARGS_TRY)
|
||||||
|
set(${result_variable} "" PARENT_SCOPE)
|
||||||
|
message(STATUS "No ${_exec_name_text} executable found. Can't check ${qt_variable}")
|
||||||
|
return()
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "No ${_exec_name_text} executable found. Can't check ${qt_variable} as required")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${QUERY_EXECUTABLE} ${_cli_option} "${qt_variable}"
|
||||||
|
RESULT_VARIABLE return_code
|
||||||
|
OUTPUT_VARIABLE output
|
||||||
|
)
|
||||||
|
if(return_code EQUAL 0)
|
||||||
|
string(STRIP "${output}" output)
|
||||||
|
file(TO_CMAKE_PATH "${output}" output_path)
|
||||||
|
set(${result_variable} "${output_path}" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
message(WARNING "Failed call: ${_command} \"${qt_variable}\"")
|
||||||
|
message(FATAL_ERROR "${_exec_name_text} call failed: ${return_code}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
@ -3,7 +3,7 @@
|
|||||||
# These functions force a re-configure on each git commit so that you can
|
# These functions force a re-configure on each git commit so that you can
|
||||||
# trust the values of the variables in your build system.
|
# trust the values of the variables in your build system.
|
||||||
#
|
#
|
||||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
|
||||||
#
|
#
|
||||||
# Returns the refspec and sha hash of the current head revision
|
# Returns the refspec and sha hash of the current head revision
|
||||||
#
|
#
|
||||||
@ -12,20 +12,33 @@
|
|||||||
# Returns the results of git describe on the source tree, and adjusting
|
# Returns the results of git describe on the source tree, and adjusting
|
||||||
# the output so that it tests false if an error occurs.
|
# the output so that it tests false if an error occurs.
|
||||||
#
|
#
|
||||||
|
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the working tree (--dirty option),
|
||||||
|
# and adjusting the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||||
#
|
#
|
||||||
# Returns the results of git describe --exact-match on the source tree,
|
# Returns the results of git describe --exact-match on the source tree,
|
||||||
# and adjusting the output so that it tests false if there was no exact
|
# and adjusting the output so that it tests false if there was no exact
|
||||||
# matching tag.
|
# matching tag.
|
||||||
#
|
#
|
||||||
|
# git_local_changes(<var>)
|
||||||
|
#
|
||||||
|
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||||
|
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||||
|
# Does not regard untracked files.
|
||||||
|
#
|
||||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
#
|
#
|
||||||
# Original Author:
|
# Original Author:
|
||||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||||
# http://academic.cleardefinition.com
|
# http://academic.cleardefinition.com
|
||||||
# Iowa State University HCI Graduate Program/VRAC
|
|
||||||
#
|
#
|
||||||
# Copyright Iowa State University 2009-2010.
|
# Copyright 2009-2013, Iowa State University.
|
||||||
|
# Copyright 2013-2020, Ryan Pavlik
|
||||||
|
# Copyright 2013-2020, Contributors
|
||||||
|
# SPDX-License-Identifier: BSL-1.0
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
# http://www.boost.org/LICENSE_1_0.txt)
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@ -39,45 +52,124 @@ set(__get_git_revision_description YES)
|
|||||||
# to find the path to this module rather than the path to a calling list file
|
# to find the path to this module rather than the path to a calling list file
|
||||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
function(get_git_head_revision _refspecvar _hashvar)
|
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
# that is part of any directory in the path defined by _start_dir.
|
||||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
# The result is returned in the parent scope variable whose name is passed
|
||||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
# as variable _git_dir_var. If no .git directory can be found, the
|
||||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
# function returns an empty string via _git_dir_var.
|
||||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
#
|
||||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||||
|
# neither foo nor bar contain a file/directory .git. This wil return
|
||||||
|
# C:/bla/.git
|
||||||
|
#
|
||||||
|
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||||
|
set(cur_dir "${_start_dir}")
|
||||||
|
set(git_dir "${_start_dir}/.git")
|
||||||
|
while(NOT EXISTS "${git_dir}")
|
||||||
|
# .git dir not found, search parent directories
|
||||||
|
set(git_previous_parent "${cur_dir}")
|
||||||
|
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||||
|
if(cur_dir STREQUAL git_previous_parent)
|
||||||
# We have reached the root directory, we are not in git
|
# We have reached the root directory, we are not in git
|
||||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
set(${_git_dir_var}
|
||||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
""
|
||||||
|
PARENT_SCOPE)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
set(git_dir "${cur_dir}/.git")
|
||||||
endwhile()
|
endwhile()
|
||||||
# check if this is a submodule
|
set(${_git_dir_var}
|
||||||
|
"${git_dir}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(get_git_head_revision _refspecvar _hashvar)
|
||||||
|
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||||
|
|
||||||
|
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||||
|
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
|
||||||
|
else()
|
||||||
|
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
|
||||||
|
endif()
|
||||||
|
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||||
|
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||||
|
"${GIT_DIR}")
|
||||||
|
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||||||
|
# We've gone above the CMake root dir.
|
||||||
|
set(GIT_DIR "")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if("${GIT_DIR}" STREQUAL "")
|
||||||
|
set(${_refspecvar}
|
||||||
|
"GITDIR-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
set(${_hashvar}
|
||||||
|
"GITDIR-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if the current source dir is a git submodule or a worktree.
|
||||||
|
# In both cases .git is a file instead of a directory.
|
||||||
|
#
|
||||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||||
file(READ ${GIT_DIR} submodule)
|
# The following git command will return a non empty string that
|
||||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
# points to the super project working tree if the current
|
||||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
# source dir is inside a git submodule.
|
||||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
# Otherwise the command will return an empty string.
|
||||||
|
#
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||||
|
--show-superproject-working-tree
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT "${out}" STREQUAL "")
|
||||||
|
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||||
|
file(READ ${GIT_DIR} submodule)
|
||||||
|
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||||
|
${submodule})
|
||||||
|
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||||
|
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||||
|
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||||
|
ABSOLUTE)
|
||||||
|
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||||
|
else()
|
||||||
|
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||||
|
file(READ ${GIT_DIR} worktree_ref)
|
||||||
|
# The .git directory contains a path to the worktree information directory
|
||||||
|
# inside the parent git repo of the worktree.
|
||||||
|
#
|
||||||
|
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||||
|
${worktree_ref})
|
||||||
|
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||||
|
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||||
|
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||||
endif()
|
endif()
|
||||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||||
if(NOT EXISTS "${GIT_DATA}")
|
if(NOT EXISTS "${GIT_DATA}")
|
||||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||||
|
|
||||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||||
"${GIT_DATA}/grabRef.cmake"
|
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||||
@ONLY)
|
|
||||||
include("${GIT_DATA}/grabRef.cmake")
|
include("${GIT_DATA}/grabRef.cmake")
|
||||||
|
|
||||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
set(${_refspecvar}
|
||||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
"${HEAD_REF}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
set(${_hashvar}
|
||||||
|
"${HEAD_HASH}"
|
||||||
|
PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(git_describe _var)
|
function(git_describe _var)
|
||||||
@ -86,45 +178,107 @@ function(git_describe _var)
|
|||||||
endif()
|
endif()
|
||||||
get_git_head_revision(refspec hash)
|
get_git_head_revision(refspec hash)
|
||||||
if(NOT GIT_FOUND)
|
if(NOT GIT_FOUND)
|
||||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
if(NOT hash)
|
if(NOT hash)
|
||||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
set(${_var}
|
||||||
|
"HEAD-HASH-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# TODO sanitize
|
# TODO sanitize
|
||||||
#if((${ARGN}" MATCHES "&&") OR
|
#if((${ARGN}" MATCHES "&&") OR
|
||||||
# (ARGN MATCHES "||") OR
|
# (ARGN MATCHES "||") OR
|
||||||
# (ARGN MATCHES "\\;"))
|
# (ARGN MATCHES "\\;"))
|
||||||
# message("Please report the following error to the project!")
|
# message("Please report the following error to the project!")
|
||||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||||
#endif()
|
#endif()
|
||||||
|
|
||||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||||
|
|
||||||
execute_process(COMMAND
|
execute_process(
|
||||||
"${GIT_EXECUTABLE}"
|
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||||
describe
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${hash}
|
RESULT_VARIABLE res
|
||||||
${ARGN}
|
OUTPUT_VARIABLE out
|
||||||
WORKING_DIRECTORY
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
RESULT_VARIABLE
|
|
||||||
res
|
|
||||||
OUTPUT_VARIABLE
|
|
||||||
out
|
|
||||||
ERROR_QUIET
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
if(NOT res EQUAL 0)
|
if(NOT res EQUAL 0)
|
||||||
set(out "${out}-${res}-NOTFOUND")
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${_var} "${out}" PARENT_SCOPE)
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe_working_tree _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(git_get_exact_tag _var)
|
function(git_get_exact_tag _var)
|
||||||
git_describe(out --exact-match ${ARGN})
|
git_describe(out --exact-match ${ARGN})
|
||||||
set(${_var} "${out}" PARENT_SCOPE)
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_local_changes _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var}
|
||||||
|
"HEAD-HASH-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(res EQUAL 0)
|
||||||
|
set(${_var}
|
||||||
|
"CLEAN"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${_var}
|
||||||
|
"DIRTY"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -8,10 +8,12 @@
|
|||||||
# http://academic.cleardefinition.com
|
# http://academic.cleardefinition.com
|
||||||
# Iowa State University HCI Graduate Program/VRAC
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
#
|
#
|
||||||
# Copyright Iowa State University 2009-2010.
|
# Copyright 2009-2012, Iowa State University
|
||||||
|
# Copyright 2011-2015, Contributors
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
# http://www.boost.org/LICENSE_1_0.txt)
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
# SPDX-License-Identifier: BSL-1.0
|
||||||
|
|
||||||
set(HEAD_HASH)
|
set(HEAD_HASH)
|
||||||
|
|
||||||
@ -19,23 +21,23 @@ file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
|||||||
|
|
||||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||||
if(HEAD_CONTENTS MATCHES "ref")
|
if(HEAD_CONTENTS MATCHES "ref")
|
||||||
# named branch
|
# named branch
|
||||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
else()
|
else()
|
||||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
# detached HEAD
|
# detached HEAD
|
||||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT HEAD_HASH)
|
if(NOT HEAD_HASH)
|
||||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,902 +0,0 @@
|
|||||||
# - Functions to analyze and list executable file prerequisites.
|
|
||||||
# This module provides functions to list the .dll, .dylib or .so
|
|
||||||
# files that an executable or shared library file depends on. (Its
|
|
||||||
# prerequisites.)
|
|
||||||
#
|
|
||||||
# It uses various tools to obtain the list of required shared library files:
|
|
||||||
# dumpbin (Windows)
|
|
||||||
# objdump (MinGW on Windows)
|
|
||||||
# ldd (Linux/Unix)
|
|
||||||
# otool (Mac OSX)
|
|
||||||
# The following functions are provided by this module:
|
|
||||||
# get_prerequisites
|
|
||||||
# list_prerequisites
|
|
||||||
# list_prerequisites_by_glob
|
|
||||||
# gp_append_unique
|
|
||||||
# is_file_executable
|
|
||||||
# gp_item_default_embedded_path
|
|
||||||
# (projects can override with gp_item_default_embedded_path_override)
|
|
||||||
# gp_resolve_item
|
|
||||||
# (projects can override with gp_resolve_item_override)
|
|
||||||
# gp_resolved_file_type
|
|
||||||
# (projects can override with gp_resolved_file_type_override)
|
|
||||||
# gp_file_type
|
|
||||||
# Requires CMake 2.6 or greater because it uses function, break, return and
|
|
||||||
# PARENT_SCOPE.
|
|
||||||
#
|
|
||||||
# GET_PREREQUISITES(<target> <prerequisites_var> <exclude_system> <recurse>
|
|
||||||
# <exepath> <dirs>)
|
|
||||||
# Get the list of shared library files required by <target>. The list in
|
|
||||||
# the variable named <prerequisites_var> should be empty on first entry to
|
|
||||||
# this function. On exit, <prerequisites_var> will contain the list of
|
|
||||||
# required shared library files.
|
|
||||||
#
|
|
||||||
# <target> is the full path to an executable file. <prerequisites_var> is the
|
|
||||||
# name of a CMake variable to contain the results. <exclude_system> must be 0
|
|
||||||
# or 1 indicating whether to include or exclude "system" prerequisites. If
|
|
||||||
# <recurse> is set to 1 all prerequisites will be found recursively, if set to
|
|
||||||
# 0 only direct prerequisites are listed. <exepath> is the path to the top
|
|
||||||
# level executable used for @executable_path replacment on the Mac. <dirs> is
|
|
||||||
# a list of paths where libraries might be found: these paths are searched
|
|
||||||
# first when a target without any path info is given. Then standard system
|
|
||||||
# locations are also searched: PATH, Framework locations, /usr/lib...
|
|
||||||
#
|
|
||||||
# LIST_PREREQUISITES(<target> [<recurse> [<exclude_system> [<verbose>]]])
|
|
||||||
# Print a message listing the prerequisites of <target>.
|
|
||||||
#
|
|
||||||
# <target> is the name of a shared library or executable target or the full
|
|
||||||
# path to a shared library or executable file. If <recurse> is set to 1 all
|
|
||||||
# prerequisites will be found recursively, if set to 0 only direct
|
|
||||||
# prerequisites are listed. <exclude_system> must be 0 or 1 indicating whether
|
|
||||||
# to include or exclude "system" prerequisites. With <verbose> set to 0 only
|
|
||||||
# the full path names of the prerequisites are printed, set to 1 extra
|
|
||||||
# informatin will be displayed.
|
|
||||||
#
|
|
||||||
# LIST_PREREQUISITES_BY_GLOB(<glob_arg> <glob_exp>)
|
|
||||||
# Print the prerequisites of shared library and executable files matching a
|
|
||||||
# globbing pattern. <glob_arg> is GLOB or GLOB_RECURSE and <glob_exp> is a
|
|
||||||
# globbing expression used with "file(GLOB" or "file(GLOB_RECURSE" to retrieve
|
|
||||||
# a list of matching files. If a matching file is executable, its prerequisites
|
|
||||||
# are listed.
|
|
||||||
#
|
|
||||||
# Any additional (optional) arguments provided are passed along as the
|
|
||||||
# optional arguments to the list_prerequisites calls.
|
|
||||||
#
|
|
||||||
# GP_APPEND_UNIQUE(<list_var> <value>)
|
|
||||||
# Append <value> to the list variable <list_var> only if the value is not
|
|
||||||
# already in the list.
|
|
||||||
#
|
|
||||||
# IS_FILE_EXECUTABLE(<file> <result_var>)
|
|
||||||
# Return 1 in <result_var> if <file> is a binary executable, 0 otherwise.
|
|
||||||
#
|
|
||||||
# GP_ITEM_DEFAULT_EMBEDDED_PATH(<item> <default_embedded_path_var>)
|
|
||||||
# Return the path that others should refer to the item by when the item
|
|
||||||
# is embedded inside a bundle.
|
|
||||||
#
|
|
||||||
# Override on a per-project basis by providing a project-specific
|
|
||||||
# gp_item_default_embedded_path_override function.
|
|
||||||
#
|
|
||||||
# GP_RESOLVE_ITEM(<context> <item> <exepath> <dirs> <resolved_item_var>)
|
|
||||||
# Resolve an item into an existing full path file.
|
|
||||||
#
|
|
||||||
# Override on a per-project basis by providing a project-specific
|
|
||||||
# gp_resolve_item_override function.
|
|
||||||
#
|
|
||||||
# GP_RESOLVED_FILE_TYPE(<original_file> <file> <exepath> <dirs> <type_var>)
|
|
||||||
# Return the type of <file> with respect to <original_file>. String
|
|
||||||
# describing type of prerequisite is returned in variable named <type_var>.
|
|
||||||
#
|
|
||||||
# Use <exepath> and <dirs> if necessary to resolve non-absolute <file>
|
|
||||||
# values -- but only for non-embedded items.
|
|
||||||
#
|
|
||||||
# Possible types are:
|
|
||||||
# system
|
|
||||||
# local
|
|
||||||
# embedded
|
|
||||||
# other
|
|
||||||
# Override on a per-project basis by providing a project-specific
|
|
||||||
# gp_resolved_file_type_override function.
|
|
||||||
#
|
|
||||||
# GP_FILE_TYPE(<original_file> <file> <type_var>)
|
|
||||||
# Return the type of <file> with respect to <original_file>. String
|
|
||||||
# describing type of prerequisite is returned in variable named <type_var>.
|
|
||||||
#
|
|
||||||
# Possible types are:
|
|
||||||
# system
|
|
||||||
# local
|
|
||||||
# embedded
|
|
||||||
# other
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2008-2009 Kitware, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
function(gp_append_unique list_var value)
|
|
||||||
set(contains 0)
|
|
||||||
|
|
||||||
foreach(item ${${list_var}})
|
|
||||||
if("${item}" STREQUAL "${value}")
|
|
||||||
set(contains 1)
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT contains)
|
|
||||||
set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(is_file_executable file result_var)
|
|
||||||
#
|
|
||||||
# A file is not executable until proven otherwise:
|
|
||||||
#
|
|
||||||
set(${result_var} 0 PARENT_SCOPE)
|
|
||||||
|
|
||||||
get_filename_component(file_full "${file}" ABSOLUTE)
|
|
||||||
string(TOLOWER "${file_full}" file_full_lower)
|
|
||||||
|
|
||||||
# If file name ends in .exe on Windows, *assume* executable:
|
|
||||||
#
|
|
||||||
if(WIN32 AND NOT UNIX)
|
|
||||||
if("${file_full_lower}" MATCHES "\\.exe$")
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# A clause could be added here that uses output or return value of dumpbin
|
|
||||||
# to determine ${result_var}. In 99%+? practical cases, the exe name
|
|
||||||
# match will be sufficient...
|
|
||||||
#
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Use the information returned from the Unix shell command "file" to
|
|
||||||
# determine if ${file_full} should be considered an executable file...
|
|
||||||
#
|
|
||||||
# If the file command's output contains "executable" and does *not* contain
|
|
||||||
# "text" then it is likely an executable suitable for prerequisite analysis
|
|
||||||
# via the get_prerequisites macro.
|
|
||||||
#
|
|
||||||
if(UNIX)
|
|
||||||
if(NOT file_cmd)
|
|
||||||
find_program(file_cmd "file")
|
|
||||||
mark_as_advanced(file_cmd)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(file_cmd)
|
|
||||||
execute_process(COMMAND "${file_cmd}" "${file_full}"
|
|
||||||
OUTPUT_VARIABLE file_ov
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
|
|
||||||
# Replace the name of the file in the output with a placeholder token
|
|
||||||
# (the string " _file_full_ ") so that just in case the path name of
|
|
||||||
# the file contains the word "text" or "executable" we are not fooled
|
|
||||||
# into thinking "the wrong thing" because the file name matches the
|
|
||||||
# other 'file' command output we are looking for...
|
|
||||||
#
|
|
||||||
string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
|
|
||||||
string(TOLOWER "${file_ov}" file_ov)
|
|
||||||
|
|
||||||
#message(STATUS "file_ov='${file_ov}'")
|
|
||||||
if("${file_ov}" MATCHES "executable")
|
|
||||||
#message(STATUS "executable!")
|
|
||||||
if("${file_ov}" MATCHES "text")
|
|
||||||
#message(STATUS "but text, so *not* a binary executable!")
|
|
||||||
else()
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Also detect position independent executables on Linux,
|
|
||||||
# where "file" gives "shared object ... (uses shared libraries)"
|
|
||||||
if("${file_ov}" MATCHES "shared object.*\(uses shared libs\)")
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# "file" version 5.22 does not print "(used shared libraries)"
|
|
||||||
# but uses "interpreter"
|
|
||||||
if("${file_ov}" MATCHES "shared object.*interpreter")
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: No 'file' command, skipping execute_process...")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_item_default_embedded_path item default_embedded_path_var)
|
|
||||||
|
|
||||||
# On Windows and Linux, "embed" prerequisites in the same directory
|
|
||||||
# as the executable by default:
|
|
||||||
#
|
|
||||||
set(path "@executable_path")
|
|
||||||
set(overridden 0)
|
|
||||||
|
|
||||||
# On the Mac, relative to the executable depending on the type
|
|
||||||
# of the thing we are embedding:
|
|
||||||
#
|
|
||||||
if(APPLE)
|
|
||||||
#
|
|
||||||
# The assumption here is that all executables in the bundle will be
|
|
||||||
# in same-level-directories inside the bundle. The parent directory
|
|
||||||
# of an executable inside the bundle should be MacOS or a sibling of
|
|
||||||
# MacOS and all embedded paths returned from here will begin with
|
|
||||||
# "@executable_path/../" and will work from all executables in all
|
|
||||||
# such same-level-directories inside the bundle.
|
|
||||||
#
|
|
||||||
|
|
||||||
# By default, embed things right next to the main bundle executable:
|
|
||||||
#
|
|
||||||
set(path "@executable_path/../../Contents/MacOS")
|
|
||||||
|
|
||||||
# Embed .dylibs right next to the main bundle executable:
|
|
||||||
#
|
|
||||||
if(item MATCHES "\\.dylib$")
|
|
||||||
set(path "@executable_path/../MacOS")
|
|
||||||
set(overridden 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
|
|
||||||
#
|
|
||||||
if(NOT overridden)
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
set(path "@executable_path/../Frameworks")
|
|
||||||
set(overridden 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Provide a hook so that projects can override the default embedded location
|
|
||||||
# of any given library by whatever logic they choose:
|
|
||||||
#
|
|
||||||
if(COMMAND gp_item_default_embedded_path_override)
|
|
||||||
gp_item_default_embedded_path_override("${item}" path)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_resolve_item context item exepath dirs resolved_item_var)
|
|
||||||
set(resolved 0)
|
|
||||||
set(resolved_item "${item}")
|
|
||||||
|
|
||||||
# Is it already resolved?
|
|
||||||
#
|
|
||||||
if(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
|
|
||||||
set(resolved 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "@executable_path")
|
|
||||||
#
|
|
||||||
# @executable_path references are assumed relative to exepath
|
|
||||||
#
|
|
||||||
string(REPLACE "@executable_path" "${exepath}" ri "${item}")
|
|
||||||
get_filename_component(ri "${ri}" ABSOLUTE)
|
|
||||||
|
|
||||||
if(EXISTS "${ri}")
|
|
||||||
#message(STATUS "info: embedded item exists (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: embedded item does not exist '${ri}'")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "@loader_path")
|
|
||||||
#
|
|
||||||
# @loader_path references are assumed relative to the
|
|
||||||
# PATH of the given "context" (presumably another library)
|
|
||||||
#
|
|
||||||
get_filename_component(contextpath "${context}" PATH)
|
|
||||||
string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
|
|
||||||
get_filename_component(ri "${ri}" ABSOLUTE)
|
|
||||||
|
|
||||||
if(EXISTS "${ri}")
|
|
||||||
#message(STATUS "info: embedded item exists (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: embedded item does not exist '${ri}'")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "@rpath")
|
|
||||||
#
|
|
||||||
# @rpath references are relative to the paths built into the binaries with -rpath
|
|
||||||
# We handle this case like we do for other Unixes
|
|
||||||
#
|
|
||||||
string(REPLACE "@rpath/" "" norpath_item "${item}")
|
|
||||||
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
find_file(ri "${norpath_item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
|
|
||||||
if(ri)
|
|
||||||
#message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
|
|
||||||
find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
|
|
||||||
if(ri)
|
|
||||||
#message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
set(fw "fw-NOTFOUND")
|
|
||||||
find_file(fw "${item}"
|
|
||||||
"~/Library/Frameworks"
|
|
||||||
"/Library/Frameworks"
|
|
||||||
"/System/Library/Frameworks"
|
|
||||||
)
|
|
||||||
if(fw)
|
|
||||||
#message(STATUS "info: 'find_file' found framework (${fw})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${fw}")
|
|
||||||
set(fw "fw-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Using find_program on Windows will find dll files that are in the PATH.
|
|
||||||
# (Converting simple file names into full path names if found.)
|
|
||||||
#
|
|
||||||
if(WIN32 AND NOT UNIX)
|
|
||||||
if(NOT resolved)
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
|
|
||||||
find_program(ri "${item}" PATHS "${exepath};${dirs}")
|
|
||||||
if(ri)
|
|
||||||
#message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Provide a hook so that projects can override item resolution
|
|
||||||
# by whatever logic they choose:
|
|
||||||
#
|
|
||||||
if(COMMAND gp_resolve_item_override)
|
|
||||||
gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
message(STATUS "
|
|
||||||
warning: cannot resolve item '${item}'
|
|
||||||
|
|
||||||
possible problems:
|
|
||||||
need more directories?
|
|
||||||
need to use InstallRequiredSystemLibraries?
|
|
||||||
run in install tree instead of build tree?
|
|
||||||
")
|
|
||||||
# message(STATUS "
|
|
||||||
#******************************************************************************
|
|
||||||
#warning: cannot resolve item '${item}'
|
|
||||||
#
|
|
||||||
# possible problems:
|
|
||||||
# need more directories?
|
|
||||||
# need to use InstallRequiredSystemLibraries?
|
|
||||||
# run in install tree instead of build tree?
|
|
||||||
#
|
|
||||||
# context='${context}'
|
|
||||||
# item='${item}'
|
|
||||||
# exepath='${exepath}'
|
|
||||||
# dirs='${dirs}'
|
|
||||||
# resolved_item_var='${resolved_item_var}'
|
|
||||||
#******************************************************************************
|
|
||||||
#")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_resolved_file_type original_file file exepath dirs type_var)
|
|
||||||
#message(STATUS "**")
|
|
||||||
|
|
||||||
if(NOT IS_ABSOLUTE "${original_file}")
|
|
||||||
message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(is_embedded 0)
|
|
||||||
set(is_local 0)
|
|
||||||
set(is_system 0)
|
|
||||||
|
|
||||||
set(resolved_file "${file}")
|
|
||||||
|
|
||||||
if("${file}" MATCHES "^@(executable|loader)_path")
|
|
||||||
set(is_embedded 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT is_embedded)
|
|
||||||
if(NOT IS_ABSOLUTE "${file}")
|
|
||||||
gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
string(TOLOWER "${original_file}" original_lower)
|
|
||||||
string(TOLOWER "${resolved_file}" lower)
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
string(TOLOWER "$ENV{SystemRoot}" sysroot)
|
|
||||||
string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
|
|
||||||
|
|
||||||
string(TOLOWER "$ENV{windir}" windir)
|
|
||||||
string(REGEX REPLACE "\\\\" "/" windir "${windir}")
|
|
||||||
|
|
||||||
if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
# if cygwin, we can get the properly formed windows paths from cygpath
|
|
||||||
find_program(CYGPATH_EXECUTABLE cygpath)
|
|
||||||
|
|
||||||
if(CYGPATH_EXECUTABLE)
|
|
||||||
execute_process(COMMAND ${CYGPATH_EXECUTABLE} -W
|
|
||||||
OUTPUT_VARIABLE env_windir
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
execute_process(COMMAND ${CYGPATH_EXECUTABLE} -S
|
|
||||||
OUTPUT_VARIABLE env_sysdir
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
string(TOLOWER "${env_windir}" windir)
|
|
||||||
string(TOLOWER "${env_sysdir}" sysroot)
|
|
||||||
|
|
||||||
if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT is_system)
|
|
||||||
get_filename_component(original_path "${original_lower}" PATH)
|
|
||||||
get_filename_component(path "${lower}" PATH)
|
|
||||||
if("${original_path}" STREQUAL "${path}")
|
|
||||||
set(is_local 1)
|
|
||||||
else()
|
|
||||||
string(LENGTH "${original_path}/" original_length)
|
|
||||||
string(LENGTH "${lower}" path_length)
|
|
||||||
if(${path_length} GREATER ${original_length})
|
|
||||||
string(SUBSTRING "${lower}" 0 ${original_length} path)
|
|
||||||
if("${original_path}/" STREQUAL "${path}")
|
|
||||||
set(is_embedded 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Return type string based on computed booleans:
|
|
||||||
#
|
|
||||||
set(type "other")
|
|
||||||
|
|
||||||
if(is_system)
|
|
||||||
set(type "system")
|
|
||||||
elseif(is_embedded)
|
|
||||||
set(type "embedded")
|
|
||||||
elseif(is_local)
|
|
||||||
set(type "local")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
|
|
||||||
#message(STATUS " type: '${type}'")
|
|
||||||
|
|
||||||
if(NOT is_embedded)
|
|
||||||
if(NOT IS_ABSOLUTE "${resolved_file}")
|
|
||||||
if(lower MATCHES "^msvc[^/]+dll" AND is_system)
|
|
||||||
message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Provide a hook so that projects can override the decision on whether a
|
|
||||||
# library belongs to the system or not by whatever logic they choose:
|
|
||||||
#
|
|
||||||
if(COMMAND gp_resolved_file_type_override)
|
|
||||||
gp_resolved_file_type_override("${resolved_file}" type)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${type_var} "${type}" PARENT_SCOPE)
|
|
||||||
|
|
||||||
#message(STATUS "**")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_file_type original_file file type_var)
|
|
||||||
if(NOT IS_ABSOLUTE "${original_file}")
|
|
||||||
message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(exepath "${original_file}" PATH)
|
|
||||||
|
|
||||||
set(type "")
|
|
||||||
gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
|
|
||||||
|
|
||||||
set(${type_var} "${type}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
|
|
||||||
set(verbose 0)
|
|
||||||
set(eol_char "E")
|
|
||||||
|
|
||||||
if(NOT IS_ABSOLUTE "${target}")
|
|
||||||
message("warning: target '${target}' is not absolute...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT EXISTS "${target}")
|
|
||||||
message("warning: target '${target}' does not exist...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(gp_cmd_paths ${gp_cmd_paths}
|
|
||||||
"C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
|
|
||||||
"C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
|
|
||||||
"C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
|
|
||||||
"C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
|
|
||||||
"C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
|
|
||||||
"C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
|
|
||||||
"/usr/local/bin"
|
|
||||||
"/usr/bin"
|
|
||||||
)
|
|
||||||
|
|
||||||
# <setup-gp_tool-vars>
|
|
||||||
#
|
|
||||||
# Try to choose the right tool by default. Caller can set gp_tool prior to
|
|
||||||
# calling this function to force using a different tool.
|
|
||||||
#
|
|
||||||
if("${gp_tool}" STREQUAL "")
|
|
||||||
set(gp_tool "ldd")
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
set(gp_tool "otool")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32 AND NOT UNIX) # This is how to check for cygwin, har!
|
|
||||||
find_program(gp_dumpbin "dumpbin" PATHS ${gp_cmd_paths})
|
|
||||||
if(gp_dumpbin)
|
|
||||||
set(gp_tool "dumpbin")
|
|
||||||
else() # Try harder. Maybe we're on MinGW
|
|
||||||
set(gp_tool "objdump")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
|
|
||||||
|
|
||||||
if(NOT gp_cmd)
|
|
||||||
message(FATAL_ERROR "FATAL ERROR: could not find '${gp_tool}' - cannot analyze prerequisites!")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(gp_tool_known 0)
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "ldd")
|
|
||||||
set(gp_cmd_args "")
|
|
||||||
set(gp_regex "^[\t ]*[^\t ]+ => ([^\t\(]+) .*${eol_char}$")
|
|
||||||
set(gp_regex_error "not found${eol_char}$")
|
|
||||||
set(gp_regex_fallback "^[\t ]*([^\t ]+) => ([^\t ]+).*${eol_char}$")
|
|
||||||
set(gp_regex_cmp_count 1)
|
|
||||||
set(gp_tool_known 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "otool")
|
|
||||||
set(gp_cmd_args "-L")
|
|
||||||
set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
|
|
||||||
set(gp_regex_error "")
|
|
||||||
set(gp_regex_fallback "")
|
|
||||||
set(gp_regex_cmp_count 3)
|
|
||||||
set(gp_tool_known 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "dumpbin")
|
|
||||||
set(gp_cmd_args "/dependents")
|
|
||||||
set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$")
|
|
||||||
set(gp_regex_error "")
|
|
||||||
set(gp_regex_fallback "")
|
|
||||||
set(gp_regex_cmp_count 1)
|
|
||||||
set(gp_tool_known 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "objdump")
|
|
||||||
set(gp_cmd_args "-p")
|
|
||||||
set(gp_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$")
|
|
||||||
set(gp_regex_error "")
|
|
||||||
set(gp_regex_fallback "")
|
|
||||||
set(gp_regex_cmp_count 1)
|
|
||||||
set(gp_tool_known 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT gp_tool_known)
|
|
||||||
message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
|
|
||||||
message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
|
|
||||||
message(STATUS "Valid gp_tool values are dumpbin, ldd, objdump and otool.")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "dumpbin")
|
|
||||||
# When running dumpbin, it also needs the "Common7/IDE" directory in the
|
|
||||||
# PATH. It will already be in the PATH if being run from a Visual Studio
|
|
||||||
# command prompt. Add it to the PATH here in case we are running from a
|
|
||||||
# different command prompt.
|
|
||||||
#
|
|
||||||
get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
|
|
||||||
get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
|
|
||||||
# Use cmake paths as a user may have a PATH element ending with a backslash.
|
|
||||||
# This will escape the list delimiter and create havoc!
|
|
||||||
if(EXISTS "${gp_cmd_dlls_dir}")
|
|
||||||
# only add to the path if it is not already in the path
|
|
||||||
set(gp_found_cmd_dlls_dir 0)
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PATH}" env_path)
|
|
||||||
foreach(gp_env_path_element ${env_path})
|
|
||||||
if("${gp_env_path_element}" STREQUAL "${gp_cmd_dlls_dir}")
|
|
||||||
set(gp_found_cmd_dlls_dir 1)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT gp_found_cmd_dlls_dir)
|
|
||||||
file(TO_NATIVE_PATH "${gp_cmd_dlls_dir}" gp_cmd_dlls_dir)
|
|
||||||
set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
# </setup-gp_tool-vars>
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "ldd")
|
|
||||||
set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
|
|
||||||
foreach(dir ${exepath} ${dirs})
|
|
||||||
set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
# Track new prerequisites at each new level of recursion. Start with an
|
|
||||||
# empty list at each level:
|
|
||||||
#
|
|
||||||
set(unseen_prereqs)
|
|
||||||
|
|
||||||
# Run gp_cmd on the target:
|
|
||||||
#
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
|
|
||||||
OUTPUT_VARIABLE gp_cmd_ov
|
|
||||||
)
|
|
||||||
|
|
||||||
if("${gp_tool}" STREQUAL "ldd")
|
|
||||||
set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(verbose)
|
|
||||||
message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
|
|
||||||
message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
|
|
||||||
message(STATUS "</RawOutput>")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(target_dir "${target}" PATH)
|
|
||||||
|
|
||||||
# Convert to a list of lines:
|
|
||||||
#
|
|
||||||
string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
|
|
||||||
string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
|
|
||||||
|
|
||||||
# check for install id and remove it from list, since otool -L can include a
|
|
||||||
# reference to itself
|
|
||||||
set(gp_install_id)
|
|
||||||
if("${gp_tool}" STREQUAL "otool")
|
|
||||||
execute_process(
|
|
||||||
COMMAND otool -D ${target}
|
|
||||||
OUTPUT_VARIABLE gp_install_id_ov
|
|
||||||
)
|
|
||||||
# second line is install name
|
|
||||||
string(REGEX REPLACE ".*:\n" "" gp_install_id "${gp_install_id_ov}")
|
|
||||||
if(gp_install_id)
|
|
||||||
# trim
|
|
||||||
string(REGEX MATCH "[^\n ].*[^\n ]" gp_install_id "${gp_install_id}")
|
|
||||||
#message("INSTALL ID is \"${gp_install_id}\"")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Analyze each line for file names that match the regular expression:
|
|
||||||
#
|
|
||||||
foreach(candidate ${candidates})
|
|
||||||
if("${candidate}" MATCHES "${gp_regex}")
|
|
||||||
|
|
||||||
# Extract information from each candidate:
|
|
||||||
if(gp_regex_error AND "${candidate}" MATCHES "${gp_regex_error}")
|
|
||||||
string(REGEX REPLACE "${gp_regex_fallback}" "\\1" raw_item "${candidate}")
|
|
||||||
else()
|
|
||||||
string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(gp_regex_cmp_count GREATER 1)
|
|
||||||
string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(gp_regex_cmp_count GREATER 2)
|
|
||||||
string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Use the raw_item as the list entries returned by this function. Use the
|
|
||||||
# gp_resolve_item function to resolve it to an actual full path file if
|
|
||||||
# necessary.
|
|
||||||
#
|
|
||||||
set(item "${raw_item}")
|
|
||||||
|
|
||||||
# Add each item unless it is excluded:
|
|
||||||
#
|
|
||||||
set(add_item 1)
|
|
||||||
|
|
||||||
if("${item}" STREQUAL "${gp_install_id}")
|
|
||||||
set(add_item 0)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(add_item AND ${exclude_system})
|
|
||||||
set(type "")
|
|
||||||
gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type)
|
|
||||||
|
|
||||||
if("${type}" STREQUAL "system")
|
|
||||||
set(add_item 0)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(add_item)
|
|
||||||
list(LENGTH ${prerequisites_var} list_length_before_append)
|
|
||||||
gp_append_unique(${prerequisites_var} "${item}")
|
|
||||||
list(LENGTH ${prerequisites_var} list_length_after_append)
|
|
||||||
|
|
||||||
if(${recurse})
|
|
||||||
# If item was really added, this is the first time we have seen it.
|
|
||||||
# Add it to unseen_prereqs so that we can recursively add *its*
|
|
||||||
# prerequisites...
|
|
||||||
#
|
|
||||||
# But first: resolve its name to an absolute full path name such
|
|
||||||
# that the analysis tools can simply accept it as input.
|
|
||||||
#
|
|
||||||
if(NOT list_length_before_append EQUAL list_length_after_append)
|
|
||||||
gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
|
|
||||||
set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if(verbose)
|
|
||||||
message(STATUS "ignoring non-matching line: '${candidate}'")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
list(LENGTH ${prerequisites_var} prerequisites_var_length)
|
|
||||||
if(prerequisites_var_length GREATER 0)
|
|
||||||
list(SORT ${prerequisites_var})
|
|
||||||
endif()
|
|
||||||
if(${recurse})
|
|
||||||
set(more_inputs ${unseen_prereqs})
|
|
||||||
foreach(input ${more_inputs})
|
|
||||||
get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(list_prerequisites target)
|
|
||||||
if("${ARGV1}" STREQUAL "")
|
|
||||||
set(all 1)
|
|
||||||
else()
|
|
||||||
set(all "${ARGV1}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${ARGV2}" STREQUAL "")
|
|
||||||
set(exclude_system 0)
|
|
||||||
else()
|
|
||||||
set(exclude_system "${ARGV2}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${ARGV3}" STREQUAL "")
|
|
||||||
set(verbose 0)
|
|
||||||
else()
|
|
||||||
set(verbose "${ARGV3}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(count 0)
|
|
||||||
set(count_str "")
|
|
||||||
set(print_count "${verbose}")
|
|
||||||
set(print_prerequisite_type "${verbose}")
|
|
||||||
set(print_target "${verbose}")
|
|
||||||
set(type_str "")
|
|
||||||
|
|
||||||
get_filename_component(exepath "${target}" PATH)
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
|
|
||||||
|
|
||||||
if(print_target)
|
|
||||||
message(STATUS "File '${target}' depends on:")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(d ${prereqs})
|
|
||||||
math(EXPR count "${count} + 1")
|
|
||||||
|
|
||||||
if(print_count)
|
|
||||||
set(count_str "${count}. ")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(print_prerequisite_type)
|
|
||||||
gp_file_type("${target}" "${d}" type)
|
|
||||||
set(type_str " (${type})")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "${count_str}${d}${type_str}")
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(list_prerequisites_by_glob glob_arg glob_exp)
|
|
||||||
message(STATUS "=============================================================================")
|
|
||||||
message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
|
|
||||||
message(STATUS "")
|
|
||||||
file(${glob_arg} file_list ${glob_exp})
|
|
||||||
foreach(f ${file_list})
|
|
||||||
is_file_executable("${f}" is_f_executable)
|
|
||||||
if(is_f_executable)
|
|
||||||
message(STATUS "=============================================================================")
|
|
||||||
list_prerequisites("${f}" ${ARGN})
|
|
||||||
message(STATUS "")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>A Minecraft mod wants to access your camera.</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>A Minecraft mod wants to access your microphone.</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string>NSApplication</string>
|
<string>NSApplication</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
@ -36,5 +40,43 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||||
|
<key>SUPublicEDKey</key>
|
||||||
|
<string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string>
|
||||||
|
<key>SUFeedURL</key>
|
||||||
|
<string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string>
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>zip</string>
|
||||||
|
<string>mrpack</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Prism Launcher instance</string>
|
||||||
|
<key>CFBundleTypeOSTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>TEXT</string>
|
||||||
|
<string>utxt</string>
|
||||||
|
<string>TUTX</string>
|
||||||
|
<string>****</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Alternate</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>Curseforge</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>curseforge</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
if(__QMAKEQUERY_CMAKE__)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
set(__QMAKEQUERY_CMAKE__ TRUE)
|
|
||||||
|
|
||||||
get_target_property(QMAKE_EXECUTABLE Qt5::qmake LOCATION)
|
|
||||||
|
|
||||||
function(QUERY_QMAKE VAR RESULT)
|
|
||||||
exec_program(${QMAKE_EXECUTABLE} ARGS "-query ${VAR}" RETURN_VALUE return_code OUTPUT_VARIABLE output )
|
|
||||||
if(NOT return_code)
|
|
||||||
file(TO_CMAKE_PATH "${output}" output)
|
|
||||||
set(${RESULT} ${output} PARENT_SCOPE)
|
|
||||||
endif(NOT return_code)
|
|
||||||
endfunction(QUERY_QMAKE)
|
|
38
cmake/QtVersionOption.cmake
Normal file
38
cmake/QtVersionOption.cmake
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#.rst:
|
||||||
|
# QtVersionOption
|
||||||
|
# ---------------
|
||||||
|
#
|
||||||
|
# Adds a build option to select the major Qt version if necessary,
|
||||||
|
# that is, if the major Qt version has not yet been determined otherwise
|
||||||
|
# (e.g. by a corresponding find_package() call).
|
||||||
|
#
|
||||||
|
# This module is typically included by other modules requiring knowledge
|
||||||
|
# about the major Qt version.
|
||||||
|
#
|
||||||
|
# ``QT_MAJOR_VERSION`` is defined to either be "5" or "6".
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Since 5.82.0.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
if (DEFINED QT_MAJOR_VERSION)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (TARGET Qt5::Core)
|
||||||
|
set(QT_MAJOR_VERSION 5)
|
||||||
|
elseif (TARGET Qt6::Core)
|
||||||
|
set(QT_MAJOR_VERSION 6)
|
||||||
|
else()
|
||||||
|
option(BUILD_WITH_QT6 "Build against Qt 6" OFF)
|
||||||
|
|
||||||
|
if (BUILD_WITH_QT6)
|
||||||
|
set(QT_MAJOR_VERSION 6)
|
||||||
|
else()
|
||||||
|
set(QT_MAJOR_VERSION 5)
|
||||||
|
endif()
|
||||||
|
endif()
|
97
cmake/QtVersionlessBackport.cmake
Normal file
97
cmake/QtVersionlessBackport.cmake
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#=============================================================================
|
||||||
|
# Copyright 2005-2011 Kitware, Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Kitware, Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
# From Qt5CoreMacros.cmake
|
||||||
|
|
||||||
|
function(qt_generate_moc)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_generate_moc(${ARGV})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_generate_moc(${ARGV})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(qt_wrap_cpp outfiles)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_wrap_cpp("${outfiles}" ${ARGN})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_wrap_cpp("${outfiles}" ${ARGN})
|
||||||
|
endif()
|
||||||
|
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(qt_add_binary_resources)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_add_binary_resources(${ARGV})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_add_binary_resources(${ARGV})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(qt_add_resources outfiles)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_add_resources("${outfiles}" ${ARGN})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_add_resources("${outfiles}" ${ARGN})
|
||||||
|
endif()
|
||||||
|
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(qt_add_big_resources outfiles)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_add_big_resources(${outfiles} ${ARGN})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_add_big_resources(${outfiles} ${ARGN})
|
||||||
|
endif()
|
||||||
|
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(qt_import_plugins)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_import_plugins(${ARGV})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_import_plugins(${ARGV})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
# From Qt5WidgetsMacros.cmake
|
||||||
|
|
||||||
|
function(qt_wrap_ui outfiles)
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 5)
|
||||||
|
qt5_wrap_ui("${outfiles}" ${ARGN})
|
||||||
|
elseif(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt6_wrap_ui("${outfiles}" ${ARGN})
|
||||||
|
endif()
|
||||||
|
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
@ -1,48 +0,0 @@
|
|||||||
find_package(Qt5Test REQUIRED)
|
|
||||||
|
|
||||||
set(TEST_RESOURCE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
message(${TEST_RESOURCE_PATH})
|
|
||||||
|
|
||||||
function(add_unit_test name)
|
|
||||||
set(options "")
|
|
||||||
set(oneValueArgs DATA)
|
|
||||||
set(multiValueArgs SOURCES LIBS)
|
|
||||||
|
|
||||||
cmake_parse_arguments(OPT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
add_executable(${name}_test ${OPT_SOURCES} ${TEST_RESOURCE_PATH}/UnitTest/test.rc)
|
|
||||||
else()
|
|
||||||
add_executable(${name}_test ${OPT_SOURCES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT "${OPT_DATA}" STREQUAL "")
|
|
||||||
set(TEST_DATA_PATH "${CMAKE_CURRENT_BINARY_DIR}/data")
|
|
||||||
set(TEST_DATA_PATH_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${OPT_DATA}")
|
|
||||||
message("From ${TEST_DATA_PATH_SRC} to ${TEST_DATA_PATH}")
|
|
||||||
string(REGEX REPLACE "[/\\:]" "_" DATA_TARGET_NAME "${TEST_DATA_PATH_SRC}")
|
|
||||||
if(UNIX)
|
|
||||||
# on unix we get the third / from the filename
|
|
||||||
set(TEST_DATA_URL "file://${TEST_DATA_PATH}")
|
|
||||||
else()
|
|
||||||
# we don't on windows, so we have to add it ourselves
|
|
||||||
set(TEST_DATA_URL "file:///${TEST_DATA_PATH}")
|
|
||||||
endif()
|
|
||||||
if(NOT TARGET "${DATA_TARGET_NAME}")
|
|
||||||
add_custom_target(${DATA_TARGET_NAME})
|
|
||||||
add_dependencies(${name}_test ${DATA_TARGET_NAME})
|
|
||||||
add_custom_command(
|
|
||||||
TARGET ${DATA_TARGET_NAME}
|
|
||||||
COMMAND ${CMAKE_COMMAND} "-DTEST_DATA_URL=${TEST_DATA_URL}" -DSOURCE=${TEST_DATA_PATH_SRC} -DDESTINATION=${TEST_DATA_PATH} -P ${TEST_RESOURCE_PATH}/UnitTest/generate_test_data.cmake
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(${name}_test Qt5::Test ${OPT_LIBS})
|
|
||||||
|
|
||||||
target_include_directories(${name}_test PRIVATE "${TEST_RESOURCE_PATH}/UnitTest/")
|
|
||||||
|
|
||||||
add_test(NAME ${name} COMMAND ${name}_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endfunction()
|
|
@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QTest>
|
|
||||||
#include <QDir>
|
|
||||||
|
|
||||||
#define expandstr(s) expandstr2(s)
|
|
||||||
#define expandstr2(s) #s
|
|
||||||
|
|
||||||
class TestsInternal
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static QByteArray readFile(const QString &fileName)
|
|
||||||
{
|
|
||||||
QFile f(fileName);
|
|
||||||
f.open(QFile::ReadOnly);
|
|
||||||
return f.readAll();
|
|
||||||
}
|
|
||||||
static QString readFileUtf8(const QString &fileName)
|
|
||||||
{
|
|
||||||
return QString::fromUtf8(readFile(fileName));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GET_TEST_FILE(file) TestsInternal::readFile(QFINDTESTDATA(file))
|
|
||||||
#define GET_TEST_FILE_UTF8(file) TestsInternal::readFileUtf8(QFINDTESTDATA(file))
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
# Copy files from source directory to destination directory, substituting any
|
|
||||||
# variables. Create destination directory if it does not exist.
|
|
||||||
|
|
||||||
function(configure_files srcDir destDir)
|
|
||||||
make_directory(${destDir})
|
|
||||||
|
|
||||||
file(GLOB templateFiles RELATIVE ${srcDir} ${srcDir}/*)
|
|
||||||
foreach(templateFile ${templateFiles})
|
|
||||||
set(srcTemplatePath ${srcDir}/${templateFile})
|
|
||||||
if(NOT IS_DIRECTORY ${srcTemplatePath})
|
|
||||||
configure_file(
|
|
||||||
${srcTemplatePath}
|
|
||||||
${destDir}/${templateFile}
|
|
||||||
@ONLY
|
|
||||||
NEWLINE_STYLE LF
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
configure_files("${srcTemplatePath}" "${destDir}/${templateFile}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
configure_files(${SOURCE} ${DESTINATION})
|
|
@ -1,28 +0,0 @@
|
|||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
1 RT_MANIFEST "test.manifest"
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION 1,0,0,0
|
|
||||||
FILEOS VOS_NT_WINDOWS32
|
|
||||||
FILETYPE VFT_APP
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "000004b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "CompanyName", "MultiMC Contributors"
|
|
||||||
VALUE "FileDescription", "Testcase"
|
|
||||||
VALUE "FileVersion", "1.0.0.0"
|
|
||||||
VALUE "ProductName", "Launcher Testcase"
|
|
||||||
VALUE "ProductVersion", "5"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x0000, 0x04b0 // Unicode
|
|
||||||
END
|
|
||||||
END
|
|
@ -1,881 +0,0 @@
|
|||||||
# - Use Module for Java
|
|
||||||
# This file provides functions for Java. It is assumed that FindJava.cmake
|
|
||||||
# has already been loaded. See FindJava.cmake for information on how to
|
|
||||||
# load Java into your CMake project.
|
|
||||||
#
|
|
||||||
# add_jar(TARGET_NAME SRC1 SRC2 .. SRCN RCS1 RCS2 .. RCSN)
|
|
||||||
#
|
|
||||||
# This command creates a <TARGET_NAME>.jar. It compiles the given source
|
|
||||||
# files (SRC) and adds the given resource files (RCS) to the jar file.
|
|
||||||
# If only resource files are given then just a jar file is created.
|
|
||||||
#
|
|
||||||
# Additional instructions:
|
|
||||||
# To add compile flags to the target you can set these flags with
|
|
||||||
# the following variable:
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAVA_COMPILE_FLAGS -nowarn)
|
|
||||||
#
|
|
||||||
# To add a path or a jar file to the class path you can do this
|
|
||||||
# with the CMAKE_JAVA_INCLUDE_PATH variable.
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAVA_INCLUDE_PATH /usr/share/java/shibboleet.jar)
|
|
||||||
#
|
|
||||||
# To use a different output name for the target you can set it with:
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAVA_TARGET_OUTPUT_NAME shibboleet.jar)
|
|
||||||
# add_jar(foobar foobar.java)
|
|
||||||
#
|
|
||||||
# To use a different output directory than CMAKE_CURRENT_BINARY_DIR
|
|
||||||
# you can set it with:
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin)
|
|
||||||
#
|
|
||||||
# To define an entry point in your jar you can set it with:
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAVA_JAR_ENTRY_POINT com/examples/MyProject/Main)
|
|
||||||
#
|
|
||||||
# To add a VERSION to the target output name you can set it using
|
|
||||||
# CMAKE_JAVA_TARGET_VERSION. This will create a jar file with the name
|
|
||||||
# shibboleet-1.0.0.jar and will create a symlink shibboleet.jar
|
|
||||||
# pointing to the jar with the version information.
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAVA_TARGET_VERSION 1.2.0)
|
|
||||||
# add_jar(shibboleet shibbotleet.java)
|
|
||||||
#
|
|
||||||
# If the target is a JNI library, utilize the following commands to
|
|
||||||
# create a JNI symbolic link:
|
|
||||||
#
|
|
||||||
# set(CMAKE_JNI_TARGET TRUE)
|
|
||||||
# set(CMAKE_JAVA_TARGET_VERSION 1.2.0)
|
|
||||||
# add_jar(shibboleet shibbotleet.java)
|
|
||||||
# install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet)
|
|
||||||
# install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR})
|
|
||||||
#
|
|
||||||
# If a single target needs to produce more than one jar from its
|
|
||||||
# java source code, to prevent the accumulation of duplicate class
|
|
||||||
# files in subsequent jars, set/reset CMAKE_JAR_CLASSES_PREFIX prior
|
|
||||||
# to calling the add_jar() function:
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo)
|
|
||||||
# add_jar(foo foo.java)
|
|
||||||
#
|
|
||||||
# set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar)
|
|
||||||
# add_jar(bar bar.java)
|
|
||||||
#
|
|
||||||
# Target Properties:
|
|
||||||
# The add_jar() functions sets some target properties. You can get these
|
|
||||||
# properties with the
|
|
||||||
# get_property(TARGET <target_name> PROPERTY <propery_name>)
|
|
||||||
# command.
|
|
||||||
#
|
|
||||||
# INSTALL_FILES The files which should be installed. This is used by
|
|
||||||
# install_jar().
|
|
||||||
# JNI_SYMLINK The JNI symlink which should be installed.
|
|
||||||
# This is used by install_jni_symlink().
|
|
||||||
# JAR_FILE The location of the jar file so that you can include
|
|
||||||
# it.
|
|
||||||
# CLASS_DIR The directory where the class files can be found. For
|
|
||||||
# example to use them with javah.
|
|
||||||
#
|
|
||||||
# find_jar(<VAR>
|
|
||||||
# name | NAMES name1 [name2 ...]
|
|
||||||
# [PATHS path1 [path2 ... ENV var]]
|
|
||||||
# [VERSIONS version1 [version2]]
|
|
||||||
# [DOC "cache documentation string"]
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# This command is used to find a full path to the named jar. A cache
|
|
||||||
# entry named by <VAR> is created to stor the result of this command. If
|
|
||||||
# the full path to a jar is found the result is stored in the variable
|
|
||||||
# and the search will not repeated unless the variable is cleared. If
|
|
||||||
# nothing is found, the result will be <VAR>-NOTFOUND, and the search
|
|
||||||
# will be attempted again next time find_jar is invoked with the same
|
|
||||||
# variable.
|
|
||||||
# The name of the full path to a file that is searched for is specified
|
|
||||||
# by the names listed after NAMES argument. Additional search locations
|
|
||||||
# can be specified after the PATHS argument. If you require special a
|
|
||||||
# version of a jar file you can specify it with the VERSIONS argument.
|
|
||||||
# The argument after DOC will be used for the documentation string in
|
|
||||||
# the cache.
|
|
||||||
#
|
|
||||||
# install_jar(TARGET_NAME DESTINATION)
|
|
||||||
#
|
|
||||||
# This command installs the TARGET_NAME files to the given DESTINATION.
|
|
||||||
# It should be called in the same scope as add_jar() or it will fail.
|
|
||||||
#
|
|
||||||
# install_jni_symlink(TARGET_NAME DESTINATION)
|
|
||||||
#
|
|
||||||
# This command installs the TARGET_NAME JNI symlinks to the given
|
|
||||||
# DESTINATION. It should be called in the same scope as add_jar()
|
|
||||||
# or it will fail.
|
|
||||||
#
|
|
||||||
# create_javadoc(<VAR>
|
|
||||||
# PACKAGES pkg1 [pkg2 ...]
|
|
||||||
# [SOURCEPATH <sourcepath>]
|
|
||||||
# [CLASSPATH <classpath>]
|
|
||||||
# [INSTALLPATH <install path>]
|
|
||||||
# [DOCTITLE "the documentation title"]
|
|
||||||
# [WINDOWTITLE "the title of the document"]
|
|
||||||
# [AUTHOR TRUE|FALSE]
|
|
||||||
# [USE TRUE|FALSE]
|
|
||||||
# [VERSION TRUE|FALSE]
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# Create java documentation based on files or packages. For more
|
|
||||||
# details please read the javadoc manpage.
|
|
||||||
#
|
|
||||||
# There are two main signatures for create_javadoc. The first
|
|
||||||
# signature works with package names on a path with source files:
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# create_javadoc(my_example_doc
|
|
||||||
# PACKAGES com.exmaple.foo com.example.bar
|
|
||||||
# SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
# CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
|
|
||||||
# WINDOWTITLE "My example"
|
|
||||||
# DOCTITLE "<h1>My example</h1>"
|
|
||||||
# AUTHOR TRUE
|
|
||||||
# USE TRUE
|
|
||||||
# VERSION TRUE
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# The second signature for create_javadoc works on a given list of
|
|
||||||
# files.
|
|
||||||
#
|
|
||||||
# create_javadoc(<VAR>
|
|
||||||
# FILES file1 [file2 ...]
|
|
||||||
# [CLASSPATH <classpath>]
|
|
||||||
# [INSTALLPATH <install path>]
|
|
||||||
# [DOCTITLE "the documentation title"]
|
|
||||||
# [WINDOWTITLE "the title of the document"]
|
|
||||||
# [AUTHOR TRUE|FALSE]
|
|
||||||
# [USE TRUE|FALSE]
|
|
||||||
# [VERSION TRUE|FALSE]
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# create_javadoc(my_example_doc
|
|
||||||
# FILES ${example_SRCS}
|
|
||||||
# CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
|
|
||||||
# WINDOWTITLE "My example"
|
|
||||||
# DOCTITLE "<h1>My example</h1>"
|
|
||||||
# AUTHOR TRUE
|
|
||||||
# USE TRUE
|
|
||||||
# VERSION TRUE
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# Both signatures share most of the options. These options are the
|
|
||||||
# same as what you can find in the javadoc manpage. Please look at
|
|
||||||
# the manpage for CLASSPATH, DOCTITLE, WINDOWTITLE, AUTHOR, USE and
|
|
||||||
# VERSION.
|
|
||||||
#
|
|
||||||
# The documentation will be by default installed to
|
|
||||||
#
|
|
||||||
# ${CMAKE_INSTALL_PREFIX}/share/javadoc/<VAR>
|
|
||||||
#
|
|
||||||
# if you don't set the INSTALLPATH.
|
|
||||||
#
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
|
|
||||||
# Copyright 2010 Ben Boeckel <ben.boeckel@kitware.com>
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
function (__java_copy_file src dest comment)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${dest}
|
|
||||||
COMMAND cmake -E copy_if_different
|
|
||||||
ARGS ${src}
|
|
||||||
${dest}
|
|
||||||
DEPENDS ${src}
|
|
||||||
COMMENT ${comment})
|
|
||||||
endfunction (__java_copy_file src dest comment)
|
|
||||||
|
|
||||||
# define helper scripts
|
|
||||||
set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaClassFilelist.cmake)
|
|
||||||
set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake)
|
|
||||||
|
|
||||||
function(add_jar _TARGET_NAME)
|
|
||||||
set(_JAVA_SOURCE_FILES ${ARGN})
|
|
||||||
|
|
||||||
if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
|
|
||||||
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endif(NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
|
|
||||||
|
|
||||||
if (CMAKE_JAVA_JAR_ENTRY_POINT)
|
|
||||||
set(_ENTRY_POINT_OPTION e)
|
|
||||||
set(_ENTRY_POINT_VALUE ${CMAKE_JAVA_JAR_ENTRY_POINT})
|
|
||||||
endif (CMAKE_JAVA_JAR_ENTRY_POINT)
|
|
||||||
|
|
||||||
if (LIBRARY_OUTPUT_PATH)
|
|
||||||
set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH})
|
|
||||||
else (LIBRARY_OUTPUT_PATH)
|
|
||||||
set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR})
|
|
||||||
endif (LIBRARY_OUTPUT_PATH)
|
|
||||||
|
|
||||||
set(CMAKE_JAVA_INCLUDE_PATH
|
|
||||||
${CMAKE_JAVA_INCLUDE_PATH}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
${CMAKE_JAVA_OBJECT_OUTPUT_PATH}
|
|
||||||
${CMAKE_JAVA_LIBRARY_OUTPUT_PATH}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (WIN32 AND NOT CYGWIN AND NOT CMAKE_CROSSCOMPILING)
|
|
||||||
set(CMAKE_JAVA_INCLUDE_FLAG_SEP ";")
|
|
||||||
else ()
|
|
||||||
set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach (JAVA_INCLUDE_DIR ${CMAKE_JAVA_INCLUDE_PATH})
|
|
||||||
set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}")
|
|
||||||
endforeach(JAVA_INCLUDE_DIR)
|
|
||||||
|
|
||||||
set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir")
|
|
||||||
|
|
||||||
set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar")
|
|
||||||
if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION)
|
|
||||||
set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar")
|
|
||||||
set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar")
|
|
||||||
elseif (CMAKE_JAVA_TARGET_VERSION)
|
|
||||||
set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar")
|
|
||||||
set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar")
|
|
||||||
elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME)
|
|
||||||
set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar")
|
|
||||||
endif (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION)
|
|
||||||
# reset
|
|
||||||
set(CMAKE_JAVA_TARGET_OUTPUT_NAME)
|
|
||||||
|
|
||||||
set(_JAVA_CLASS_FILES)
|
|
||||||
set(_JAVA_COMPILE_FILES)
|
|
||||||
set(_JAVA_DEPENDS)
|
|
||||||
set(_JAVA_RESOURCE_FILES)
|
|
||||||
foreach(_JAVA_SOURCE_FILE ${_JAVA_SOURCE_FILES})
|
|
||||||
get_filename_component(_JAVA_EXT ${_JAVA_SOURCE_FILE} EXT)
|
|
||||||
get_filename_component(_JAVA_FILE ${_JAVA_SOURCE_FILE} NAME_WE)
|
|
||||||
get_filename_component(_JAVA_PATH ${_JAVA_SOURCE_FILE} PATH)
|
|
||||||
get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE)
|
|
||||||
|
|
||||||
file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR} ${_JAVA_FULL})
|
|
||||||
file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL})
|
|
||||||
string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN)
|
|
||||||
string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN)
|
|
||||||
if (${_BIN_LEN} LESS ${_SRC_LEN})
|
|
||||||
set(_JAVA_REL_PATH ${_JAVA_REL_BINARY_PATH})
|
|
||||||
else (${_BIN_LEN} LESS ${_SRC_LEN})
|
|
||||||
set(_JAVA_REL_PATH ${_JAVA_REL_SOURCE_PATH})
|
|
||||||
endif (${_BIN_LEN} LESS ${_SRC_LEN})
|
|
||||||
get_filename_component(_JAVA_REL_PATH ${_JAVA_REL_PATH} PATH)
|
|
||||||
|
|
||||||
if (_JAVA_EXT MATCHES ".java")
|
|
||||||
list(APPEND _JAVA_COMPILE_FILES ${_JAVA_SOURCE_FILE})
|
|
||||||
set(_JAVA_CLASS_FILE "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_REL_PATH}/${_JAVA_FILE}.class")
|
|
||||||
set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES} ${_JAVA_CLASS_FILE})
|
|
||||||
|
|
||||||
elseif (_JAVA_EXT MATCHES ".jar"
|
|
||||||
OR _JAVA_EXT MATCHES ".war"
|
|
||||||
OR _JAVA_EXT MATCHES ".ear"
|
|
||||||
OR _JAVA_EXT MATCHES ".sar")
|
|
||||||
list(APPEND CMAKE_JAVA_INCLUDE_PATH ${_JAVA_SOURCE_FILE})
|
|
||||||
|
|
||||||
elseif (_JAVA_EXT STREQUAL "")
|
|
||||||
list(APPEND CMAKE_JAVA_INCLUDE_PATH ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}} ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}_CLASSPATH})
|
|
||||||
list(APPEND _JAVA_DEPENDS ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}})
|
|
||||||
|
|
||||||
else (_JAVA_EXT MATCHES ".java")
|
|
||||||
__java_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_JAVA_SOURCE_FILE}
|
|
||||||
${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_SOURCE_FILE}
|
|
||||||
"Copying ${_JAVA_SOURCE_FILE} to the build directory")
|
|
||||||
list(APPEND _JAVA_RESOURCE_FILES ${_JAVA_SOURCE_FILE})
|
|
||||||
endif (_JAVA_EXT MATCHES ".java")
|
|
||||||
endforeach(_JAVA_SOURCE_FILE)
|
|
||||||
|
|
||||||
# create an empty java_class_filelist
|
|
||||||
if (NOT EXISTS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist)
|
|
||||||
file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_JAVA_COMPILE_FILES)
|
|
||||||
# Compile the java files and create a list of class files
|
|
||||||
add_custom_command(
|
|
||||||
# NOTE: this command generates an artificial dependency file
|
|
||||||
OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
|
|
||||||
COMMAND ${Java_JAVAC_EXECUTABLE}
|
|
||||||
${CMAKE_JAVA_COMPILE_FLAGS}
|
|
||||||
-classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}"
|
|
||||||
-d ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
|
|
||||||
${_JAVA_COMPILE_FILES}
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
|
|
||||||
DEPENDS ${_JAVA_COMPILE_FILES}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
COMMENT "Building Java objects for ${_TARGET_NAME}.jar"
|
|
||||||
)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
|
|
||||||
-DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}"
|
|
||||||
-P ${_JAVA_CLASS_FILELIST_SCRIPT}
|
|
||||||
DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
endif (_JAVA_COMPILE_FILES)
|
|
||||||
|
|
||||||
# create the jar file
|
|
||||||
set(_JAVA_JAR_OUTPUT_PATH
|
|
||||||
${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME})
|
|
||||||
if (CMAKE_JNI_TARGET)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
|
|
||||||
COMMAND ${Java_JAR_EXECUTABLE}
|
|
||||||
-cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE}
|
|
||||||
${_JAVA_RESOURCE_FILES} @java_class_filelist
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
|
|
||||||
-D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
|
|
||||||
-D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
|
|
||||||
-P ${_JAVA_SYMLINK_SCRIPT}
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
|
|
||||||
-D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH}
|
|
||||||
-D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
|
|
||||||
-P ${_JAVA_SYMLINK_SCRIPT}
|
|
||||||
DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
|
|
||||||
WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
|
|
||||||
COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
|
|
||||||
)
|
|
||||||
else ()
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
|
|
||||||
COMMAND ${Java_JAR_EXECUTABLE}
|
|
||||||
-cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE}
|
|
||||||
${_JAVA_RESOURCE_FILES} @java_class_filelist
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
|
|
||||||
-D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
|
|
||||||
-D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
|
|
||||||
-P ${_JAVA_SYMLINK_SCRIPT}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
|
|
||||||
DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
|
|
||||||
COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
|
|
||||||
)
|
|
||||||
endif (CMAKE_JNI_TARGET)
|
|
||||||
|
|
||||||
# Add the target and make sure we have the latest resource files.
|
|
||||||
add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_JAVA_JAR_OUTPUT_PATH})
|
|
||||||
|
|
||||||
set_property(
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
INSTALL_FILES
|
|
||||||
${_JAVA_JAR_OUTPUT_PATH}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (_JAVA_TARGET_OUTPUT_LINK)
|
|
||||||
set_property(
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
INSTALL_FILES
|
|
||||||
${_JAVA_JAR_OUTPUT_PATH}
|
|
||||||
${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (CMAKE_JNI_TARGET)
|
|
||||||
set_property(
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
JNI_SYMLINK
|
|
||||||
${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
|
|
||||||
)
|
|
||||||
endif (CMAKE_JNI_TARGET)
|
|
||||||
endif (_JAVA_TARGET_OUTPUT_LINK)
|
|
||||||
|
|
||||||
set_property(
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
JAR_FILE
|
|
||||||
${_JAVA_JAR_OUTPUT_PATH}
|
|
||||||
)
|
|
||||||
|
|
||||||
set_property(
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
CLASSDIR
|
|
||||||
${CMAKE_JAVA_CLASS_OUTPUT_PATH}
|
|
||||||
)
|
|
||||||
|
|
||||||
endfunction(add_jar)
|
|
||||||
|
|
||||||
function(INSTALL_JAR _TARGET_NAME _DESTINATION)
|
|
||||||
get_property(__FILES
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
INSTALL_FILES
|
|
||||||
)
|
|
||||||
|
|
||||||
if (__FILES)
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
${__FILES}
|
|
||||||
DESTINATION
|
|
||||||
${_DESTINATION}
|
|
||||||
)
|
|
||||||
else (__FILES)
|
|
||||||
message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.")
|
|
||||||
endif (__FILES)
|
|
||||||
endfunction(INSTALL_JAR _TARGET_NAME _DESTINATION)
|
|
||||||
|
|
||||||
function(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION)
|
|
||||||
get_property(__SYMLINK
|
|
||||||
TARGET
|
|
||||||
${_TARGET_NAME}
|
|
||||||
PROPERTY
|
|
||||||
JNI_SYMLINK
|
|
||||||
)
|
|
||||||
|
|
||||||
if (__SYMLINK)
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
${__SYMLINK}
|
|
||||||
DESTINATION
|
|
||||||
${_DESTINATION}
|
|
||||||
)
|
|
||||||
else (__SYMLINK)
|
|
||||||
message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.")
|
|
||||||
endif (__SYMLINK)
|
|
||||||
endfunction(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION)
|
|
||||||
|
|
||||||
function (find_jar VARIABLE)
|
|
||||||
set(_jar_names)
|
|
||||||
set(_jar_files)
|
|
||||||
set(_jar_versions)
|
|
||||||
set(_jar_paths
|
|
||||||
/usr/share/java/
|
|
||||||
/usr/local/share/java/
|
|
||||||
${Java_JAR_PATHS})
|
|
||||||
set(_jar_doc "NOTSET")
|
|
||||||
|
|
||||||
set(_state "name")
|
|
||||||
|
|
||||||
foreach (arg ${ARGN})
|
|
||||||
if (${_state} STREQUAL "name")
|
|
||||||
if (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_state "versions")
|
|
||||||
elseif (${arg} STREQUAL "NAMES")
|
|
||||||
set(_state "names")
|
|
||||||
elseif (${arg} STREQUAL "PATHS")
|
|
||||||
set(_state "paths")
|
|
||||||
elseif (${arg} STREQUAL "DOC")
|
|
||||||
set(_state "doc")
|
|
||||||
else (${arg} STREQUAL "NAMES")
|
|
||||||
set(_jar_names ${arg})
|
|
||||||
if (_jar_doc STREQUAL "NOTSET")
|
|
||||||
set(_jar_doc "Finding ${arg} jar")
|
|
||||||
endif (_jar_doc STREQUAL "NOTSET")
|
|
||||||
endif (${arg} STREQUAL "VERSIONS")
|
|
||||||
elseif (${_state} STREQUAL "versions")
|
|
||||||
if (${arg} STREQUAL "NAMES")
|
|
||||||
set(_state "names")
|
|
||||||
elseif (${arg} STREQUAL "PATHS")
|
|
||||||
set(_state "paths")
|
|
||||||
elseif (${arg} STREQUAL "DOC")
|
|
||||||
set(_state "doc")
|
|
||||||
else (${arg} STREQUAL "NAMES")
|
|
||||||
set(_jar_versions ${_jar_versions} ${arg})
|
|
||||||
endif (${arg} STREQUAL "NAMES")
|
|
||||||
elseif (${_state} STREQUAL "names")
|
|
||||||
if (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_state "versions")
|
|
||||||
elseif (${arg} STREQUAL "PATHS")
|
|
||||||
set(_state "paths")
|
|
||||||
elseif (${arg} STREQUAL "DOC")
|
|
||||||
set(_state "doc")
|
|
||||||
else (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_jar_names ${_jar_names} ${arg})
|
|
||||||
if (_jar_doc STREQUAL "NOTSET")
|
|
||||||
set(_jar_doc "Finding ${arg} jar")
|
|
||||||
endif (_jar_doc STREQUAL "NOTSET")
|
|
||||||
endif (${arg} STREQUAL "VERSIONS")
|
|
||||||
elseif (${_state} STREQUAL "paths")
|
|
||||||
if (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_state "versions")
|
|
||||||
elseif (${arg} STREQUAL "NAMES")
|
|
||||||
set(_state "names")
|
|
||||||
elseif (${arg} STREQUAL "DOC")
|
|
||||||
set(_state "doc")
|
|
||||||
else (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_jar_paths ${_jar_paths} ${arg})
|
|
||||||
endif (${arg} STREQUAL "VERSIONS")
|
|
||||||
elseif (${_state} STREQUAL "doc")
|
|
||||||
if (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_state "versions")
|
|
||||||
elseif (${arg} STREQUAL "NAMES")
|
|
||||||
set(_state "names")
|
|
||||||
elseif (${arg} STREQUAL "PATHS")
|
|
||||||
set(_state "paths")
|
|
||||||
else (${arg} STREQUAL "VERSIONS")
|
|
||||||
set(_jar_doc ${arg})
|
|
||||||
endif (${arg} STREQUAL "VERSIONS")
|
|
||||||
endif (${_state} STREQUAL "name")
|
|
||||||
endforeach (arg ${ARGN})
|
|
||||||
|
|
||||||
if (NOT _jar_names)
|
|
||||||
message(FATAL_ERROR "find_jar: No name to search for given")
|
|
||||||
endif (NOT _jar_names)
|
|
||||||
|
|
||||||
foreach (jar_name ${_jar_names})
|
|
||||||
foreach (version ${_jar_versions})
|
|
||||||
set(_jar_files ${_jar_files} ${jar_name}-${version}.jar)
|
|
||||||
endforeach (version ${_jar_versions})
|
|
||||||
set(_jar_files ${_jar_files} ${jar_name}.jar)
|
|
||||||
endforeach (jar_name ${_jar_names})
|
|
||||||
|
|
||||||
find_file(${VARIABLE}
|
|
||||||
NAMES ${_jar_files}
|
|
||||||
PATHS ${_jar_paths}
|
|
||||||
DOC ${_jar_doc}
|
|
||||||
NO_DEFAULT_PATH)
|
|
||||||
endfunction (find_jar VARIABLE)
|
|
||||||
|
|
||||||
function(create_javadoc _target)
|
|
||||||
set(_javadoc_packages)
|
|
||||||
set(_javadoc_files)
|
|
||||||
set(_javadoc_sourcepath)
|
|
||||||
set(_javadoc_classpath)
|
|
||||||
set(_javadoc_installpath "${CMAKE_INSTALL_PREFIX}/share/javadoc")
|
|
||||||
set(_javadoc_doctitle)
|
|
||||||
set(_javadoc_windowtitle)
|
|
||||||
set(_javadoc_author FALSE)
|
|
||||||
set(_javadoc_version FALSE)
|
|
||||||
set(_javadoc_use FALSE)
|
|
||||||
|
|
||||||
set(_state "package")
|
|
||||||
|
|
||||||
foreach (arg ${ARGN})
|
|
||||||
if (${_state} STREQUAL "package")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_packages ${arg})
|
|
||||||
set(_state "packages")
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "packages")
|
|
||||||
if (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
list(APPEND _javadoc_packages ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "files")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
list(APPEND _javadoc_files ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "sourcepath")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
list(APPEND _javadoc_sourcepath ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "classpath")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
list(APPEND _javadoc_classpath ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "installpath")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_installpath ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "doctitle")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_doctitle ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "windowtitle")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_windowtitle ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "author")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_author ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "use")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_use ${arg})
|
|
||||||
endif ()
|
|
||||||
elseif (${_state} STREQUAL "version")
|
|
||||||
if (${arg} STREQUAL "PACKAGES")
|
|
||||||
set(_state "packages")
|
|
||||||
elseif (${arg} STREQUAL "FILES")
|
|
||||||
set(_state "files")
|
|
||||||
elseif (${arg} STREQUAL "SOURCEPATH")
|
|
||||||
set(_state "sourcepath")
|
|
||||||
elseif (${arg} STREQUAL "CLASSPATH")
|
|
||||||
set(_state "classpath")
|
|
||||||
elseif (${arg} STREQUAL "INSTALLPATH")
|
|
||||||
set(_state "installpath")
|
|
||||||
elseif (${arg} STREQUAL "DOCTITLE")
|
|
||||||
set(_state "doctitle")
|
|
||||||
elseif (${arg} STREQUAL "WINDOWTITLE")
|
|
||||||
set(_state "windowtitle")
|
|
||||||
elseif (${arg} STREQUAL "AUTHOR")
|
|
||||||
set(_state "author")
|
|
||||||
elseif (${arg} STREQUAL "USE")
|
|
||||||
set(_state "use")
|
|
||||||
elseif (${arg} STREQUAL "VERSION")
|
|
||||||
set(_state "version")
|
|
||||||
else ()
|
|
||||||
set(_javadoc_version ${arg})
|
|
||||||
endif ()
|
|
||||||
endif (${_state} STREQUAL "package")
|
|
||||||
endforeach (arg ${ARGN})
|
|
||||||
|
|
||||||
set(_javadoc_builddir ${CMAKE_CURRENT_BINARY_DIR}/javadoc/${_target})
|
|
||||||
set(_javadoc_options -d ${_javadoc_builddir})
|
|
||||||
|
|
||||||
if (_javadoc_sourcepath)
|
|
||||||
set(_start TRUE)
|
|
||||||
foreach(_path ${_javadoc_sourcepath})
|
|
||||||
if (_start)
|
|
||||||
set(_sourcepath ${_path})
|
|
||||||
set(_start FALSE)
|
|
||||||
else (_start)
|
|
||||||
set(_sourcepath ${_sourcepath}:${_path})
|
|
||||||
endif (_start)
|
|
||||||
endforeach(_path ${_javadoc_sourcepath})
|
|
||||||
set(_javadoc_options ${_javadoc_options} -sourcepath ${_sourcepath})
|
|
||||||
endif (_javadoc_sourcepath)
|
|
||||||
|
|
||||||
if (_javadoc_classpath)
|
|
||||||
set(_start TRUE)
|
|
||||||
foreach(_path ${_javadoc_classpath})
|
|
||||||
if (_start)
|
|
||||||
set(_classpath ${_path})
|
|
||||||
set(_start FALSE)
|
|
||||||
else (_start)
|
|
||||||
set(_classpath ${_classpath}:${_path})
|
|
||||||
endif (_start)
|
|
||||||
endforeach(_path ${_javadoc_classpath})
|
|
||||||
set(_javadoc_options ${_javadoc_options} -classpath "${_classpath}")
|
|
||||||
endif (_javadoc_classpath)
|
|
||||||
|
|
||||||
if (_javadoc_doctitle)
|
|
||||||
set(_javadoc_options ${_javadoc_options} -doctitle '${_javadoc_doctitle}')
|
|
||||||
endif (_javadoc_doctitle)
|
|
||||||
|
|
||||||
if (_javadoc_windowtitle)
|
|
||||||
set(_javadoc_options ${_javadoc_options} -windowtitle '${_javadoc_windowtitle}')
|
|
||||||
endif (_javadoc_windowtitle)
|
|
||||||
|
|
||||||
if (_javadoc_author)
|
|
||||||
set(_javadoc_options ${_javadoc_options} -author)
|
|
||||||
endif (_javadoc_author)
|
|
||||||
|
|
||||||
if (_javadoc_use)
|
|
||||||
set(_javadoc_options ${_javadoc_options} -use)
|
|
||||||
endif (_javadoc_use)
|
|
||||||
|
|
||||||
if (_javadoc_version)
|
|
||||||
set(_javadoc_options ${_javadoc_options} -version)
|
|
||||||
endif (_javadoc_version)
|
|
||||||
|
|
||||||
add_custom_target(${_target}_javadoc ALL
|
|
||||||
COMMAND ${Java_JAVADOC_EXECUTABLE} ${_javadoc_options}
|
|
||||||
${_javadoc_files}
|
|
||||||
${_javadoc_packages}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
DIRECTORY ${_javadoc_builddir}
|
|
||||||
DESTINATION ${_javadoc_installpath}
|
|
||||||
)
|
|
||||||
endfunction(create_javadoc)
|
|
@ -1,52 +0,0 @@
|
|||||||
#
|
|
||||||
# This script create a list of compiled Java class files to be added to a
|
|
||||||
# jar file. This avoids including cmake files which get created in the
|
|
||||||
# binary directory.
|
|
||||||
#
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
if (CMAKE_JAVA_CLASS_OUTPUT_PATH)
|
|
||||||
if (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
|
|
||||||
|
|
||||||
set(_JAVA_GLOBBED_FILES)
|
|
||||||
if (CMAKE_JAR_CLASSES_PREFIX)
|
|
||||||
foreach(JAR_CLASS_PREFIX ${CMAKE_JAR_CLASSES_PREFIX})
|
|
||||||
message(STATUS "JAR_CLASS_PREFIX: ${JAR_CLASS_PREFIX}")
|
|
||||||
|
|
||||||
file(GLOB_RECURSE _JAVA_GLOBBED_TMP_FILES "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${JAR_CLASS_PREFIX}/*.class")
|
|
||||||
if (_JAVA_GLOBBED_TMP_FILES)
|
|
||||||
list(APPEND _JAVA_GLOBBED_FILES ${_JAVA_GLOBBED_TMP_FILES})
|
|
||||||
endif (_JAVA_GLOBBED_TMP_FILES)
|
|
||||||
endforeach(JAR_CLASS_PREFIX ${CMAKE_JAR_CLASSES_PREFIX})
|
|
||||||
else()
|
|
||||||
file(GLOB_RECURSE _JAVA_GLOBBED_FILES "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/*.class")
|
|
||||||
endif (CMAKE_JAR_CLASSES_PREFIX)
|
|
||||||
|
|
||||||
set(_JAVA_CLASS_FILES)
|
|
||||||
# file(GLOB_RECURSE foo RELATIVE) is broken so we need this.
|
|
||||||
foreach(_JAVA_GLOBBED_FILE ${_JAVA_GLOBBED_FILES})
|
|
||||||
file(RELATIVE_PATH _JAVA_CLASS_FILE ${CMAKE_JAVA_CLASS_OUTPUT_PATH} ${_JAVA_GLOBBED_FILE})
|
|
||||||
set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES}${_JAVA_CLASS_FILE}\n)
|
|
||||||
endforeach(_JAVA_GLOBBED_FILE ${_JAVA_GLOBBED_FILES})
|
|
||||||
|
|
||||||
# write to file
|
|
||||||
file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist ${_JAVA_CLASS_FILES})
|
|
||||||
|
|
||||||
else (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
|
|
||||||
message(SEND_ERROR "FATAL: Java class output path doesn't exist")
|
|
||||||
endif (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
|
|
||||||
else (CMAKE_JAVA_CLASS_OUTPUT_PATH)
|
|
||||||
message(SEND_ERROR "FATAL: Can't find CMAKE_JAVA_CLASS_OUTPUT_PATH")
|
|
||||||
endif (CMAKE_JAVA_CLASS_OUTPUT_PATH)
|
|
@ -1,32 +0,0 @@
|
|||||||
#
|
|
||||||
# Helper script for UseJava.cmake
|
|
||||||
#
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
if (UNIX AND _JAVA_TARGET_OUTPUT_LINK)
|
|
||||||
if (_JAVA_TARGET_OUTPUT_NAME)
|
|
||||||
find_program(LN_EXECUTABLE
|
|
||||||
NAMES
|
|
||||||
ln
|
|
||||||
)
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${LN_EXECUTABLE} -sf "${_JAVA_TARGET_OUTPUT_NAME}" "${_JAVA_TARGET_OUTPUT_LINK}"
|
|
||||||
WORKING_DIRECTORY ${_JAVA_TARGET_DIR}
|
|
||||||
)
|
|
||||||
else (_JAVA_TARGET_OUTPUT_NAME)
|
|
||||||
message(SEND_ERROR "FATAL: Can't find _JAVA_TARGET_OUTPUT_NAME")
|
|
||||||
endif (_JAVA_TARGET_OUTPUT_NAME)
|
|
||||||
endif (UNIX AND _JAVA_TARGET_OUTPUT_LINK)
|
|
15
default.nix
15
default.nix
@ -1 +1,14 @@
|
|||||||
(import packages/nix/flake-compat.nix).defaultNix
|
(
|
||||||
|
import
|
||||||
|
(
|
||||||
|
let
|
||||||
|
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||||
|
in
|
||||||
|
fetchTarball {
|
||||||
|
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||||
|
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
{src = ./.;}
|
||||||
|
)
|
||||||
|
.defaultNix
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
POLYMC(1)
|
|
||||||
==========
|
|
||||||
:doctype: manpage
|
|
||||||
|
|
||||||
|
|
||||||
NAME
|
|
||||||
----
|
|
||||||
polymc - a launcher and instance manager for Minecraft.
|
|
||||||
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
--------
|
|
||||||
*polymc* ['OPTIONS']
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
-----------
|
|
||||||
PolyMC is a custom launcher for Minecraft that allows you to easily manage
|
|
||||||
multiple installations of Minecraft at once. It also allows you to easily
|
|
||||||
install and remove mods by simply dragging and dropping.
|
|
||||||
Here are the current features of PolyMC.
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
-------
|
|
||||||
*-d, --dir*='DIRECTORY'::
|
|
||||||
Use 'DIRECTORY' as the PolyMC root.
|
|
||||||
|
|
||||||
*-l, --launch*='INSTANCE_ID'::
|
|
||||||
Launch the instance specified by 'INSTANCE_ID'.
|
|
||||||
|
|
||||||
*--alive*::
|
|
||||||
Write a small 'live.check' file after PolyMC starts.
|
|
||||||
|
|
||||||
*-h, --help*::
|
|
||||||
Display help text and exit.
|
|
||||||
|
|
||||||
*-v, --version*::
|
|
||||||
Display program version and exit.
|
|
||||||
*-a, --profile*='PROFILE'::
|
|
||||||
Use the account specified by 'PROFILE' (only valid in combination with --launch).
|
|
||||||
|
|
||||||
EXIT STATUS
|
|
||||||
-----------
|
|
||||||
*0*::
|
|
||||||
Success
|
|
||||||
|
|
||||||
*1*::
|
|
||||||
Failure (syntax or usage error; configuration error; unexpected error).
|
|
||||||
|
|
||||||
BUGS
|
|
||||||
----
|
|
||||||
<https://github.com/PolyMC/PolyMC/issues>
|
|
||||||
|
|
||||||
RESOURCES
|
|
||||||
---------
|
|
||||||
GitHub: <https://github.com/PolyMC/PolyMC>
|
|
||||||
|
|
||||||
Main website: <https://polymc.org>
|
|
||||||
|
|
||||||
AUTHORS
|
|
||||||
-------
|
|
||||||
peterix <peterix@gmail.com>
|
|
||||||
|
|
||||||
swurl <swurl@swurl.xyz>
|
|
||||||
|
|
||||||
// vim: syntax=asciidoc
|
|
155
flake.lock
generated
155
flake.lock
generated
@ -3,11 +3,11 @@
|
|||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1641205782,
|
"lastModified": 1696426674,
|
||||||
"narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=",
|
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7",
|
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -16,13 +16,34 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils": {
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1638122382,
|
"lastModified": 1698882062,
|
||||||
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
|
"narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "8c9fa2545007b49a5db5f650ae91f227672c3877",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1685518550,
|
||||||
|
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
|
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -31,61 +52,143 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"pre-commit-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1660459072,
|
||||||
|
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"libnbtplusplus": {
|
"libnbtplusplus": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1591558203,
|
"lastModified": 1690036783,
|
||||||
"narHash": "sha256-QgvNvaoFflCXEPCCFBCeZvYTpuiwScBG7EosUgFwFNQ=",
|
"narHash": "sha256-A5kTgICnx+Qdq3Fir/bKTfdTt/T1NQP2SC+nhN1ENug=",
|
||||||
"owner": "multimc",
|
"owner": "PrismLauncher",
|
||||||
"repo": "libnbtplusplus",
|
"repo": "libnbtplusplus",
|
||||||
"rev": "dc72a20b7efd304d12af2025223fad07b4b78464",
|
"rev": "a5e8fd52b8bf4ab5d5bcc042b2a247867589985f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "multimc",
|
"owner": "PrismLauncher",
|
||||||
"repo": "libnbtplusplus",
|
"repo": "libnbtplusplus",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nix-filter": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694857738,
|
||||||
|
"narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "nix-filter",
|
||||||
|
"rev": "41fd48e00c22b4ced525af521ead8792402de0ea",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "nix-filter",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1641528457,
|
"lastModified": 1699094435,
|
||||||
"narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=",
|
"narHash": "sha256-YLZ5/KKZ1PyLrm2MO8UxRe4H3M0/oaYqNhSlq6FDeeA=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ff377a78794d412a35245e05428c8f95fef3951f",
|
"rev": "9d5d25bbfe8c0297ebe85324addcb5020ed1a454",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"dir": "lib",
|
||||||
|
"lastModified": 1698611440,
|
||||||
|
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"dir": "lib",
|
||||||
|
"owner": "NixOS",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"quazip": {
|
"pre-commit-hooks": {
|
||||||
"flake": false,
|
"inputs": {
|
||||||
|
"flake-compat": [
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-stable": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1633895098,
|
"lastModified": 1698852633,
|
||||||
"narHash": "sha256-+Of0M2IAoTf1CyC0teCpsyurv6xfqiBo84V49dSeNTA=",
|
"narHash": "sha256-Hsc/cCHud8ZXLvmm8pxrXpuaPEeNaaUttaCvtdX/Wug=",
|
||||||
"owner": "multimc",
|
"owner": "cachix",
|
||||||
"repo": "quazip",
|
"repo": "pre-commit-hooks.nix",
|
||||||
"rev": "b1a72ac0bb5a732bf887a535ab75c6f9bedb6b6b",
|
"rev": "dec10399e5b56aa95fcd530e0338be72ad6462a0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "multimc",
|
"owner": "cachix",
|
||||||
"repo": "quazip",
|
"repo": "pre-commit-hooks.nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"flake-utils": "flake-utils",
|
"flake-parts": "flake-parts",
|
||||||
"libnbtplusplus": "libnbtplusplus",
|
"libnbtplusplus": "libnbtplusplus",
|
||||||
|
"nix-filter": "nix-filter",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"quazip": "quazip"
|
"pre-commit-hooks": "pre-commit-hooks"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
87
flake.nix
87
flake.nix
@ -1,55 +1,44 @@
|
|||||||
{
|
{
|
||||||
description = "PolyMC flake";
|
description = "A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once (Fork of MultiMC)";
|
||||||
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
|
||||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
inputs = {
|
||||||
inputs.flake-compat = {
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
url = "github:edolstra/flake-compat";
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
flake = false;
|
nix-filter.url = "github:numtide/nix-filter";
|
||||||
};
|
pre-commit-hooks = {
|
||||||
inputs.libnbtplusplus = {
|
url = "github:cachix/pre-commit-hooks.nix";
|
||||||
url = "github:multimc/libnbtplusplus";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
flake = false;
|
inputs.nixpkgs-stable.follows = "nixpkgs";
|
||||||
};
|
inputs.flake-compat.follows = "flake-compat";
|
||||||
inputs.quazip = {
|
};
|
||||||
url = "github:multimc/quazip";
|
flake-compat = {
|
||||||
flake = false;
|
url = "github:edolstra/flake-compat";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
libnbtplusplus = {
|
||||||
|
url = "github:PrismLauncher/libnbtplusplus";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
|
outputs = {
|
||||||
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
|
flake-parts,
|
||||||
let
|
pre-commit-hooks,
|
||||||
pkgs = import nixpkgs {
|
...
|
||||||
inherit system;
|
} @ inputs:
|
||||||
};
|
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||||
|
imports = [
|
||||||
|
pre-commit-hooks.flakeModule
|
||||||
|
|
||||||
packages = {
|
./nix/dev.nix
|
||||||
polymc = pkgs.libsForQt5.callPackage ./packages/nix/polymc {
|
./nix/distribution.nix
|
||||||
inherit self;
|
];
|
||||||
submoduleQuazip = quazip;
|
|
||||||
submoduleNbt = libnbtplusplus;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# 'nix flake check' fails
|
|
||||||
overlay = (final: prev: rec {
|
|
||||||
polymc = prev.libsForQt5.callPackage ./packages/nix/polymc {
|
|
||||||
inherit self;
|
|
||||||
submoduleQuazip = quazip;
|
|
||||||
submoduleNbt = libnbtplusplus;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
apps = {
|
systems = [
|
||||||
polymc = flake-utils.lib.mkApp {
|
"x86_64-linux"
|
||||||
name = "polymc";
|
"aarch64-linux"
|
||||||
drv = packages.polymc;
|
"x86_64-darwin"
|
||||||
};
|
"aarch64-darwin"
|
||||||
};
|
];
|
||||||
in
|
};
|
||||||
{
|
|
||||||
inherit packages overlay apps;
|
|
||||||
defaultPackage = packages.polymc;
|
|
||||||
defaultApp = apps.polymc;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
22
flatpak/libdecor.json
Normal file
22
flatpak/libdecor.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "libdecor",
|
||||||
|
"buildsystem": "meson",
|
||||||
|
"config-opts": [
|
||||||
|
"-Ddemo=false"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitlab.freedesktop.org/libdecor/libdecor.git",
|
||||||
|
"commit": "73260393a97291c887e1074ab7f318e031be0ac6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patch",
|
||||||
|
"path": "patches/weird_libdecor.patch"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cleanup": [
|
||||||
|
"/include",
|
||||||
|
"/lib/pkgconfig"
|
||||||
|
]
|
||||||
|
}
|
158
flatpak/org.prismlauncher.PrismLauncher.yml
Normal file
158
flatpak/org.prismlauncher.PrismLauncher.yml
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
id: org.prismlauncher.PrismLauncher
|
||||||
|
runtime: org.kde.Platform
|
||||||
|
runtime-version: "5.15-22.08"
|
||||||
|
sdk: org.kde.Sdk
|
||||||
|
sdk-extensions:
|
||||||
|
- org.freedesktop.Sdk.Extension.openjdk17
|
||||||
|
- org.freedesktop.Sdk.Extension.openjdk8
|
||||||
|
|
||||||
|
command: prismlauncher
|
||||||
|
finish-args:
|
||||||
|
- --share=ipc
|
||||||
|
- --socket=x11
|
||||||
|
- --socket=wayland
|
||||||
|
- --device=all
|
||||||
|
- --share=network
|
||||||
|
- --socket=pulseaudio
|
||||||
|
# for Discord RPC mods
|
||||||
|
- --filesystem=xdg-run/app/com.discordapp.Discord:create
|
||||||
|
# Mod drag&drop
|
||||||
|
- --filesystem=xdg-download:ro
|
||||||
|
# FTBApp import
|
||||||
|
- --filesystem=~/.ftba:ro
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
- /lib/libGLU*
|
||||||
|
|
||||||
|
modules:
|
||||||
|
# Might be needed by some Controller mods (see https://github.com/isXander/Controlify/issues/31)
|
||||||
|
- shared-modules/libusb/libusb.json
|
||||||
|
|
||||||
|
# Needed for proper Wayland support
|
||||||
|
- libdecor.json
|
||||||
|
|
||||||
|
- name: prismlauncher
|
||||||
|
buildsystem: cmake-ninja
|
||||||
|
builddir: true
|
||||||
|
config-opts:
|
||||||
|
- -DLauncher_BUILD_PLATFORM=flatpak
|
||||||
|
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
- -DLauncher_QT_VERSION_MAJOR=5
|
||||||
|
build-options:
|
||||||
|
env:
|
||||||
|
JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17
|
||||||
|
JAVA_COMPILER: /usr/lib/sdk/openjdk17/jvm/openjdk-17/bin/javac
|
||||||
|
sources:
|
||||||
|
- type: dir
|
||||||
|
path: ../
|
||||||
|
|
||||||
|
- name: openjdk
|
||||||
|
buildsystem: simple
|
||||||
|
build-commands:
|
||||||
|
- mkdir -p /app/jdk/
|
||||||
|
- /usr/lib/sdk/openjdk17/install.sh
|
||||||
|
- mv /app/jre /app/jdk/17
|
||||||
|
- /usr/lib/sdk/openjdk8/install.sh
|
||||||
|
- mv /app/jre /app/jdk/8
|
||||||
|
cleanup:
|
||||||
|
- /jre
|
||||||
|
|
||||||
|
- name: glfw
|
||||||
|
buildsystem: cmake-ninja
|
||||||
|
config-opts:
|
||||||
|
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||||
|
- -DBUILD_SHARED_LIBS:BOOL=ON
|
||||||
|
- -DGLFW_USE_WAYLAND=ON
|
||||||
|
sources:
|
||||||
|
- type: git
|
||||||
|
url: https://github.com/glfw/glfw.git
|
||||||
|
commit: 3fa2360720eeba1964df3c0ecf4b5df8648a8e52
|
||||||
|
- type: patch
|
||||||
|
path: patches/0003-Don-t-crash-on-calls-to-focus-or-icon.patch
|
||||||
|
- type: patch
|
||||||
|
path: patches/0005-Add-warning-about-being-an-unofficial-patch.patch
|
||||||
|
- type: patch
|
||||||
|
path: patches/0007-Platform-Prefer-Wayland-over-X11.patch
|
||||||
|
cleanup:
|
||||||
|
- /include
|
||||||
|
- /lib/cmake
|
||||||
|
- /lib/pkgconfig
|
||||||
|
|
||||||
|
- name: xrandr
|
||||||
|
buildsystem: autotools
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
url: https://xorg.freedesktop.org/archive/individual/app/xrandr-1.5.2.tar.xz
|
||||||
|
sha256: c8bee4790d9058bacc4b6246456c58021db58a87ddda1a9d0139bf5f18f1f240
|
||||||
|
x-checker-data:
|
||||||
|
type: anitya
|
||||||
|
project-id: 14957
|
||||||
|
stable-only: true
|
||||||
|
url-template: https://xorg.freedesktop.org/archive/individual/app/xrandr-$version.tar.xz
|
||||||
|
cleanup:
|
||||||
|
- /share/man
|
||||||
|
- /bin/xkeystone
|
||||||
|
|
||||||
|
- name: gamemode
|
||||||
|
buildsystem: meson
|
||||||
|
config-opts:
|
||||||
|
- -Dwith-sd-bus-provider=no-daemon
|
||||||
|
- -Dwith-examples=false
|
||||||
|
post-install:
|
||||||
|
# gamemoderun is installed for users who want to use wrapper commands
|
||||||
|
# post-install is running inside the build dir, we need it from the source though
|
||||||
|
- install -Dm755 ../data/gamemoderun -t /app/bin
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
archive-type: tar-gzip
|
||||||
|
url: https://api.github.com/repos/FeralInteractive/gamemode/tarball/1.7
|
||||||
|
sha256: 57ce73ba605d1cf12f8d13725006a895182308d93eba0f69f285648449641803
|
||||||
|
x-checker-data:
|
||||||
|
type: json
|
||||||
|
url: https://api.github.com/repos/FeralInteractive/gamemode/releases/latest
|
||||||
|
version-query: .tag_name
|
||||||
|
url-query: .tarball_url
|
||||||
|
timestamp-query: .published_at
|
||||||
|
cleanup:
|
||||||
|
- /include
|
||||||
|
- /lib/pkgconfig
|
||||||
|
- /lib/libgamemodeauto.a
|
||||||
|
|
||||||
|
- name: glxinfo
|
||||||
|
buildsystem: meson
|
||||||
|
config-opts:
|
||||||
|
- --bindir=/app/mesa-demos
|
||||||
|
- -Degl=disabled
|
||||||
|
- -Dglut=disabled
|
||||||
|
- -Dosmesa=disabled
|
||||||
|
- -Dvulkan=disabled
|
||||||
|
- -Dwayland=disabled
|
||||||
|
post-install:
|
||||||
|
- mv -v /app/mesa-demos/glxinfo /app/bin
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
url: https://archive.mesa3d.org/demos/mesa-demos-9.0.0.tar.xz
|
||||||
|
sha256: 3046a3d26a7b051af7ebdd257a5f23bfeb160cad6ed952329cdff1e9f1ed496b
|
||||||
|
x-checker-data:
|
||||||
|
type: anitya
|
||||||
|
project-id: 16781
|
||||||
|
stable-only: true
|
||||||
|
url-template: https://archive.mesa3d.org/demos/mesa-demos-$version.tar.xz
|
||||||
|
cleanup:
|
||||||
|
- /include
|
||||||
|
- /mesa-demos
|
||||||
|
- /share
|
||||||
|
modules:
|
||||||
|
- shared-modules/glu/glu-9.json
|
||||||
|
|
||||||
|
- name: enhance
|
||||||
|
buildsystem: simple
|
||||||
|
build-commands:
|
||||||
|
- install -Dm755 prime-run /app/bin/prime-run
|
||||||
|
- mv /app/bin/prismlauncher /app/bin/prismrun
|
||||||
|
- install -Dm755 prismlauncher /app/bin/prismlauncher
|
||||||
|
sources:
|
||||||
|
- type: file
|
||||||
|
path: prime-run
|
||||||
|
- type: file
|
||||||
|
path: prismlauncher
|
@ -0,0 +1,24 @@
|
|||||||
|
diff --git a/src/wl_window.c b/src/wl_window.c
|
||||||
|
index 52d3b9eb..4ac4eb5d 100644
|
||||||
|
--- a/src/wl_window.c
|
||||||
|
+++ b/src/wl_window.c
|
||||||
|
@@ -2117,8 +2117,7 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
|
||||||
|
void _glfwSetWindowIconWayland(_GLFWwindow* window,
|
||||||
|
int count, const GLFWimage* images)
|
||||||
|
{
|
||||||
|
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
|
- "Wayland: The platform does not support setting the window icon");
|
||||||
|
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
|
@@ -2361,8 +2360,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
|
||||||
|
|
||||||
|
void _glfwFocusWindowWayland(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
|
||||||
|
- "Wayland: The platform does not support setting the input focus");
|
||||||
|
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
|
@ -0,0 +1,17 @@
|
|||||||
|
diff --git a/src/init.c b/src/init.c
|
||||||
|
index 06dbb3f2..a7c6da86 100644
|
||||||
|
--- a/src/init.c
|
||||||
|
+++ b/src/init.c
|
||||||
|
@@ -449,6 +449,12 @@ GLFWAPI int glfwInit(void)
|
||||||
|
_glfw.initialized = GLFW_TRUE;
|
||||||
|
|
||||||
|
glfwDefaultWindowHints();
|
||||||
|
+
|
||||||
|
+ fprintf(stderr, "!!! Patched GLFW from https://github.com/Admicos/minecraft-wayland\n"
|
||||||
|
+ "!!! If any issues with the window, or some issues with rendering, occur, "
|
||||||
|
+ "first try with the built-in GLFW, and if that solves the issue, report there first.\n"
|
||||||
|
+ "!!! Use outside Minecraft is untested, and things might break.\n");
|
||||||
|
+
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
20
flatpak/patches/0007-Platform-Prefer-Wayland-over-X11.patch
Normal file
20
flatpak/patches/0007-Platform-Prefer-Wayland-over-X11.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
diff --git a/src/platform.c b/src/platform.c
|
||||||
|
index c5966ae7..3e7442f9 100644
|
||||||
|
--- a/src/platform.c
|
||||||
|
+++ b/src/platform.c
|
||||||
|
@@ -49,12 +49,12 @@ static const struct
|
||||||
|
#if defined(_GLFW_COCOA)
|
||||||
|
{ GLFW_PLATFORM_COCOA, _glfwConnectCocoa },
|
||||||
|
#endif
|
||||||
|
-#if defined(_GLFW_X11)
|
||||||
|
- { GLFW_PLATFORM_X11, _glfwConnectX11 },
|
||||||
|
-#endif
|
||||||
|
#if defined(_GLFW_WAYLAND)
|
||||||
|
{ GLFW_PLATFORM_WAYLAND, _glfwConnectWayland },
|
||||||
|
#endif
|
||||||
|
+#if defined(_GLFW_X11)
|
||||||
|
+ { GLFW_PLATFORM_X11, _glfwConnectX11 },
|
||||||
|
+#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
|
40
flatpak/patches/weird_libdecor.patch
Normal file
40
flatpak/patches/weird_libdecor.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
diff --git a/src/libdecor.c b/src/libdecor.c
|
||||||
|
index a9c1106..1aa38b3 100644
|
||||||
|
--- a/src/libdecor.c
|
||||||
|
+++ b/src/libdecor.c
|
||||||
|
@@ -1391,22 +1391,32 @@ calculate_priority(const struct libdecor_plugin_description *plugin_description)
|
||||||
|
static bool
|
||||||
|
check_symbol_conflicts(const struct libdecor_plugin_description *plugin_description)
|
||||||
|
{
|
||||||
|
+ bool ret = true;
|
||||||
|
char * const *symbol;
|
||||||
|
+ void* main_prog = dlopen(NULL, RTLD_LAZY);
|
||||||
|
+ if (!main_prog) {
|
||||||
|
+ fprintf(stderr, "Plugin \"%s\" couldn't check conflicting symbols: \"%s\".\n",
|
||||||
|
+ plugin_description->description, dlerror());
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
symbol = plugin_description->conflicting_symbols;
|
||||||
|
while (*symbol) {
|
||||||
|
dlerror();
|
||||||
|
- dlsym (RTLD_DEFAULT, *symbol);
|
||||||
|
+ dlsym (main_prog, *symbol);
|
||||||
|
if (!dlerror()) {
|
||||||
|
fprintf(stderr, "Plugin \"%s\" uses conflicting symbol \"%s\".\n",
|
||||||
|
plugin_description->description, *symbol);
|
||||||
|
- return false;
|
||||||
|
+ ret = false;
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol++;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return true;
|
||||||
|
+ dlclose(main_prog);
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct plugin_loader *
|
4
flatpak/prime-run
Normal file
4
flatpak/prime-run
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia
|
||||||
|
exec "$@"
|
11
flatpak/prismlauncher
Normal file
11
flatpak/prismlauncher
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# discord RPC
|
||||||
|
for i in {0..9}; do
|
||||||
|
test -S "$XDG_RUNTIME_DIR"/discord-ipc-"$i" || ln -sf {app/com.discordapp.Discord,"$XDG_RUNTIME_DIR"}/discord-ipc-"$i";
|
||||||
|
done
|
||||||
|
|
||||||
|
export PATH="${PATH}${PATH:+:}/usr/lib/extensions/vulkan/gamescope/bin:/usr/lib/extensions/vulkan/MangoHud/bin"
|
||||||
|
export VK_LAYER_PATH="/usr/lib/extensions/vulkan/share/vulkan/implicit_layer.d/"
|
||||||
|
|
||||||
|
exec /app/bin/prismrun "$@"
|
1
flatpak/shared-modules
Submodule
1
flatpak/shared-modules
Submodule
Submodule flatpak/shared-modules added at 45094ca570
6
garnix.yaml
Normal file
6
garnix.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
builds:
|
||||||
|
exclude: []
|
||||||
|
include:
|
||||||
|
- "checks.x86_64-linux.*"
|
||||||
|
- "devShells.*.*"
|
||||||
|
- "packages.*.*"
|
File diff suppressed because it is too large
Load Diff
@ -1,17 +1,54 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (C) 2022 Tayou <git@tayou.org>
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <memory>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFlag>
|
#include <QFlag>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QDateTime>
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <updater/GoUpdate.h>
|
#include <memory>
|
||||||
|
|
||||||
#include <BaseInstance.h>
|
#include <BaseInstance.h>
|
||||||
|
|
||||||
#include "minecraft/launch/MinecraftServerTarget.h"
|
#include "minecraft/launch/MinecraftServerTarget.h"
|
||||||
|
#include "ui/themes/CatPack.h"
|
||||||
|
|
||||||
class LaunchController;
|
class LaunchController;
|
||||||
class LocalPeer;
|
class LocalPeer;
|
||||||
@ -27,85 +64,73 @@ class AccountList;
|
|||||||
class IconList;
|
class IconList;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class JavaInstallList;
|
class JavaInstallList;
|
||||||
class UpdateChecker;
|
class ExternalUpdater;
|
||||||
class BaseProfilerFactory;
|
class BaseProfilerFactory;
|
||||||
class BaseDetachedToolFactory;
|
class BaseDetachedToolFactory;
|
||||||
class TranslationsModel;
|
class TranslationsModel;
|
||||||
class ITheme;
|
class ITheme;
|
||||||
class MCEditTool;
|
class MCEditTool;
|
||||||
|
class ThemeManager;
|
||||||
|
class IconTheme;
|
||||||
|
|
||||||
namespace Meta {
|
namespace Meta {
|
||||||
class Index;
|
class Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(APPLICATION)
|
#if defined(APPLICATION)
|
||||||
#undef APPLICATION
|
#undef APPLICATION
|
||||||
#endif
|
#endif
|
||||||
#define APPLICATION (static_cast<Application *>(QCoreApplication::instance()))
|
#define APPLICATION (static_cast<Application*>(QCoreApplication::instance()))
|
||||||
|
|
||||||
class Application : public QApplication
|
class Application : public QApplication {
|
||||||
{
|
|
||||||
// friends for the purpose of limiting access to deprecated stuff
|
// friends for the purpose of limiting access to deprecated stuff
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum Status {
|
enum Status { StartingUp, Failed, Succeeded, Initialized };
|
||||||
StartingUp,
|
|
||||||
Failed,
|
|
||||||
Succeeded,
|
|
||||||
Initialized
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
enum Capability {
|
||||||
Application(int &argc, char **argv);
|
None = 0,
|
||||||
|
|
||||||
|
SupportsMSA = 1 << 0,
|
||||||
|
SupportsFlame = 1 << 1,
|
||||||
|
SupportsGameMode = 1 << 2,
|
||||||
|
SupportsMangoHud = 1 << 3,
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(Capabilities, Capability)
|
||||||
|
|
||||||
|
public:
|
||||||
|
Application(int& argc, char** argv);
|
||||||
virtual ~Application();
|
virtual ~Application();
|
||||||
|
|
||||||
std::shared_ptr<SettingsObject> settings() const {
|
bool event(QEvent* event) override;
|
||||||
return m_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 timeSinceStart() const {
|
std::shared_ptr<SettingsObject> settings() const { return m_settings; }
|
||||||
return startTime.msecsTo(QDateTime::currentDateTime());
|
|
||||||
}
|
qint64 timeSinceStart() const { return startTime.msecsTo(QDateTime::currentDateTime()); }
|
||||||
|
|
||||||
QIcon getThemedIcon(const QString& name);
|
QIcon getThemedIcon(const QString& name);
|
||||||
|
|
||||||
void setIconTheme(const QString& name);
|
ThemeManager* themeManager() { return m_themeManager.get(); }
|
||||||
|
|
||||||
std::vector<ITheme *> getValidApplicationThemes();
|
shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; }
|
||||||
|
|
||||||
void setApplicationTheme(const QString& name, bool initial);
|
void triggerUpdateCheck();
|
||||||
|
|
||||||
shared_qobject_ptr<UpdateChecker> updateChecker() {
|
|
||||||
return m_updateChecker;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TranslationsModel> translations();
|
std::shared_ptr<TranslationsModel> translations();
|
||||||
|
|
||||||
std::shared_ptr<JavaInstallList> javalist();
|
std::shared_ptr<JavaInstallList> javalist();
|
||||||
|
|
||||||
std::shared_ptr<InstanceList> instances() const {
|
std::shared_ptr<InstanceList> instances() const { return m_instances; }
|
||||||
return m_instances;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IconList> icons() const {
|
std::shared_ptr<IconList> icons() const { return m_icons; }
|
||||||
return m_icons;
|
|
||||||
}
|
|
||||||
|
|
||||||
MCEditTool *mcedit() const {
|
MCEditTool* mcedit() const { return m_mcedit.get(); }
|
||||||
return m_mcedit.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_qobject_ptr<AccountList> accounts() const {
|
shared_qobject_ptr<AccountList> accounts() const { return m_accounts; }
|
||||||
return m_accounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status status() const {
|
Status status() const { return m_status; }
|
||||||
return m_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QMap<QString, std::shared_ptr<BaseProfilerFactory>> &profilers() const {
|
const QMap<QString, std::shared_ptr<BaseProfilerFactory>>& profilers() const { return m_profilers; }
|
||||||
return m_profilers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
|
void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
|
||||||
|
|
||||||
@ -115,67 +140,98 @@ public:
|
|||||||
|
|
||||||
shared_qobject_ptr<Meta::Index> metadataIndex();
|
shared_qobject_ptr<Meta::Index> metadataIndex();
|
||||||
|
|
||||||
QString getJarsPath();
|
void updateCapabilities();
|
||||||
|
|
||||||
|
void detectLibraries();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Finds and returns the full path to a jar file.
|
||||||
|
* Returns a null-string if it could not be found.
|
||||||
|
*/
|
||||||
|
QString getJarPath(QString jarFile);
|
||||||
|
|
||||||
|
QString getMSAClientID();
|
||||||
|
QString getFlameAPIKey();
|
||||||
|
QString getModrinthAPIToken();
|
||||||
|
QString getUserAgent();
|
||||||
|
QString getUserAgentUncached();
|
||||||
|
|
||||||
/// this is the root of the 'installation'. Used for automatic updates
|
/// this is the root of the 'installation'. Used for automatic updates
|
||||||
const QString &root() {
|
const QString& root() { return m_rootPath; }
|
||||||
return m_rootPath;
|
|
||||||
}
|
/// the data path the application is using
|
||||||
|
const QString& dataRoot() { return m_dataPath; }
|
||||||
|
|
||||||
|
bool isPortable() { return m_portable; }
|
||||||
|
|
||||||
|
const Capabilities capabilities() { return m_capabilities; }
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Opens a json file using either a system default editor, or, if not empty, the editor
|
* Opens a json file using either a system default editor, or, if not empty, the editor
|
||||||
* specified in the settings
|
* specified in the settings
|
||||||
*/
|
*/
|
||||||
bool openJsonEditor(const QString &filename);
|
bool openJsonEditor(const QString& filename);
|
||||||
|
|
||||||
InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString());
|
InstanceWindow* showInstanceWindow(InstancePtr instance, QString page = QString());
|
||||||
MainWindow *showMainWindow(bool minimized = false);
|
MainWindow* showMainWindow(bool minimized = false);
|
||||||
|
|
||||||
void updateIsRunning(bool running);
|
void updateIsRunning(bool running);
|
||||||
bool updatesAreAllowed();
|
bool updatesAreAllowed();
|
||||||
|
|
||||||
void ShowGlobalSettings(class QWidget * parent, QString open_page = QString());
|
void ShowGlobalSettings(class QWidget* parent, QString open_page = QString());
|
||||||
|
|
||||||
signals:
|
int suitableMaxMem();
|
||||||
|
|
||||||
|
bool updaterEnabled();
|
||||||
|
QString updaterBinaryName();
|
||||||
|
|
||||||
|
QUrl normalizeImportUrl(QString const& url);
|
||||||
|
|
||||||
|
signals:
|
||||||
void updateAllowedChanged(bool status);
|
void updateAllowedChanged(bool status);
|
||||||
void globalSettingsAboutToOpen();
|
void globalSettingsAboutToOpen();
|
||||||
void globalSettingsClosed();
|
void globalSettingsClosed();
|
||||||
|
int currentCatChanged(int index);
|
||||||
|
|
||||||
public slots:
|
#ifdef Q_OS_MACOS
|
||||||
bool launch(
|
void clickedOnDock();
|
||||||
InstancePtr instance,
|
#endif
|
||||||
bool online = true,
|
|
||||||
BaseProfilerFactory *profiler = nullptr,
|
public slots:
|
||||||
MinecraftServerTargetPtr serverToJoin = nullptr,
|
bool launch(InstancePtr instance,
|
||||||
MinecraftAccountPtr accountToUse = nullptr
|
bool online = true,
|
||||||
);
|
bool demo = false,
|
||||||
|
MinecraftServerTargetPtr serverToJoin = nullptr,
|
||||||
|
MinecraftAccountPtr accountToUse = nullptr);
|
||||||
bool kill(InstancePtr instance);
|
bool kill(InstancePtr instance);
|
||||||
|
void closeCurrentWindow();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_windowClose();
|
void on_windowClose();
|
||||||
void messageReceived(const QByteArray & message);
|
void messageReceived(const QByteArray& message);
|
||||||
void controllerSucceeded();
|
void controllerSucceeded();
|
||||||
void controllerFailed(const QString & error);
|
void controllerFailed(const QString& error);
|
||||||
void setupWizardFinished(int status);
|
void setupWizardFinished(int status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool handleDataMigration(const QString& currentData, const QString& oldData, const QString& name, const QString& configFile) const;
|
||||||
bool createSetupWizard();
|
bool createSetupWizard();
|
||||||
void performMainStartupAction();
|
void performMainStartupAction();
|
||||||
|
|
||||||
// sets the fatal error message and m_status to Failed.
|
// sets the fatal error message and m_status to Failed.
|
||||||
void showFatalErrorMessage(const QString & title, const QString & content);
|
void showFatalErrorMessage(const QString& title, const QString& content);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addRunningInstance();
|
void addRunningInstance();
|
||||||
void subRunningInstance();
|
void subRunningInstance();
|
||||||
bool shouldExitNow() const;
|
bool shouldExitNow() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QDateTime startTime;
|
QDateTime startTime;
|
||||||
|
|
||||||
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
||||||
|
|
||||||
shared_qobject_ptr<UpdateChecker> m_updateChecker;
|
shared_qobject_ptr<ExternalUpdater> m_updater;
|
||||||
shared_qobject_ptr<AccountList> m_accounts;
|
shared_qobject_ptr<AccountList> m_accounts;
|
||||||
|
|
||||||
shared_qobject_ptr<HttpMetaCache> m_metacache;
|
shared_qobject_ptr<HttpMetaCache> m_metacache;
|
||||||
@ -187,15 +243,21 @@ private:
|
|||||||
std::shared_ptr<JavaInstallList> m_javalist;
|
std::shared_ptr<JavaInstallList> m_javalist;
|
||||||
std::shared_ptr<TranslationsModel> m_translations;
|
std::shared_ptr<TranslationsModel> m_translations;
|
||||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||||
std::map<QString, std::unique_ptr<ITheme>> m_themes;
|
|
||||||
std::unique_ptr<MCEditTool> m_mcedit;
|
std::unique_ptr<MCEditTool> m_mcedit;
|
||||||
QString m_jarsPath;
|
|
||||||
QSet<QString> m_features;
|
QSet<QString> m_features;
|
||||||
|
std::unique_ptr<ThemeManager> m_themeManager;
|
||||||
|
|
||||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||||
|
|
||||||
QString m_rootPath;
|
QString m_rootPath;
|
||||||
|
QString m_dataPath;
|
||||||
Status m_status = Application::StartingUp;
|
Status m_status = Application::StartingUp;
|
||||||
|
Capabilities m_capabilities;
|
||||||
|
bool m_portable = false;
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
// used on Windows to attach the standard IO streams
|
// used on Windows to attach the standard IO streams
|
||||||
@ -204,7 +266,7 @@ private:
|
|||||||
|
|
||||||
// FIXME: attach to instances instead.
|
// FIXME: attach to instances instead.
|
||||||
struct InstanceXtras {
|
struct InstanceXtras {
|
||||||
InstanceWindow * window = nullptr;
|
InstanceWindow* window = nullptr;
|
||||||
shared_qobject_ptr<LaunchController> controller;
|
shared_qobject_ptr<LaunchController> controller;
|
||||||
};
|
};
|
||||||
std::map<QString, InstanceXtras> m_instanceExtras;
|
std::map<QString, InstanceXtras> m_instanceExtras;
|
||||||
@ -215,18 +277,21 @@ private:
|
|||||||
bool m_updateRunning = false;
|
bool m_updateRunning = false;
|
||||||
|
|
||||||
// main window, if any
|
// main window, if any
|
||||||
MainWindow * m_mainWindow = nullptr;
|
MainWindow* m_mainWindow = nullptr;
|
||||||
|
|
||||||
// peer launcher instance connector - used to implement single instance launcher and signalling
|
// peer launcher instance connector - used to implement single instance launcher and signalling
|
||||||
LocalPeer * m_peerInstance = nullptr;
|
LocalPeer* m_peerInstance = nullptr;
|
||||||
|
|
||||||
SetupWizard * m_setupWizard = nullptr;
|
SetupWizard* m_setupWizard = nullptr;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
|
QString m_detectedGLFWPath;
|
||||||
|
QString m_detectedOpenALPath;
|
||||||
QString m_instanceIdToLaunch;
|
QString m_instanceIdToLaunch;
|
||||||
QString m_serverToJoin;
|
QString m_serverToJoin;
|
||||||
QString m_profileToUse;
|
QString m_profileToUse;
|
||||||
bool m_liveCheck = false;
|
bool m_liveCheck = false;
|
||||||
QUrl m_zipToImport;
|
QList<QUrl> m_urlsToImport;
|
||||||
|
QString m_instanceIdToShowWindowOf;
|
||||||
std::unique_ptr<QFile> logFile;
|
std::unique_ptr<QFile> logFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,31 +1,67 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ApplicationMessage.h"
|
#include "ApplicationMessage.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include "Json.h"
|
||||||
|
|
||||||
void ApplicationMessage::parse(const QByteArray & input) {
|
void ApplicationMessage::parse(const QByteArray& input)
|
||||||
auto doc = QJsonDocument::fromBinaryData(input);
|
{
|
||||||
auto root = doc.object();
|
auto doc = Json::requireDocument(input, "ApplicationMessage");
|
||||||
|
auto root = Json::requireObject(doc, "ApplicationMessage");
|
||||||
|
|
||||||
command = root.value("command").toString();
|
command = root.value("command").toString();
|
||||||
args.clear();
|
args.clear();
|
||||||
|
|
||||||
auto parsedArgs = root.value("args").toObject();
|
auto parsedArgs = root.value("args").toObject();
|
||||||
for(auto iter = parsedArgs.begin(); iter != parsedArgs.end(); iter++) {
|
for (auto iter = parsedArgs.constBegin(); iter != parsedArgs.constEnd(); iter++) {
|
||||||
args[iter.key()] = iter.value().toString();
|
args.insert(iter.key(), iter.value().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ApplicationMessage::serialize() {
|
QByteArray ApplicationMessage::serialize()
|
||||||
|
{
|
||||||
QJsonObject root;
|
QJsonObject root;
|
||||||
root.insert("command", command);
|
root.insert("command", command);
|
||||||
QJsonObject outArgs;
|
QJsonObject outArgs;
|
||||||
for (auto iter = args.begin(); iter != args.end(); iter++) {
|
for (auto iter = args.constBegin(); iter != args.constEnd(); iter++) {
|
||||||
outArgs[iter.key()] = iter.value();
|
outArgs.insert(iter.key(), iter.value());
|
||||||
}
|
}
|
||||||
root.insert("args", outArgs);
|
root.insert("args", outArgs);
|
||||||
|
|
||||||
QJsonDocument out;
|
return Json::toText(root);
|
||||||
out.setObject(root);
|
|
||||||
return out.toBinaryData();
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
struct ApplicationMessage {
|
struct ApplicationMessage {
|
||||||
QString command;
|
QString command;
|
||||||
QMap<QString, QString> args;
|
QHash<QString, QString> args;
|
||||||
|
|
||||||
QByteArray serialize();
|
QByteArray serialize();
|
||||||
void parse(const QByteArray & input);
|
void parse(const QByteArray& input);
|
||||||
};
|
};
|
||||||
|
@ -18,27 +18,21 @@
|
|||||||
#include "BaseInstaller.h"
|
#include "BaseInstaller.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
|
||||||
BaseInstaller::BaseInstaller()
|
BaseInstaller::BaseInstaller() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
bool BaseInstaller::isApplied(MinecraftInstance* on)
|
||||||
|
|
||||||
bool BaseInstaller::isApplied(MinecraftInstance *on)
|
|
||||||
{
|
{
|
||||||
return QFile::exists(filename(on->instanceRoot()));
|
return QFile::exists(filename(on->instanceRoot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseInstaller::add(MinecraftInstance *to)
|
bool BaseInstaller::add(MinecraftInstance* to)
|
||||||
{
|
{
|
||||||
if (!patchesDir(to->instanceRoot()).exists())
|
if (!patchesDir(to->instanceRoot()).exists()) {
|
||||||
{
|
|
||||||
QDir(to->instanceRoot()).mkdir("patches");
|
QDir(to->instanceRoot()).mkdir("patches");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isApplied(to))
|
if (isApplied(to)) {
|
||||||
{
|
if (!remove(to)) {
|
||||||
if (!remove(to))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,16 +40,16 @@ bool BaseInstaller::add(MinecraftInstance *to)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseInstaller::remove(MinecraftInstance *from)
|
bool BaseInstaller::remove(MinecraftInstance* from)
|
||||||
{
|
{
|
||||||
return QFile::remove(filename(from->instanceRoot()));
|
return QFile::remove(filename(from->instanceRoot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstaller::filename(const QString &root) const
|
QString BaseInstaller::filename(const QString& root) const
|
||||||
{
|
{
|
||||||
return patchesDir(root).absoluteFilePath(id() + ".json");
|
return patchesDir(root).absoluteFilePath(id() + ".json");
|
||||||
}
|
}
|
||||||
QDir BaseInstaller::patchesDir(const QString &root) const
|
QDir BaseInstaller::patchesDir(const QString& root) const
|
||||||
{
|
{
|
||||||
return QDir(root + "/patches/");
|
return QDir(root + "/patches/");
|
||||||
}
|
}
|
||||||
|
@ -17,28 +17,28 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "BaseVersion.h"
|
||||||
|
|
||||||
class MinecraftInstance;
|
class MinecraftInstance;
|
||||||
class QDir;
|
class QDir;
|
||||||
class QString;
|
class QString;
|
||||||
class QObject;
|
class QObject;
|
||||||
class Task;
|
class Task;
|
||||||
class BaseVersion;
|
class BaseVersion;
|
||||||
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
|
||||||
|
|
||||||
class BaseInstaller
|
class BaseInstaller {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
BaseInstaller();
|
BaseInstaller();
|
||||||
virtual ~BaseInstaller(){};
|
virtual ~BaseInstaller(){};
|
||||||
bool isApplied(MinecraftInstance *on);
|
bool isApplied(MinecraftInstance* on);
|
||||||
|
|
||||||
virtual bool add(MinecraftInstance *to);
|
virtual bool add(MinecraftInstance* to);
|
||||||
virtual bool remove(MinecraftInstance *from);
|
virtual bool remove(MinecraftInstance* from);
|
||||||
|
|
||||||
virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
|
virtual Task* createInstallTask(MinecraftInstance* instance, BaseVersion::Ptr version, QObject* parent) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QString id() const = 0;
|
virtual QString id() const = 0;
|
||||||
QString filename(const QString &root) const;
|
QString filename(const QString& root) const;
|
||||||
QDir patchesDir(const QString &root) const;
|
QDir patchesDir(const QString& root) const;
|
||||||
};
|
};
|
||||||
|
@ -1,47 +1,85 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
#include "settings/INISettingsObject.h"
|
#include "settings/INISettingsObject.h"
|
||||||
#include "settings/Setting.h"
|
|
||||||
#include "settings/OverrideSetting.h"
|
#include "settings/OverrideSetting.h"
|
||||||
|
#include "settings/Setting.h"
|
||||||
|
|
||||||
#include "FileSystem.h"
|
|
||||||
#include "Commandline.h"
|
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
#include "Commandline.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
|
BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) : QObject()
|
||||||
: QObject()
|
|
||||||
{
|
{
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
m_global_settings = globalSettings;
|
||||||
m_rootDir = rootDir;
|
m_rootDir = rootDir;
|
||||||
|
|
||||||
m_settings->registerSetting("name", "Unnamed Instance");
|
m_settings->registerSetting("name", "Unnamed Instance");
|
||||||
m_settings->registerSetting("iconKey", "default");
|
m_settings->registerSetting("iconKey", "default");
|
||||||
m_settings->registerSetting("notes", "");
|
m_settings->registerSetting("notes", "");
|
||||||
|
|
||||||
m_settings->registerSetting("lastLaunchTime", 0);
|
m_settings->registerSetting("lastLaunchTime", 0);
|
||||||
m_settings->registerSetting("totalTimePlayed", 0);
|
m_settings->registerSetting("totalTimePlayed", 0);
|
||||||
m_settings->registerSetting("lastTimePlayed", 0);
|
m_settings->registerSetting("lastTimePlayed", 0);
|
||||||
|
|
||||||
|
m_settings->registerSetting("linkedInstances", "[]");
|
||||||
|
|
||||||
|
// Game time override
|
||||||
|
auto gameTimeOverride = m_settings->registerSetting("OverrideGameTime", false);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("ShowGameTime"), gameTimeOverride);
|
||||||
|
m_settings->registerOverride(globalSettings->getSetting("RecordGameTime"), gameTimeOverride);
|
||||||
|
|
||||||
|
// NOTE: Sometimees InstanceType is already registered, as it was used to identify the type of
|
||||||
|
// a locally stored instance
|
||||||
|
if (!m_settings->getSetting("InstanceType"))
|
||||||
|
m_settings->registerSetting("InstanceType", "");
|
||||||
|
|
||||||
// Custom Commands
|
// Custom Commands
|
||||||
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
auto commandSetting = m_settings->registerSetting({ "OverrideCommands", "OverrideLaunchCmd" }, false);
|
||||||
m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"), commandSetting);
|
m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"), commandSetting);
|
||||||
m_settings->registerOverride(globalSettings->getSetting("WrapperCommand"), commandSetting);
|
m_settings->registerOverride(globalSettings->getSetting("WrapperCommand"), commandSetting);
|
||||||
m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"), commandSetting);
|
m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"), commandSetting);
|
||||||
@ -55,6 +93,16 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
|
|||||||
|
|
||||||
m_settings->registerPassthrough(globalSettings->getSetting("ConsoleMaxLines"), nullptr);
|
m_settings->registerPassthrough(globalSettings->getSetting("ConsoleMaxLines"), nullptr);
|
||||||
m_settings->registerPassthrough(globalSettings->getSetting("ConsoleOverflowStop"), nullptr);
|
m_settings->registerPassthrough(globalSettings->getSetting("ConsoleOverflowStop"), nullptr);
|
||||||
|
|
||||||
|
// Managed Packs
|
||||||
|
m_settings->registerSetting("ManagedPack", false);
|
||||||
|
m_settings->registerSetting("ManagedPackType", "");
|
||||||
|
m_settings->registerSetting("ManagedPackID", "");
|
||||||
|
m_settings->registerSetting("ManagedPackName", "");
|
||||||
|
m_settings->registerSetting("ManagedPackVersionID", "");
|
||||||
|
m_settings->registerSetting("ManagedPackVersionName", "");
|
||||||
|
|
||||||
|
m_settings->registerSetting("Profiler", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::getPreLaunchCommand()
|
QString BaseInstance::getPreLaunchCommand()
|
||||||
@ -72,13 +120,66 @@ QString BaseInstance::getPostExitCommand()
|
|||||||
return settings()->get("PostExitCommand").toString();
|
return settings()->get("PostExitCommand").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BaseInstance::isManagedPack() const
|
||||||
|
{
|
||||||
|
return m_settings->get("ManagedPack").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BaseInstance::getManagedPackType() const
|
||||||
|
{
|
||||||
|
return m_settings->get("ManagedPackType").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BaseInstance::getManagedPackID() const
|
||||||
|
{
|
||||||
|
return m_settings->get("ManagedPackID").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BaseInstance::getManagedPackName() const
|
||||||
|
{
|
||||||
|
return m_settings->get("ManagedPackName").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BaseInstance::getManagedPackVersionID() const
|
||||||
|
{
|
||||||
|
return m_settings->get("ManagedPackVersionID").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BaseInstance::getManagedPackVersionName() const
|
||||||
|
{
|
||||||
|
return m_settings->get("ManagedPackVersionName").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseInstance::setManagedPack(const QString& type,
|
||||||
|
const QString& id,
|
||||||
|
const QString& name,
|
||||||
|
const QString& versionId,
|
||||||
|
const QString& version)
|
||||||
|
{
|
||||||
|
m_settings->set("ManagedPack", true);
|
||||||
|
m_settings->set("ManagedPackType", type);
|
||||||
|
m_settings->set("ManagedPackID", id);
|
||||||
|
m_settings->set("ManagedPackName", name);
|
||||||
|
m_settings->set("ManagedPackVersionID", versionId);
|
||||||
|
m_settings->set("ManagedPackVersionName", version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseInstance::copyManagedPack(BaseInstance& other)
|
||||||
|
{
|
||||||
|
m_settings->set("ManagedPack", other.isManagedPack());
|
||||||
|
m_settings->set("ManagedPackType", other.getManagedPackType());
|
||||||
|
m_settings->set("ManagedPackID", other.getManagedPackID());
|
||||||
|
m_settings->set("ManagedPackName", other.getManagedPackName());
|
||||||
|
m_settings->set("ManagedPackVersionID", other.getManagedPackVersionID());
|
||||||
|
m_settings->set("ManagedPackVersionName", other.getManagedPackVersionName());
|
||||||
|
}
|
||||||
|
|
||||||
int BaseInstance::getConsoleMaxLines() const
|
int BaseInstance::getConsoleMaxLines() const
|
||||||
{
|
{
|
||||||
auto lineSetting = settings()->getSetting("ConsoleMaxLines");
|
auto lineSetting = m_settings->getSetting("ConsoleMaxLines");
|
||||||
bool conversionOk = false;
|
bool conversionOk = false;
|
||||||
int maxLines = lineSetting->get().toInt(&conversionOk);
|
int maxLines = lineSetting->get().toInt(&conversionOk);
|
||||||
if(!conversionOk)
|
if (!conversionOk) {
|
||||||
{
|
|
||||||
maxLines = lineSetting->defValue().toInt();
|
maxLines = lineSetting->defValue().toInt();
|
||||||
qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines;
|
qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines;
|
||||||
}
|
}
|
||||||
@ -87,13 +188,44 @@ int BaseInstance::getConsoleMaxLines() const
|
|||||||
|
|
||||||
bool BaseInstance::shouldStopOnConsoleOverflow() const
|
bool BaseInstance::shouldStopOnConsoleOverflow() const
|
||||||
{
|
{
|
||||||
return settings()->get("ConsoleOverflowStop").toBool();
|
return m_settings->get("ConsoleOverflowStop").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList BaseInstance::getLinkedInstances() const
|
||||||
|
{
|
||||||
|
return m_settings->get("linkedInstances").toStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseInstance::setLinkedInstances(const QStringList& list)
|
||||||
|
{
|
||||||
|
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||||
|
m_settings->set("linkedInstances", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseInstance::addLinkedInstanceId(const QString& id)
|
||||||
|
{
|
||||||
|
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||||
|
linkedInstances.append(id);
|
||||||
|
setLinkedInstances(linkedInstances);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseInstance::removeLinkedInstanceId(const QString& id)
|
||||||
|
{
|
||||||
|
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||||
|
int numRemoved = linkedInstances.removeAll(id);
|
||||||
|
setLinkedInstances(linkedInstances);
|
||||||
|
return numRemoved > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseInstance::isLinkedToInstanceId(const QString& id) const
|
||||||
|
{
|
||||||
|
auto linkedInstances = m_settings->get("linkedInstances").toStringList();
|
||||||
|
return linkedInstances.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::iconUpdated(QString key)
|
void BaseInstance::iconUpdated(QString key)
|
||||||
{
|
{
|
||||||
if(iconKey() == key)
|
if (iconKey() == key) {
|
||||||
{
|
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,8 +239,7 @@ void BaseInstance::invalidate()
|
|||||||
void BaseInstance::changeStatus(BaseInstance::Status newStatus)
|
void BaseInstance::changeStatus(BaseInstance::Status newStatus)
|
||||||
{
|
{
|
||||||
Status status = currentStatus();
|
Status status = currentStatus();
|
||||||
if(status != newStatus)
|
if (status != newStatus) {
|
||||||
{
|
|
||||||
m_status = newStatus;
|
m_status = newStatus;
|
||||||
emit statusChanged(status, newStatus);
|
emit statusChanged(status, newStatus);
|
||||||
}
|
}
|
||||||
@ -131,23 +262,19 @@ bool BaseInstance::isRunning() const
|
|||||||
|
|
||||||
void BaseInstance::setRunning(bool running)
|
void BaseInstance::setRunning(bool running)
|
||||||
{
|
{
|
||||||
if(running == m_isRunning)
|
if (running == m_isRunning)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_isRunning = running;
|
m_isRunning = running;
|
||||||
|
|
||||||
if(!m_settings->get("RecordGameTime").toBool())
|
if (!m_settings->get("RecordGameTime").toBool()) {
|
||||||
{
|
|
||||||
emit runningStatusChanged(running);
|
emit runningStatusChanged(running);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(running)
|
if (running) {
|
||||||
{
|
|
||||||
m_timeStarted = QDateTime::currentDateTime();
|
m_timeStarted = QDateTime::currentDateTime();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QDateTime timeEnded = QDateTime::currentDateTime();
|
QDateTime timeEnded = QDateTime::currentDateTime();
|
||||||
|
|
||||||
qint64 current = settings()->get("totalTimePlayed").toLongLong();
|
qint64 current = settings()->get("totalTimePlayed").toLongLong();
|
||||||
@ -162,9 +289,8 @@ void BaseInstance::setRunning(bool running)
|
|||||||
|
|
||||||
int64_t BaseInstance::totalTimePlayed() const
|
int64_t BaseInstance::totalTimePlayed() const
|
||||||
{
|
{
|
||||||
qint64 current = settings()->get("totalTimePlayed").toLongLong();
|
qint64 current = m_settings->get("totalTimePlayed").toLongLong();
|
||||||
if(m_isRunning)
|
if (m_isRunning) {
|
||||||
{
|
|
||||||
QDateTime timeNow = QDateTime::currentDateTime();
|
QDateTime timeNow = QDateTime::currentDateTime();
|
||||||
return current + m_timeStarted.secsTo(timeNow);
|
return current + m_timeStarted.secsTo(timeNow);
|
||||||
}
|
}
|
||||||
@ -173,12 +299,11 @@ int64_t BaseInstance::totalTimePlayed() const
|
|||||||
|
|
||||||
int64_t BaseInstance::lastTimePlayed() const
|
int64_t BaseInstance::lastTimePlayed() const
|
||||||
{
|
{
|
||||||
if(m_isRunning)
|
if (m_isRunning) {
|
||||||
{
|
|
||||||
QDateTime timeNow = QDateTime::currentDateTime();
|
QDateTime timeNow = QDateTime::currentDateTime();
|
||||||
return m_timeStarted.secsTo(timeNow);
|
return m_timeStarted.secsTo(timeNow);
|
||||||
}
|
}
|
||||||
return settings()->get("lastTimePlayed").toLongLong();
|
return m_settings->get("lastTimePlayed").toLongLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::resetTimePlayed()
|
void BaseInstance::resetTimePlayed()
|
||||||
@ -197,8 +322,10 @@ QString BaseInstance::instanceRoot() const
|
|||||||
return m_rootDir;
|
return m_rootDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsObjectPtr BaseInstance::settings() const
|
SettingsObjectPtr BaseInstance::settings()
|
||||||
{
|
{
|
||||||
|
loadSpecificSettings();
|
||||||
|
|
||||||
return m_settings;
|
return m_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,14 +346,14 @@ qint64 BaseInstance::lastLaunch() const
|
|||||||
|
|
||||||
void BaseInstance::setLastLaunch(qint64 val)
|
void BaseInstance::setLastLaunch(qint64 val)
|
||||||
{
|
{
|
||||||
//FIXME: if no change, do not set. setting involves saving a file.
|
// FIXME: if no change, do not set. setting involves saving a file.
|
||||||
m_settings->set("lastLaunchTime", val);
|
m_settings->set("lastLaunchTime", val);
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseInstance::setNotes(QString val)
|
void BaseInstance::setNotes(QString val)
|
||||||
{
|
{
|
||||||
//FIXME: if no change, do not set. setting involves saving a file.
|
// FIXME: if no change, do not set. setting involves saving a file.
|
||||||
m_settings->set("notes", val);
|
m_settings->set("notes", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +364,7 @@ QString BaseInstance::notes() const
|
|||||||
|
|
||||||
void BaseInstance::setIconKey(QString val)
|
void BaseInstance::setIconKey(QString val)
|
||||||
{
|
{
|
||||||
//FIXME: if no change, do not set. setting involves saving a file.
|
// FIXME: if no change, do not set. setting involves saving a file.
|
||||||
m_settings->set("iconKey", val);
|
m_settings->set("iconKey", val);
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
@ -249,7 +376,7 @@ QString BaseInstance::iconKey() const
|
|||||||
|
|
||||||
void BaseInstance::setName(QString val)
|
void BaseInstance::setName(QString val)
|
||||||
{
|
{
|
||||||
//FIXME: if no change, do not set. setting involves saving a file.
|
// FIXME: if no change, do not set. setting involves saving a file.
|
||||||
m_settings->set("name", val);
|
m_settings->set("name", val);
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
@ -261,11 +388,11 @@ QString BaseInstance::name() const
|
|||||||
|
|
||||||
QString BaseInstance::windowTitle() const
|
QString BaseInstance::windowTitle() const
|
||||||
{
|
{
|
||||||
return BuildConfig.LAUNCHER_NAME + ": " + name().replace(QRegExp("[ \n\r\t]+"), " ");
|
return BuildConfig.LAUNCHER_DISPLAYNAME + ": " + name();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: why is this here? move it to MinecraftInstance!!!
|
// FIXME: why is this here? move it to MinecraftInstance!!!
|
||||||
QStringList BaseInstance::extraArguments() const
|
QStringList BaseInstance::extraArguments()
|
||||||
{
|
{
|
||||||
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
|
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
|
||||||
}
|
}
|
||||||
@ -274,3 +401,8 @@ shared_qobject_ptr<LaunchTask> BaseInstance::getLaunchTask()
|
|||||||
{
|
{
|
||||||
return m_launchProcess;
|
return m_launchProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseInstance::updateRuntimeContext()
|
||||||
|
{
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
@ -1,37 +1,61 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "QObjectPtr.h"
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QSet>
|
#include <QMenu>
|
||||||
|
#include <QObject>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QSet>
|
||||||
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
#include "settings/SettingsObject.h"
|
#include "settings/SettingsObject.h"
|
||||||
|
|
||||||
#include "settings/INIFile.h"
|
|
||||||
#include "BaseVersionList.h"
|
#include "BaseVersionList.h"
|
||||||
#include "minecraft/auth/MinecraftAccount.h"
|
|
||||||
#include "MessageLevel.h"
|
#include "MessageLevel.h"
|
||||||
|
#include "minecraft/auth/MinecraftAccount.h"
|
||||||
#include "pathmatcher/IPathMatcher.h"
|
#include "pathmatcher/IPathMatcher.h"
|
||||||
|
#include "settings/INIFile.h"
|
||||||
|
|
||||||
#include "net/Mode.h"
|
#include "net/Mode.h"
|
||||||
|
|
||||||
|
#include "RuntimeContext.h"
|
||||||
#include "minecraft/launch/MinecraftServerTarget.h"
|
#include "minecraft/launch/MinecraftServerTarget.h"
|
||||||
|
|
||||||
class QDir;
|
class QDir;
|
||||||
@ -40,7 +64,7 @@ class LaunchTask;
|
|||||||
class BaseInstance;
|
class BaseInstance;
|
||||||
|
|
||||||
// pointer for lazy people
|
// pointer for lazy people
|
||||||
typedef std::shared_ptr<BaseInstance> InstancePtr;
|
using InstancePtr = std::shared_ptr<BaseInstance>;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Base class for instances.
|
* \brief Base class for instances.
|
||||||
@ -50,23 +74,21 @@ typedef std::shared_ptr<BaseInstance> InstancePtr;
|
|||||||
* To create a new instance type, create a new class inheriting from this class
|
* To create a new instance type, create a new class inheriting from this class
|
||||||
* and implement the pure virtual functions.
|
* and implement the pure virtual functions.
|
||||||
*/
|
*/
|
||||||
class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance>
|
class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance> {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
/// no-touchy!
|
/// no-touchy!
|
||||||
BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
|
BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir);
|
||||||
|
|
||||||
public: /* types */
|
public: /* types */
|
||||||
enum class Status
|
enum class Status {
|
||||||
{
|
|
||||||
Present,
|
Present,
|
||||||
Gone // either nuked or invalidated
|
Gone // either nuked or invalidated
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// virtual destructor to make sure the destruction is COMPLETE
|
/// virtual destructor to make sure the destruction is COMPLETE
|
||||||
virtual ~BaseInstance() {};
|
virtual ~BaseInstance() {}
|
||||||
|
|
||||||
virtual void saveNow() = 0;
|
virtual void saveNow() = 0;
|
||||||
|
|
||||||
@ -95,10 +117,7 @@ public:
|
|||||||
QString instanceRoot() const;
|
QString instanceRoot() const;
|
||||||
|
|
||||||
/// Path to the instance's game root directory.
|
/// Path to the instance's game root directory.
|
||||||
virtual QString gameRoot() const
|
virtual QString gameRoot() const { return instanceRoot(); }
|
||||||
{
|
|
||||||
return instanceRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Path to the instance's mods directory.
|
/// Path to the instance's mods directory.
|
||||||
virtual QString modsRoot() const = 0;
|
virtual QString modsRoot() const = 0;
|
||||||
@ -119,16 +138,22 @@ public:
|
|||||||
QString getPostExitCommand();
|
QString getPostExitCommand();
|
||||||
QString getWrapperCommand();
|
QString getWrapperCommand();
|
||||||
|
|
||||||
/// guess log level from a line of game log
|
bool isManagedPack() const;
|
||||||
virtual MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level)
|
QString getManagedPackType() const;
|
||||||
{
|
QString getManagedPackID() const;
|
||||||
return level;
|
QString getManagedPackName() const;
|
||||||
};
|
QString getManagedPackVersionID() const;
|
||||||
|
QString getManagedPackVersionName() const;
|
||||||
|
void setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version);
|
||||||
|
void copyManagedPack(BaseInstance& other);
|
||||||
|
|
||||||
virtual QStringList extraArguments() const;
|
/// guess log level from a line of game log
|
||||||
|
virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString& line, MessageLevel::Enum level) { return level; }
|
||||||
|
|
||||||
|
virtual QStringList extraArguments();
|
||||||
|
|
||||||
/// Traits. Normally inside the version, depends on instance implementation.
|
/// Traits. Normally inside the version, depends on instance implementation.
|
||||||
virtual QSet <QString> traits() const = 0;
|
virtual QSet<QString> traits() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the time that the instance was last launched.
|
* Gets the time that the instance was last launched.
|
||||||
@ -141,16 +166,24 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Gets this instance's settings object.
|
* \brief Gets this instance's settings object.
|
||||||
* This settings object stores instance-specific settings.
|
* This settings object stores instance-specific settings.
|
||||||
|
*
|
||||||
|
* Note that this method is not const.
|
||||||
|
* It may call loadSpecificSettings() to ensure those are loaded.
|
||||||
|
*
|
||||||
* \return A pointer to this instance's settings object.
|
* \return A pointer to this instance's settings object.
|
||||||
*/
|
*/
|
||||||
virtual SettingsObjectPtr settings() const;
|
virtual SettingsObjectPtr settings();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Loads settings specific to an instance type if they're not already loaded.
|
||||||
|
*/
|
||||||
|
virtual void loadSpecificSettings() = 0;
|
||||||
|
|
||||||
/// returns a valid update task
|
/// returns a valid update task
|
||||||
virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0;
|
virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0;
|
||||||
|
|
||||||
/// returns a valid launcher (task container)
|
/// returns a valid launcher (task container)
|
||||||
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(
|
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0;
|
||||||
AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0;
|
|
||||||
|
|
||||||
/// returns the current launch task (if any)
|
/// returns the current launch task (if any)
|
||||||
shared_qobject_ptr<LaunchTask> getLaunchTask();
|
shared_qobject_ptr<LaunchTask> getLaunchTask();
|
||||||
@ -159,6 +192,7 @@ public:
|
|||||||
* Create envrironment variables for running the instance
|
* Create envrironment variables for running the instance
|
||||||
*/
|
*/
|
||||||
virtual QProcessEnvironment createEnvironment() = 0;
|
virtual QProcessEnvironment createEnvironment() = 0;
|
||||||
|
virtual QProcessEnvironment createLaunchEnvironment() = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a matcher that can maps relative paths within the instance to whether they are 'log files'
|
* Returns a matcher that can maps relative paths within the instance to whether they are 'log files'
|
||||||
@ -176,44 +210,35 @@ public:
|
|||||||
virtual QString instanceConfigFolder() const = 0;
|
virtual QString instanceConfigFolder() const = 0;
|
||||||
|
|
||||||
/// get variables this instance exports
|
/// get variables this instance exports
|
||||||
virtual QMap<QString, QString> getVariables() const = 0;
|
virtual QMap<QString, QString> getVariables() = 0;
|
||||||
|
|
||||||
virtual QString typeName() const = 0;
|
virtual QString typeName() const = 0;
|
||||||
|
|
||||||
bool hasVersionBroken() const
|
void updateRuntimeContext();
|
||||||
{
|
RuntimeContext runtimeContext() const { return m_runtimeContext; }
|
||||||
return m_hasBrokenVersion;
|
|
||||||
}
|
bool hasVersionBroken() const { return m_hasBrokenVersion; }
|
||||||
void setVersionBroken(bool value)
|
void setVersionBroken(bool value)
|
||||||
{
|
{
|
||||||
if(m_hasBrokenVersion != value)
|
if (m_hasBrokenVersion != value) {
|
||||||
{
|
|
||||||
m_hasBrokenVersion = value;
|
m_hasBrokenVersion = value;
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasUpdateAvailable() const
|
bool hasUpdateAvailable() const { return m_hasUpdate; }
|
||||||
{
|
|
||||||
return m_hasUpdate;
|
|
||||||
}
|
|
||||||
void setUpdateAvailable(bool value)
|
void setUpdateAvailable(bool value)
|
||||||
{
|
{
|
||||||
if(m_hasUpdate != value)
|
if (m_hasUpdate != value) {
|
||||||
{
|
|
||||||
m_hasUpdate = value;
|
m_hasUpdate = value;
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasCrashed() const
|
bool hasCrashed() const { return m_crashed; }
|
||||||
{
|
|
||||||
return m_crashed;
|
|
||||||
}
|
|
||||||
void setCrashed(bool value)
|
void setCrashed(bool value)
|
||||||
{
|
{
|
||||||
if(m_crashed != value)
|
if (m_crashed != value) {
|
||||||
{
|
|
||||||
m_crashed = value;
|
m_crashed = value;
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
@ -223,6 +248,8 @@ public:
|
|||||||
virtual bool canEdit() const = 0;
|
virtual bool canEdit() const = 0;
|
||||||
virtual bool canExport() const = 0;
|
virtual bool canExport() const = 0;
|
||||||
|
|
||||||
|
virtual void populateLaunchMenu(QMenu* menu) = 0;
|
||||||
|
|
||||||
bool reloadSettings();
|
bool reloadSettings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -235,39 +262,56 @@ public:
|
|||||||
int getConsoleMaxLines() const;
|
int getConsoleMaxLines() const;
|
||||||
bool shouldStopOnConsoleOverflow() const;
|
bool shouldStopOnConsoleOverflow() const;
|
||||||
|
|
||||||
protected:
|
QStringList getLinkedInstances() const;
|
||||||
|
void setLinkedInstances(const QStringList& list);
|
||||||
|
void addLinkedInstanceId(const QString& id);
|
||||||
|
bool removeLinkedInstanceId(const QString& id);
|
||||||
|
bool isLinkedToInstanceId(const QString& id) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
void changeStatus(Status newStatus);
|
void changeStatus(Status newStatus);
|
||||||
|
|
||||||
signals:
|
SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); }
|
||||||
|
|
||||||
|
bool isSpecificSettingsLoaded() const { return m_specific_settings_loaded; }
|
||||||
|
void setSpecificSettingsLoaded(bool loaded) { m_specific_settings_loaded = loaded; }
|
||||||
|
|
||||||
|
signals:
|
||||||
/*!
|
/*!
|
||||||
* \brief Signal emitted when properties relevant to the instance view change
|
* \brief Signal emitted when properties relevant to the instance view change
|
||||||
*/
|
*/
|
||||||
void propertiesChanged(BaseInstance *inst);
|
void propertiesChanged(BaseInstance* inst);
|
||||||
|
|
||||||
void launchTaskChanged(shared_qobject_ptr<LaunchTask>);
|
void launchTaskChanged(shared_qobject_ptr<LaunchTask>);
|
||||||
|
|
||||||
void runningStatusChanged(bool running);
|
void runningStatusChanged(bool running);
|
||||||
|
|
||||||
|
void profilerChanged();
|
||||||
|
|
||||||
void statusChanged(Status from, Status to);
|
void statusChanged(Status from, Status to);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void iconUpdated(QString key);
|
void iconUpdated(QString key);
|
||||||
|
|
||||||
protected: /* data */
|
protected: /* data */
|
||||||
QString m_rootDir;
|
QString m_rootDir;
|
||||||
SettingsObjectPtr m_settings;
|
SettingsObjectPtr m_settings;
|
||||||
// InstanceFlags m_flags;
|
// InstanceFlags m_flags;
|
||||||
bool m_isRunning = false;
|
bool m_isRunning = false;
|
||||||
shared_qobject_ptr<LaunchTask> m_launchProcess;
|
shared_qobject_ptr<LaunchTask> m_launchProcess;
|
||||||
QDateTime m_timeStarted;
|
QDateTime m_timeStarted;
|
||||||
|
RuntimeContext m_runtimeContext;
|
||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
Status m_status = Status::Present;
|
Status m_status = Status::Present;
|
||||||
bool m_crashed = false;
|
bool m_crashed = false;
|
||||||
bool m_hasUpdate = false;
|
bool m_hasUpdate = false;
|
||||||
bool m_hasBrokenVersion = false;
|
bool m_hasBrokenVersion = false;
|
||||||
|
|
||||||
|
SettingsObjectWeakPtr m_global_settings;
|
||||||
|
bool m_specific_settings_loaded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>)
|
Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>)
|
||||||
//Q_DECLARE_METATYPE(BaseInstance::InstanceFlag)
|
// Q_DECLARE_METATYPE(BaseInstance::InstanceFlag)
|
||||||
//Q_DECLARE_OPERATORS_FOR_FLAGS(BaseInstance::InstanceFlags)
|
// Q_DECLARE_OPERATORS_FOR_FLAGS(BaseInstance::InstanceFlags)
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <QString>
|
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
#include <QString>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* An abstract base class for versions.
|
* An abstract base class for versions.
|
||||||
*/
|
*/
|
||||||
class BaseVersion
|
class BaseVersion {
|
||||||
{
|
public:
|
||||||
public:
|
using Ptr = std::shared_ptr<BaseVersion>;
|
||||||
virtual ~BaseVersion() {}
|
virtual ~BaseVersion() {}
|
||||||
/*!
|
/*!
|
||||||
* A string used to identify this version in config files.
|
* A string used to identify this version in config files.
|
||||||
@ -43,17 +43,8 @@ public:
|
|||||||
* the kind of version this is (Stable, Beta, Snapshot, whatever)
|
* the kind of version this is (Stable, Beta, Snapshot, whatever)
|
||||||
*/
|
*/
|
||||||
virtual QString typeString() const = 0;
|
virtual QString typeString() const = 0;
|
||||||
|
virtual bool operator<(BaseVersion& a) { return name() < a.name(); }
|
||||||
virtual bool operator<(BaseVersion &a)
|
virtual bool operator>(BaseVersion& a) { return name() > a.name(); }
|
||||||
{
|
|
||||||
return name() < a.name();
|
|
||||||
};
|
|
||||||
virtual bool operator>(BaseVersion &a)
|
|
||||||
{
|
|
||||||
return name() > a.name();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
Q_DECLARE_METATYPE(BaseVersion::Ptr)
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(BaseVersionPtr)
|
|
||||||
|
@ -1,44 +1,61 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* you may not use this file except in compliance with the License.
|
* it under the terms of the GNU General Public License as published by
|
||||||
* You may obtain a copy of the License at
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* You should have received a copy of the GNU General Public License
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* This file incorporates work covered by the following copyright and
|
||||||
* limitations under the License.
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "BaseVersionList.h"
|
#include "BaseVersionList.h"
|
||||||
#include "BaseVersion.h"
|
#include "BaseVersion.h"
|
||||||
|
|
||||||
BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent)
|
BaseVersionList::BaseVersionList(QObject* parent) : QAbstractListModel(parent) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseVersionPtr BaseVersionList::findVersion(const QString &descriptor)
|
BaseVersion::Ptr BaseVersionList::findVersion(const QString& descriptor)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count(); i++)
|
for (int i = 0; i < count(); i++) {
|
||||||
{
|
|
||||||
if (at(i)->descriptor() == descriptor)
|
if (at(i)->descriptor() == descriptor)
|
||||||
return at(i);
|
return at(i);
|
||||||
}
|
}
|
||||||
return BaseVersionPtr();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseVersionPtr BaseVersionList::getRecommended() const
|
BaseVersion::Ptr BaseVersionList::getRecommended() const
|
||||||
{
|
{
|
||||||
if (count() <= 0)
|
if (count() <= 0)
|
||||||
return BaseVersionPtr();
|
return nullptr;
|
||||||
else
|
else
|
||||||
return at(0);
|
return at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant BaseVersionList::data(const QModelIndex &index, int role) const
|
QVariant BaseVersionList::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -46,41 +63,40 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const
|
|||||||
if (index.row() > count())
|
if (index.row() > count())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
BaseVersionPtr version = at(index.row());
|
BaseVersion::Ptr version = at(index.row());
|
||||||
|
|
||||||
switch (role)
|
switch (role) {
|
||||||
{
|
case VersionPointerRole:
|
||||||
case VersionPointerRole:
|
return QVariant::fromValue(version);
|
||||||
return qVariantFromValue(version);
|
|
||||||
|
|
||||||
case VersionRole:
|
case VersionRole:
|
||||||
return version->name();
|
return version->name();
|
||||||
|
|
||||||
case VersionIdRole:
|
case VersionIdRole:
|
||||||
return version->descriptor();
|
return version->descriptor();
|
||||||
|
|
||||||
case TypeRole:
|
case TypeRole:
|
||||||
return version->typeString();
|
return version->typeString();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseVersionList::RoleList BaseVersionList::providesRoles() const
|
BaseVersionList::RoleList BaseVersionList::providesRoles() const
|
||||||
{
|
{
|
||||||
return {VersionPointerRole, VersionRole, VersionIdRole, TypeRole};
|
return { VersionPointerRole, VersionRole, VersionIdRole, TypeRole };
|
||||||
}
|
}
|
||||||
|
|
||||||
int BaseVersionList::rowCount(const QModelIndex &parent) const
|
int BaseVersionList::rowCount(const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
// Return count
|
// Return count
|
||||||
return count();
|
return parent.isValid() ? 0 : count();
|
||||||
}
|
}
|
||||||
|
|
||||||
int BaseVersionList::columnCount(const QModelIndex &parent) const
|
int BaseVersionList::columnCount(const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
return 1;
|
return parent.isValid() ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> BaseVersionList::roleNames() const
|
QHash<int, QByteArray> BaseVersionList::roleNames() const
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QAbstractListModel>
|
|
||||||
|
|
||||||
#include "BaseVersion.h"
|
#include "BaseVersion.h"
|
||||||
#include "tasks/Task.h"
|
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Class that each instance type's version list derives from.
|
* \brief Class that each instance type's version list derives from.
|
||||||
@ -35,12 +35,10 @@
|
|||||||
* all have a default implementation, but they can be overridden by plugins to
|
* all have a default implementation, but they can be overridden by plugins to
|
||||||
* change the behavior of the list.
|
* change the behavior of the list.
|
||||||
*/
|
*/
|
||||||
class BaseVersionList : public QAbstractListModel
|
class BaseVersionList : public QAbstractListModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum ModelRoles
|
enum ModelRoles {
|
||||||
{
|
|
||||||
VersionPointerRole = Qt::UserRole,
|
VersionPointerRole = Qt::UserRole,
|
||||||
VersionRole,
|
VersionRole,
|
||||||
VersionIdRole,
|
VersionIdRole,
|
||||||
@ -53,9 +51,9 @@ public:
|
|||||||
ArchitectureRole,
|
ArchitectureRole,
|
||||||
SortRole
|
SortRole
|
||||||
};
|
};
|
||||||
typedef QList<int> RoleList;
|
using RoleList = QList<int>;
|
||||||
|
|
||||||
explicit BaseVersionList(QObject *parent = 0);
|
explicit BaseVersionList(QObject* parent = 0);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets a task that will reload the version list.
|
* \brief Gets a task that will reload the version list.
|
||||||
@ -66,19 +64,19 @@ public:
|
|||||||
virtual Task::Ptr getLoadTask() = 0;
|
virtual Task::Ptr getLoadTask() = 0;
|
||||||
|
|
||||||
//! Checks whether or not the list is loaded. If this returns false, the list should be
|
//! Checks whether or not the list is loaded. If this returns false, the list should be
|
||||||
//loaded.
|
// loaded.
|
||||||
virtual bool isLoaded() = 0;
|
virtual bool isLoaded() = 0;
|
||||||
|
|
||||||
//! Gets the version at the given index.
|
//! Gets the version at the given index.
|
||||||
virtual const BaseVersionPtr at(int i) const = 0;
|
virtual const BaseVersion::Ptr at(int i) const = 0;
|
||||||
|
|
||||||
//! Returns the number of versions in the list.
|
//! Returns the number of versions in the list.
|
||||||
virtual int count() const = 0;
|
virtual int count() const = 0;
|
||||||
|
|
||||||
//////// List Model Functions ////////
|
//////// List Model Functions ////////
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex& index, int role) const override;
|
||||||
int rowCount(const QModelIndex &parent) const override;
|
int rowCount(const QModelIndex& parent) const override;
|
||||||
int columnCount(const QModelIndex &parent) const override;
|
int columnCount(const QModelIndex& parent) const override;
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
//! which roles are provided by this version list?
|
//! which roles are provided by this version list?
|
||||||
@ -90,21 +88,20 @@ public:
|
|||||||
* \return A const pointer to the version with the given descriptor. NULL if
|
* \return A const pointer to the version with the given descriptor. NULL if
|
||||||
* one doesn't exist.
|
* one doesn't exist.
|
||||||
*/
|
*/
|
||||||
virtual BaseVersionPtr findVersion(const QString &descriptor);
|
virtual BaseVersion::Ptr findVersion(const QString& descriptor);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the recommended version from this list
|
* \brief Gets the recommended version from this list
|
||||||
* If the list doesn't support recommended versions, this works exactly as getLatestStable
|
* If the list doesn't support recommended versions, this works exactly as getLatestStable
|
||||||
*/
|
*/
|
||||||
virtual BaseVersionPtr getRecommended() const;
|
virtual BaseVersion::Ptr getRecommended() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sorts the version list.
|
* Sorts the version list.
|
||||||
*/
|
*/
|
||||||
virtual void sortVersions() = 0;
|
virtual void sortVersions() = 0;
|
||||||
|
|
||||||
protected
|
protected slots:
|
||||||
slots:
|
|
||||||
/*!
|
/*!
|
||||||
* Updates this list with the given list of versions.
|
* Updates this list with the given list of versions.
|
||||||
* This is done by copying each version in the given list and inserting it
|
* This is done by copying each version in the given list and inserting it
|
||||||
@ -117,5 +114,5 @@ slots:
|
|||||||
* then copies the versions and sets their parents correctly.
|
* then copies the versions and sets their parents correctly.
|
||||||
* \param versions List of versions whose parents should be set.
|
* \param versions List of versions whose parents should be set.
|
||||||
*/
|
*/
|
||||||
virtual void updateListData(QList<BaseVersionPtr> versions) = 0;
|
virtual void updateListData(QList<BaseVersion::Ptr> versions) = 0;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,38 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This program is distributed in the hope that it will be useful,
|
||||||
* you may not use this file except in compliance with the License.
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* You may obtain a copy of the License at
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* This file incorporates work covered by the following copyright and
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* permission notice:
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*
|
||||||
* See the License for the specific language governing permissions and
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
* limitations under the License.
|
*
|
||||||
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Commandline.h"
|
#include "Commandline.h"
|
||||||
@ -21,8 +41,7 @@
|
|||||||
* @file libutil/src/cmdutils.cpp
|
* @file libutil/src/cmdutils.cpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Commandline
|
namespace Commandline {
|
||||||
{
|
|
||||||
|
|
||||||
// commandline splitter
|
// commandline splitter
|
||||||
QStringList splitArgs(QString args)
|
QStringList splitArgs(QString args)
|
||||||
@ -31,38 +50,29 @@ QStringList splitArgs(QString args)
|
|||||||
QString current;
|
QString current;
|
||||||
bool escape = false;
|
bool escape = false;
|
||||||
QChar inquotes;
|
QChar inquotes;
|
||||||
for (int i = 0; i < args.length(); i++)
|
for (int i = 0; i < args.length(); i++) {
|
||||||
{
|
|
||||||
QChar cchar = args.at(i);
|
QChar cchar = args.at(i);
|
||||||
|
|
||||||
// \ escaped
|
// \ escaped
|
||||||
if (escape)
|
if (escape) {
|
||||||
{
|
|
||||||
current += cchar;
|
current += cchar;
|
||||||
escape = false;
|
escape = false;
|
||||||
// in "quotes"
|
// in "quotes"
|
||||||
}
|
} else if (!inquotes.isNull()) {
|
||||||
else if (!inquotes.isNull())
|
|
||||||
{
|
|
||||||
if (cchar == '\\')
|
if (cchar == '\\')
|
||||||
escape = true;
|
escape = true;
|
||||||
else if (cchar == inquotes)
|
else if (cchar == inquotes)
|
||||||
inquotes = 0;
|
inquotes = QChar::Null;
|
||||||
else
|
else
|
||||||
current += cchar;
|
current += cchar;
|
||||||
// otherwise
|
// otherwise
|
||||||
}
|
} else {
|
||||||
else
|
if (cchar == ' ') {
|
||||||
{
|
if (!current.isEmpty()) {
|
||||||
if (cchar == ' ')
|
|
||||||
{
|
|
||||||
if (!current.isEmpty())
|
|
||||||
{
|
|
||||||
argv << current;
|
argv << current;
|
||||||
current.clear();
|
current.clear();
|
||||||
}
|
}
|
||||||
}
|
} else if (cchar == '"' || cchar == '\'')
|
||||||
else if (cchar == '"' || cchar == '\'')
|
|
||||||
inquotes = cchar;
|
inquotes = cchar;
|
||||||
else
|
else
|
||||||
current += cchar;
|
current += cchar;
|
||||||
@ -72,412 +82,4 @@ QStringList splitArgs(QString args)
|
|||||||
argv << current;
|
argv << current;
|
||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
|
} // namespace Commandline
|
||||||
Parser::Parser(FlagStyle::Enum flagStyle, ArgumentStyle::Enum argStyle)
|
|
||||||
{
|
|
||||||
m_flagStyle = flagStyle;
|
|
||||||
m_argStyle = argStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// styles setter/getter
|
|
||||||
void Parser::setArgumentStyle(ArgumentStyle::Enum style)
|
|
||||||
{
|
|
||||||
m_argStyle = style;
|
|
||||||
}
|
|
||||||
ArgumentStyle::Enum Parser::argumentStyle()
|
|
||||||
{
|
|
||||||
return m_argStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::setFlagStyle(FlagStyle::Enum style)
|
|
||||||
{
|
|
||||||
m_flagStyle = style;
|
|
||||||
}
|
|
||||||
FlagStyle::Enum Parser::flagStyle()
|
|
||||||
{
|
|
||||||
return m_flagStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup methods
|
|
||||||
void Parser::addSwitch(QString name, bool def)
|
|
||||||
{
|
|
||||||
if (m_params.contains(name))
|
|
||||||
throw "Name not unique";
|
|
||||||
|
|
||||||
OptionDef *param = new OptionDef;
|
|
||||||
param->type = otSwitch;
|
|
||||||
param->name = name;
|
|
||||||
param->metavar = QString("<%1>").arg(name);
|
|
||||||
param->def = def;
|
|
||||||
|
|
||||||
m_options[name] = param;
|
|
||||||
m_params[name] = (CommonDef *)param;
|
|
||||||
m_optionList.append(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::addOption(QString name, QVariant def)
|
|
||||||
{
|
|
||||||
if (m_params.contains(name))
|
|
||||||
throw "Name not unique";
|
|
||||||
|
|
||||||
OptionDef *param = new OptionDef;
|
|
||||||
param->type = otOption;
|
|
||||||
param->name = name;
|
|
||||||
param->metavar = QString("<%1>").arg(name);
|
|
||||||
param->def = def;
|
|
||||||
|
|
||||||
m_options[name] = param;
|
|
||||||
m_params[name] = (CommonDef *)param;
|
|
||||||
m_optionList.append(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::addArgument(QString name, bool required, QVariant def)
|
|
||||||
{
|
|
||||||
if (m_params.contains(name))
|
|
||||||
throw "Name not unique";
|
|
||||||
|
|
||||||
PositionalDef *param = new PositionalDef;
|
|
||||||
param->name = name;
|
|
||||||
param->def = def;
|
|
||||||
param->required = required;
|
|
||||||
param->metavar = name;
|
|
||||||
|
|
||||||
m_positionals.append(param);
|
|
||||||
m_params[name] = (CommonDef *)param;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::addDocumentation(QString name, QString doc, QString metavar)
|
|
||||||
{
|
|
||||||
if (!m_params.contains(name))
|
|
||||||
throw "Name does not exist";
|
|
||||||
|
|
||||||
CommonDef *param = m_params[name];
|
|
||||||
param->doc = doc;
|
|
||||||
if (!metavar.isNull())
|
|
||||||
param->metavar = metavar;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::addShortOpt(QString name, QChar flag)
|
|
||||||
{
|
|
||||||
if (!m_params.contains(name))
|
|
||||||
throw "Name does not exist";
|
|
||||||
if (!m_options.contains(name))
|
|
||||||
throw "Name is not an Option or Swtich";
|
|
||||||
|
|
||||||
OptionDef *param = m_options[name];
|
|
||||||
m_flags[flag] = param;
|
|
||||||
param->flag = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// help methods
|
|
||||||
QString Parser::compileHelp(QString progName, int helpIndent, bool useFlags)
|
|
||||||
{
|
|
||||||
QStringList help;
|
|
||||||
help << compileUsage(progName, useFlags) << "\r\n";
|
|
||||||
|
|
||||||
// positionals
|
|
||||||
if (!m_positionals.isEmpty())
|
|
||||||
{
|
|
||||||
help << "\r\n";
|
|
||||||
help << "Positional arguments:\r\n";
|
|
||||||
QListIterator<PositionalDef *> it2(m_positionals);
|
|
||||||
while (it2.hasNext())
|
|
||||||
{
|
|
||||||
PositionalDef *param = it2.next();
|
|
||||||
help << " " << param->metavar;
|
|
||||||
help << " " << QString(helpIndent - param->metavar.length() - 1, ' ');
|
|
||||||
help << param->doc << "\r\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options
|
|
||||||
if (!m_optionList.isEmpty())
|
|
||||||
{
|
|
||||||
help << "\r\n";
|
|
||||||
QString optPrefix, flagPrefix;
|
|
||||||
getPrefix(optPrefix, flagPrefix);
|
|
||||||
|
|
||||||
help << "Options & Switches:\r\n";
|
|
||||||
QListIterator<OptionDef *> it(m_optionList);
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
OptionDef *option = it.next();
|
|
||||||
help << " ";
|
|
||||||
int nameLength = optPrefix.length() + option->name.length();
|
|
||||||
if (!option->flag.isNull())
|
|
||||||
{
|
|
||||||
nameLength += 3 + flagPrefix.length();
|
|
||||||
help << flagPrefix << option->flag << ", ";
|
|
||||||
}
|
|
||||||
help << optPrefix << option->name;
|
|
||||||
if (option->type == otOption)
|
|
||||||
{
|
|
||||||
QString arg = QString("%1%2").arg(
|
|
||||||
((m_argStyle == ArgumentStyle::Equals) ? "=" : " "), option->metavar);
|
|
||||||
nameLength += arg.length();
|
|
||||||
help << arg;
|
|
||||||
}
|
|
||||||
help << " " << QString(helpIndent - nameLength - 1, ' ');
|
|
||||||
help << option->doc << "\r\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return help.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Parser::compileUsage(QString progName, bool useFlags)
|
|
||||||
{
|
|
||||||
QStringList usage;
|
|
||||||
usage << "Usage: " << progName;
|
|
||||||
|
|
||||||
QString optPrefix, flagPrefix;
|
|
||||||
getPrefix(optPrefix, flagPrefix);
|
|
||||||
|
|
||||||
// options
|
|
||||||
QListIterator<OptionDef *> it(m_optionList);
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
OptionDef *option = it.next();
|
|
||||||
usage << " [";
|
|
||||||
if (!option->flag.isNull() && useFlags)
|
|
||||||
usage << flagPrefix << option->flag;
|
|
||||||
else
|
|
||||||
usage << optPrefix << option->name;
|
|
||||||
if (option->type == otOption)
|
|
||||||
usage << ((m_argStyle == ArgumentStyle::Equals) ? "=" : " ") << option->metavar;
|
|
||||||
usage << "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
// arguments
|
|
||||||
QListIterator<PositionalDef *> it2(m_positionals);
|
|
||||||
while (it2.hasNext())
|
|
||||||
{
|
|
||||||
PositionalDef *param = it2.next();
|
|
||||||
usage << " " << (param->required ? "<" : "[");
|
|
||||||
usage << param->metavar;
|
|
||||||
usage << (param->required ? ">" : "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
return usage.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// parsing
|
|
||||||
QHash<QString, QVariant> Parser::parse(QStringList argv)
|
|
||||||
{
|
|
||||||
QHash<QString, QVariant> map;
|
|
||||||
|
|
||||||
QStringListIterator it(argv);
|
|
||||||
QString programName = it.next();
|
|
||||||
|
|
||||||
QString optionPrefix;
|
|
||||||
QString flagPrefix;
|
|
||||||
QListIterator<PositionalDef *> positionals(m_positionals);
|
|
||||||
QStringList expecting;
|
|
||||||
|
|
||||||
getPrefix(optionPrefix, flagPrefix);
|
|
||||||
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
QString arg = it.next();
|
|
||||||
|
|
||||||
if (!expecting.isEmpty())
|
|
||||||
// we were expecting an argument
|
|
||||||
{
|
|
||||||
QString name = expecting.first();
|
|
||||||
/*
|
|
||||||
if (map.contains(name))
|
|
||||||
throw ParsingError(
|
|
||||||
QString("Option %2%1 was given multiple times").arg(name, optionPrefix));
|
|
||||||
*/
|
|
||||||
map[name] = QVariant(arg);
|
|
||||||
|
|
||||||
expecting.removeFirst();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.startsWith(optionPrefix))
|
|
||||||
// we have an option
|
|
||||||
{
|
|
||||||
// qDebug("Found option %s", qPrintable(arg));
|
|
||||||
|
|
||||||
QString name = arg.mid(optionPrefix.length());
|
|
||||||
QString equals;
|
|
||||||
|
|
||||||
if ((m_argStyle == ArgumentStyle::Equals ||
|
|
||||||
m_argStyle == ArgumentStyle::SpaceAndEquals) &&
|
|
||||||
name.contains("="))
|
|
||||||
{
|
|
||||||
int i = name.indexOf("=");
|
|
||||||
equals = name.mid(i + 1);
|
|
||||||
name = name.left(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_options.contains(name))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (map.contains(name))
|
|
||||||
throw ParsingError(QString("Option %2%1 was given multiple times")
|
|
||||||
.arg(name, optionPrefix));
|
|
||||||
*/
|
|
||||||
OptionDef *option = m_options[name];
|
|
||||||
if (option->type == otSwitch)
|
|
||||||
map[name] = true;
|
|
||||||
else // if (option->type == otOption)
|
|
||||||
{
|
|
||||||
if (m_argStyle == ArgumentStyle::Space)
|
|
||||||
expecting.append(name);
|
|
||||||
else if (!equals.isNull())
|
|
||||||
map[name] = equals;
|
|
||||||
else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
|
|
||||||
expecting.append(name);
|
|
||||||
else
|
|
||||||
throw ParsingError(QString("Option %2%1 reqires an argument.")
|
|
||||||
.arg(name, optionPrefix));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw ParsingError(QString("Unknown Option %2%1").arg(name, optionPrefix));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.startsWith(flagPrefix))
|
|
||||||
// we have (a) flag(s)
|
|
||||||
{
|
|
||||||
// qDebug("Found flags %s", qPrintable(arg));
|
|
||||||
|
|
||||||
QString flags = arg.mid(flagPrefix.length());
|
|
||||||
QString equals;
|
|
||||||
|
|
||||||
if ((m_argStyle == ArgumentStyle::Equals ||
|
|
||||||
m_argStyle == ArgumentStyle::SpaceAndEquals) &&
|
|
||||||
flags.contains("="))
|
|
||||||
{
|
|
||||||
int i = flags.indexOf("=");
|
|
||||||
equals = flags.mid(i + 1);
|
|
||||||
flags = flags.left(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < flags.length(); i++)
|
|
||||||
{
|
|
||||||
QChar flag = flags.at(i);
|
|
||||||
|
|
||||||
if (!m_flags.contains(flag))
|
|
||||||
throw ParsingError(QString("Unknown flag %2%1").arg(flag, flagPrefix));
|
|
||||||
|
|
||||||
OptionDef *option = m_flags[flag];
|
|
||||||
/*
|
|
||||||
if (map.contains(option->name))
|
|
||||||
throw ParsingError(QString("Option %2%1 was given multiple times")
|
|
||||||
.arg(option->name, optionPrefix));
|
|
||||||
*/
|
|
||||||
if (option->type == otSwitch)
|
|
||||||
map[option->name] = true;
|
|
||||||
else // if (option->type == otOption)
|
|
||||||
{
|
|
||||||
if (m_argStyle == ArgumentStyle::Space)
|
|
||||||
expecting.append(option->name);
|
|
||||||
else if (!equals.isNull())
|
|
||||||
if (i == flags.length() - 1)
|
|
||||||
map[option->name] = equals;
|
|
||||||
else
|
|
||||||
throw ParsingError(QString("Flag %4%2 of Argument-requiring Option "
|
|
||||||
"%1 not last flag in %4%3")
|
|
||||||
.arg(option->name, flag, flags, flagPrefix));
|
|
||||||
else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
|
|
||||||
expecting.append(option->name);
|
|
||||||
else
|
|
||||||
throw ParsingError(QString("Option %1 reqires an argument. (flag %3%2)")
|
|
||||||
.arg(option->name, flag, flagPrefix));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// must be a positional argument
|
|
||||||
if (!positionals.hasNext())
|
|
||||||
throw ParsingError(QString("Don't know what to do with '%1'").arg(arg));
|
|
||||||
|
|
||||||
PositionalDef *param = positionals.next();
|
|
||||||
|
|
||||||
map[param->name] = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we're missing something
|
|
||||||
if (!expecting.isEmpty())
|
|
||||||
throw ParsingError(QString("Was still expecting arguments for %2%1").arg(
|
|
||||||
expecting.join(QString(", ") + optionPrefix), optionPrefix));
|
|
||||||
|
|
||||||
while (positionals.hasNext())
|
|
||||||
{
|
|
||||||
PositionalDef *param = positionals.next();
|
|
||||||
if (param->required)
|
|
||||||
throw ParsingError(
|
|
||||||
QString("Missing required positional argument '%1'").arg(param->name));
|
|
||||||
else
|
|
||||||
map[param->name] = param->def;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill out gaps
|
|
||||||
QListIterator<OptionDef *> iter(m_optionList);
|
|
||||||
while (iter.hasNext())
|
|
||||||
{
|
|
||||||
OptionDef *option = iter.next();
|
|
||||||
if (!map.contains(option->name))
|
|
||||||
map[option->name] = option->def;
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear defs
|
|
||||||
void Parser::clear()
|
|
||||||
{
|
|
||||||
m_flags.clear();
|
|
||||||
m_params.clear();
|
|
||||||
m_options.clear();
|
|
||||||
|
|
||||||
QMutableListIterator<OptionDef *> it(m_optionList);
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
OptionDef *option = it.next();
|
|
||||||
it.remove();
|
|
||||||
delete option;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMutableListIterator<PositionalDef *> it2(m_positionals);
|
|
||||||
while (it2.hasNext())
|
|
||||||
{
|
|
||||||
PositionalDef *arg = it2.next();
|
|
||||||
it2.remove();
|
|
||||||
delete arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
Parser::~Parser()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPrefix
|
|
||||||
void Parser::getPrefix(QString &opt, QString &flag)
|
|
||||||
{
|
|
||||||
if (m_flagStyle == FlagStyle::Windows)
|
|
||||||
opt = flag = "/";
|
|
||||||
else if (m_flagStyle == FlagStyle::Unix)
|
|
||||||
opt = flag = "-";
|
|
||||||
// else if (m_flagStyle == FlagStyle::GNU)
|
|
||||||
else
|
|
||||||
{
|
|
||||||
opt = "--";
|
|
||||||
flag = "-";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParsingError
|
|
||||||
ParsingError::ParsingError(const QString &what) : std::runtime_error(what.toStdString())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -17,12 +17,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
|
||||||
#include <QHash>
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,8 +25,7 @@
|
|||||||
* @brief commandline parsing and processing utilities
|
* @brief commandline parsing and processing utilities
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Commandline
|
namespace Commandline {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief split a string into argv items like a shell would do
|
* @brief split a string into argv items like a shell would do
|
||||||
@ -39,212 +33,4 @@ namespace Commandline
|
|||||||
* @return a QStringList containing all arguments
|
* @return a QStringList containing all arguments
|
||||||
*/
|
*/
|
||||||
QStringList splitArgs(QString args);
|
QStringList splitArgs(QString args);
|
||||||
|
} // namespace Commandline
|
||||||
/**
|
|
||||||
* @brief The FlagStyle enum
|
|
||||||
* Specifies how flags are decorated
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace FlagStyle
|
|
||||||
{
|
|
||||||
enum Enum
|
|
||||||
{
|
|
||||||
GNU, /**< --option and -o (GNU Style) */
|
|
||||||
Unix, /**< -option and -o (Unix Style) */
|
|
||||||
Windows, /**< /option and /o (Windows Style) */
|
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
Default = Windows
|
|
||||||
#else
|
|
||||||
Default = GNU
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The ArgumentStyle enum
|
|
||||||
*/
|
|
||||||
namespace ArgumentStyle
|
|
||||||
{
|
|
||||||
enum Enum
|
|
||||||
{
|
|
||||||
Space, /**< --option value */
|
|
||||||
Equals, /**< --option=value */
|
|
||||||
SpaceAndEquals, /**< --option[= ]value */
|
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
Default = Equals
|
|
||||||
#else
|
|
||||||
Default = SpaceAndEquals
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The ParsingError class
|
|
||||||
*/
|
|
||||||
class ParsingError : public std::runtime_error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ParsingError(const QString &what);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The Parser class
|
|
||||||
*/
|
|
||||||
class Parser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Parser constructor
|
|
||||||
* @param flagStyle the FlagStyle to use in this Parser
|
|
||||||
* @param argStyle the ArgumentStyle to use in this Parser
|
|
||||||
*/
|
|
||||||
Parser(FlagStyle::Enum flagStyle = FlagStyle::Default,
|
|
||||||
ArgumentStyle::Enum argStyle = ArgumentStyle::Default);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief set the flag style
|
|
||||||
* @param style
|
|
||||||
*/
|
|
||||||
void setFlagStyle(FlagStyle::Enum style);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief get the flag style
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
FlagStyle::Enum flagStyle();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief set the argument style
|
|
||||||
* @param style
|
|
||||||
*/
|
|
||||||
void setArgumentStyle(ArgumentStyle::Enum style);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief get the argument style
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ArgumentStyle::Enum argumentStyle();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief define a boolean switch
|
|
||||||
* @param name the parameter name
|
|
||||||
* @param def the default value
|
|
||||||
*/
|
|
||||||
void addSwitch(QString name, bool def = false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief define an option that takes an additional argument
|
|
||||||
* @param name the parameter name
|
|
||||||
* @param def the default value
|
|
||||||
*/
|
|
||||||
void addOption(QString name, QVariant def = QVariant());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief define a positional argument
|
|
||||||
* @param name the parameter name
|
|
||||||
* @param required wether this argument is required
|
|
||||||
* @param def the default value
|
|
||||||
*/
|
|
||||||
void addArgument(QString name, bool required = true, QVariant def = QVariant());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief adds a flag to an existing parameter
|
|
||||||
* @param name the (existing) parameter name
|
|
||||||
* @param flag the flag character
|
|
||||||
* @see addSwitch addArgument addOption
|
|
||||||
* Note: any one parameter can only have one flag
|
|
||||||
*/
|
|
||||||
void addShortOpt(QString name, QChar flag);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief adds documentation to a Parameter
|
|
||||||
* @param name the parameter name
|
|
||||||
* @param metavar a string to be displayed as placeholder for the value
|
|
||||||
* @param doc a QString containing the documentation
|
|
||||||
* Note: on positional arguments, metavar replaces the name as displayed.
|
|
||||||
* on options , metavar replaces the value placeholder
|
|
||||||
*/
|
|
||||||
void addDocumentation(QString name, QString doc, QString metavar = QString());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief generate a help message
|
|
||||||
* @param progName the program name to use in the help message
|
|
||||||
* @param helpIndent how much the parameter documentation should be indented
|
|
||||||
* @param flagsInUsage whether we should use flags instead of options in the usage
|
|
||||||
* @return a help message
|
|
||||||
*/
|
|
||||||
QString compileHelp(QString progName, int helpIndent = 22, bool flagsInUsage = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief generate a short usage message
|
|
||||||
* @param progName the program name to use in the usage message
|
|
||||||
* @param useFlags whether we should use flags instead of options
|
|
||||||
* @return a usage message
|
|
||||||
*/
|
|
||||||
QString compileUsage(QString progName, bool useFlags = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief parse
|
|
||||||
* @param argv a QStringList containing the program ARGV
|
|
||||||
* @return a QHash mapping argument names to their values
|
|
||||||
*/
|
|
||||||
QHash<QString, QVariant> parse(QStringList argv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief clear all definitions
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
~Parser();
|
|
||||||
|
|
||||||
private:
|
|
||||||
FlagStyle::Enum m_flagStyle;
|
|
||||||
ArgumentStyle::Enum m_argStyle;
|
|
||||||
|
|
||||||
enum OptionType
|
|
||||||
{
|
|
||||||
otSwitch,
|
|
||||||
otOption
|
|
||||||
};
|
|
||||||
|
|
||||||
// Important: the common part MUST BE COMMON ON ALL THREE structs
|
|
||||||
struct CommonDef
|
|
||||||
{
|
|
||||||
QString name;
|
|
||||||
QString doc;
|
|
||||||
QString metavar;
|
|
||||||
QVariant def;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OptionDef
|
|
||||||
{
|
|
||||||
// common
|
|
||||||
QString name;
|
|
||||||
QString doc;
|
|
||||||
QString metavar;
|
|
||||||
QVariant def;
|
|
||||||
// option
|
|
||||||
OptionType type;
|
|
||||||
QChar flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PositionalDef
|
|
||||||
{
|
|
||||||
// common
|
|
||||||
QString name;
|
|
||||||
QString doc;
|
|
||||||
QString metavar;
|
|
||||||
QVariant def;
|
|
||||||
// positional
|
|
||||||
bool required;
|
|
||||||
};
|
|
||||||
|
|
||||||
QHash<QString, OptionDef *> m_options;
|
|
||||||
QHash<QChar, OptionDef *> m_flags;
|
|
||||||
QHash<QString, CommonDef *> m_params;
|
|
||||||
QList<PositionalDef *> m_positionals;
|
|
||||||
QList<OptionDef *> m_optionList;
|
|
||||||
|
|
||||||
void getPrefix(QString &opt, QString &flag);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
96
launcher/DataMigrationTask.cpp
Normal file
96
launcher/DataMigrationTask.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
#include "DataMigrationTask.h"
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
|
DataMigrationTask::DataMigrationTask(QObject* parent,
|
||||||
|
const QString& sourcePath,
|
||||||
|
const QString& targetPath,
|
||||||
|
const IPathMatcher::Ptr pathMatcher)
|
||||||
|
: Task(parent), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
|
||||||
|
{
|
||||||
|
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataMigrationTask::executeTask()
|
||||||
|
{
|
||||||
|
setStatus(tr("Scanning files..."));
|
||||||
|
|
||||||
|
// 1. Scan
|
||||||
|
// Check how many files we gotta copy
|
||||||
|
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
||||||
|
return m_copy(true); // dry run to collect amount of files
|
||||||
|
});
|
||||||
|
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
||||||
|
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
||||||
|
m_copyFutureWatcher.setFuture(m_copyFuture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataMigrationTask::dryRunFinished()
|
||||||
|
{
|
||||||
|
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
||||||
|
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
|
||||||
|
#else
|
||||||
|
if (!m_copyFuture.result()) {
|
||||||
|
#endif
|
||||||
|
emitFailed(tr("Failed to scan source path."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Copy
|
||||||
|
// Actually copy all files now.
|
||||||
|
m_toCopy = m_copy.totalCopied();
|
||||||
|
connect(&m_copy, &FS::copy::fileCopied, [&, this](const QString& relativeName) {
|
||||||
|
QString shortenedName = relativeName;
|
||||||
|
// shorten the filename to hopefully fit into one line
|
||||||
|
if (shortenedName.length() > 50)
|
||||||
|
shortenedName = relativeName.left(20) + "…" + relativeName.right(29);
|
||||||
|
setProgress(m_copy.totalCopied(), m_toCopy);
|
||||||
|
setStatus(tr("Copying %1…").arg(shortenedName));
|
||||||
|
});
|
||||||
|
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
||||||
|
return m_copy(false); // actually copy now
|
||||||
|
});
|
||||||
|
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
||||||
|
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
||||||
|
m_copyFutureWatcher.setFuture(m_copyFuture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataMigrationTask::dryRunAborted()
|
||||||
|
{
|
||||||
|
emitFailed(tr("Aborted"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataMigrationTask::copyFinished()
|
||||||
|
{
|
||||||
|
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
||||||
|
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
if (!m_copyFuture.isValid() || !m_copyFuture.result()) {
|
||||||
|
#else
|
||||||
|
if (!m_copyFuture.result()) {
|
||||||
|
#endif
|
||||||
|
emitFailed(tr("Some paths could not be copied!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataMigrationTask::copyAborted()
|
||||||
|
{
|
||||||
|
emitFailed(tr("Aborted"));
|
||||||
|
}
|
42
launcher/DataMigrationTask.h
Normal file
42
launcher/DataMigrationTask.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "pathmatcher/IPathMatcher.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
#include <QFuture>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Migrate existing data from other MMC-like launchers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DataMigrationTask : public Task {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DataMigrationTask(QObject* parent, const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathmatcher);
|
||||||
|
~DataMigrationTask() override = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void executeTask() override;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void dryRunFinished();
|
||||||
|
void dryRunAborted();
|
||||||
|
void copyFinished();
|
||||||
|
void copyAborted();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString& m_sourcePath;
|
||||||
|
const QString& m_targetPath;
|
||||||
|
const IPathMatcher::Ptr m_pathMatcher;
|
||||||
|
|
||||||
|
FS::copy m_copy;
|
||||||
|
int m_toCopy = 0;
|
||||||
|
QFuture<bool> m_copyFuture;
|
||||||
|
QFutureWatcher<bool> m_copyFutureWatcher;
|
||||||
|
};
|
@ -1,33 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class DefaultVariable
|
class DefaultVariable {
|
||||||
{
|
public:
|
||||||
public:
|
DefaultVariable(const T& value) { defaultValue = value; }
|
||||||
DefaultVariable(const T & value)
|
DefaultVariable<T>& operator=(const T& value)
|
||||||
{
|
|
||||||
defaultValue = value;
|
|
||||||
}
|
|
||||||
DefaultVariable<T> & operator =(const T & value)
|
|
||||||
{
|
{
|
||||||
currentValue = value;
|
currentValue = value;
|
||||||
is_default = currentValue == defaultValue;
|
is_default = currentValue == defaultValue;
|
||||||
is_explicit = true;
|
is_explicit = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
operator const T &() const
|
operator const T&() const { return is_default ? defaultValue : currentValue; }
|
||||||
{
|
bool isDefault() const { return is_default; }
|
||||||
return is_default ? defaultValue : currentValue;
|
bool isExplicit() const { return is_explicit; }
|
||||||
}
|
|
||||||
bool isDefault() const
|
private:
|
||||||
{
|
|
||||||
return is_default;
|
|
||||||
}
|
|
||||||
bool isExplicit() const
|
|
||||||
{
|
|
||||||
return is_explicit;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
T currentValue;
|
T currentValue;
|
||||||
T defaultValue;
|
T defaultValue;
|
||||||
bool is_default = true;
|
bool is_default = true;
|
||||||
|
@ -1,38 +1,69 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 dada513 <dada513@protonmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2022 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
#include "DesktopServices.h"
|
#include "DesktopServices.h"
|
||||||
#include <QDir>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing.
|
* This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing.
|
||||||
*/
|
*/
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool IndirectOpen(T callable, qint64 *pid_forked = nullptr)
|
bool IndirectOpen(T callable, qint64* pid_forked = nullptr)
|
||||||
{
|
{
|
||||||
auto pid = fork();
|
auto pid = fork();
|
||||||
if(pid_forked)
|
if (pid_forked) {
|
||||||
{
|
if (pid > 0)
|
||||||
if(pid > 0)
|
|
||||||
*pid_forked = pid;
|
*pid_forked = pid;
|
||||||
else
|
else
|
||||||
*pid_forked = 0;
|
*pid_forked = 0;
|
||||||
}
|
}
|
||||||
if(pid == -1)
|
if (pid == -1) {
|
||||||
{
|
|
||||||
qWarning() << "IndirectOpen failed to fork: " << errno;
|
qWarning() << "IndirectOpen failed to fork: " << errno;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// child - do the stuff
|
// child - do the stuff
|
||||||
if(pid == 0)
|
if (pid == 0) {
|
||||||
{
|
|
||||||
// unset all this garbage so it doesn't get passed to the child process
|
// unset all this garbage so it doesn't get passed to the child process
|
||||||
qunsetenv("LD_PRELOAD");
|
qunsetenv("LD_PRELOAD");
|
||||||
qunsetenv("LD_LIBRARY_PATH");
|
qunsetenv("LD_LIBRARY_PATH");
|
||||||
@ -48,19 +79,14 @@ bool IndirectOpen(T callable, qint64 *pid_forked = nullptr)
|
|||||||
|
|
||||||
// die. now. do not clean up anything, it would just hang forever.
|
// die. now. do not clean up anything, it would just hang forever.
|
||||||
_exit(status ? 0 : 1);
|
_exit(status ? 0 : 1);
|
||||||
}
|
} else {
|
||||||
else
|
// parent - assume it worked.
|
||||||
{
|
|
||||||
//parent - assume it worked.
|
|
||||||
int status;
|
int status;
|
||||||
while (waitpid(pid, &status, 0))
|
while (waitpid(pid, &status, 0)) {
|
||||||
{
|
if (WIFEXITED(status)) {
|
||||||
if(WIFEXITED(status))
|
|
||||||
{
|
|
||||||
return WEXITSTATUS(status) == 0;
|
return WEXITSTATUS(status) == 0;
|
||||||
}
|
}
|
||||||
if(WIFSIGNALED(status))
|
if (WIFSIGNALED(status)) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,80 +96,107 @@ bool IndirectOpen(T callable, qint64 *pid_forked = nullptr)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace DesktopServices {
|
namespace DesktopServices {
|
||||||
bool openDirectory(const QString &path, bool ensureExists)
|
bool openDirectory(const QString& path, [[maybe_unused]] bool ensureExists)
|
||||||
{
|
{
|
||||||
qDebug() << "Opening directory" << path;
|
qDebug() << "Opening directory" << path;
|
||||||
QDir parentPath;
|
QDir parentPath;
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
if (!dir.exists())
|
if (ensureExists && !dir.exists()) {
|
||||||
{
|
|
||||||
parentPath.mkpath(dir.absolutePath());
|
parentPath.mkpath(dir.absolutePath());
|
||||||
}
|
}
|
||||||
auto f = [&]()
|
auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); };
|
||||||
{
|
|
||||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
|
|
||||||
};
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
return IndirectOpen(f);
|
if (!isSandbox()) {
|
||||||
|
return IndirectOpen(f);
|
||||||
|
} else {
|
||||||
|
return f();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return f();
|
return f();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool openFile(const QString &path)
|
bool openFile(const QString& path)
|
||||||
{
|
{
|
||||||
qDebug() << "Opening file" << path;
|
qDebug() << "Opening file" << path;
|
||||||
auto f = [&]()
|
auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); };
|
||||||
{
|
|
||||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
|
||||||
};
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
return IndirectOpen(f);
|
if (!isSandbox()) {
|
||||||
|
return IndirectOpen(f);
|
||||||
|
} else {
|
||||||
|
return f();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return f();
|
return f();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool openFile(const QString &application, const QString &path, const QString &workingDirectory, qint64 *pid)
|
bool openFile(const QString& application, const QString& path, const QString& workingDirectory, qint64* pid)
|
||||||
{
|
{
|
||||||
qDebug() << "Opening file" << path << "using" << application;
|
qDebug() << "Opening file" << path << "using" << application;
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
||||||
return IndirectOpen([&]()
|
if (!isSandbox()) {
|
||||||
{
|
return IndirectOpen([&]() { return QProcess::startDetached(application, QStringList() << path, workingDirectory); }, pid);
|
||||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory);
|
} else {
|
||||||
}, pid);
|
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool run(const QString &application, const QStringList &args, const QString &workingDirectory, qint64 *pid)
|
bool run(const QString& application, const QStringList& args, const QString& workingDirectory, qint64* pid)
|
||||||
{
|
{
|
||||||
qDebug() << "Running" << application << "with args" << args.join(' ');
|
qDebug() << "Running" << application << "with args" << args.join(' ');
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
if (!isSandbox()) {
|
||||||
return IndirectOpen([&]()
|
// FIXME: the pid here is fake. So if something depends on it, it will likely misbehave
|
||||||
{
|
return IndirectOpen([&]() { return QProcess::startDetached(application, args, workingDirectory); }, pid);
|
||||||
return QProcess::startDetached(application, args, workingDirectory);
|
} else {
|
||||||
}, pid);
|
return QProcess::startDetached(application, args, workingDirectory, pid);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return QProcess::startDetached(application, args, workingDirectory, pid);
|
return QProcess::startDetached(application, args, workingDirectory, pid);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool openUrl(const QUrl &url)
|
bool openUrl(const QUrl& url)
|
||||||
{
|
{
|
||||||
qDebug() << "Opening URL" << url.toString();
|
qDebug() << "Opening URL" << url.toString();
|
||||||
auto f = [&]()
|
auto f = [&]() { return QDesktopServices::openUrl(url); };
|
||||||
{
|
|
||||||
return QDesktopServices::openUrl(url);
|
|
||||||
};
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
return IndirectOpen(f);
|
if (!isSandbox()) {
|
||||||
|
return IndirectOpen(f);
|
||||||
|
} else {
|
||||||
|
return f();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return f();
|
return f();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isFlatpak()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
return QFile::exists("/.flatpak-info");
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSnap()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
return getenv("SNAP");
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSandbox()
|
||||||
|
{
|
||||||
|
return isSnap() || isFlatpak();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace DesktopServices
|
||||||
|
@ -1,36 +1,50 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This wraps around QDesktopServices and adds workarounds where needed
|
* This wraps around QDesktopServices and adds workarounds where needed
|
||||||
* Use this instead of QDesktopServices!
|
* Use this instead of QDesktopServices!
|
||||||
*/
|
*/
|
||||||
namespace DesktopServices
|
namespace DesktopServices {
|
||||||
{
|
/**
|
||||||
/**
|
* Open a file in whatever application is applicable
|
||||||
* Open a file in whatever application is applicable
|
*/
|
||||||
*/
|
bool openFile(const QString& path);
|
||||||
bool openFile(const QString &path);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a file in the specified application
|
* Open a file in the specified application
|
||||||
*/
|
*/
|
||||||
bool openFile(const QString &application, const QString &path, const QString & workingDirectory = QString(), qint64 *pid = 0);
|
bool openFile(const QString& application, const QString& path, const QString& workingDirectory = QString(), qint64* pid = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run an application
|
* Run an application
|
||||||
*/
|
*/
|
||||||
bool run(const QString &application,const QStringList &args, const QString & workingDirectory = QString(), qint64 *pid = 0);
|
bool run(const QString& application, const QStringList& args, const QString& workingDirectory = QString(), qint64* pid = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a directory
|
* Open a directory
|
||||||
*/
|
*/
|
||||||
bool openDirectory(const QString &path, bool ensureExists = false);
|
bool openDirectory(const QString& path, bool ensureExists = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the URL, most likely in a browser. Maybe.
|
* Open the URL, most likely in a browser. Maybe.
|
||||||
*/
|
*/
|
||||||
bool openUrl(const QUrl &url);
|
bool openUrl(const QUrl& url);
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Determine whether the launcher is running in a Flatpak environment
|
||||||
|
*/
|
||||||
|
bool isFlatpak();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the launcher is running in a Snap environment
|
||||||
|
*/
|
||||||
|
bool isSnap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the launcher is running in a sandboxed (Flatpak or Snap) environment
|
||||||
|
*/
|
||||||
|
bool isSandbox();
|
||||||
|
} // namespace DesktopServices
|
||||||
|
@ -2,31 +2,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
class Exception : public std::exception
|
class Exception : public std::exception {
|
||||||
{
|
public:
|
||||||
public:
|
Exception(const QString& message) : std::exception(), m_message(message) { qCritical() << "Exception:" << message; }
|
||||||
Exception(const QString &message) : std::exception(), m_message(message)
|
Exception(const Exception& other) : std::exception(), m_message(other.cause()) {}
|
||||||
{
|
|
||||||
qCritical() << "Exception:" << message;
|
|
||||||
}
|
|
||||||
Exception(const Exception &other)
|
|
||||||
: std::exception(), m_message(other.cause())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual ~Exception() noexcept {}
|
virtual ~Exception() noexcept {}
|
||||||
const char *what() const noexcept
|
const char* what() const noexcept { return m_message.toLatin1().constData(); }
|
||||||
{
|
QString cause() const { return m_message; }
|
||||||
return m_message.toLatin1().constData();
|
|
||||||
}
|
|
||||||
QString cause() const
|
|
||||||
{
|
|
||||||
return m_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_message;
|
QString m_message;
|
||||||
};
|
};
|
||||||
|
@ -4,31 +4,24 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline void clamp(T& current, T min, T max)
|
inline void clamp(T& current, T min, T max)
|
||||||
{
|
{
|
||||||
if (current < min)
|
if (current < min) {
|
||||||
{
|
|
||||||
current = min;
|
current = min;
|
||||||
}
|
} else if (current > max) {
|
||||||
else if(current > max)
|
|
||||||
{
|
|
||||||
current = max;
|
current = max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of numbers from min to max. Next is exponent times bigger than previous.
|
// List of numbers from min to max. Next is exponent times bigger than previous.
|
||||||
|
|
||||||
class ExponentialSeries
|
class ExponentialSeries {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2)
|
ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2)
|
||||||
{
|
{
|
||||||
m_current = m_min = min;
|
m_current = m_min = min;
|
||||||
m_max = max;
|
m_max = max;
|
||||||
m_exponent = exponent;
|
m_exponent = exponent;
|
||||||
}
|
}
|
||||||
void reset()
|
void reset() { m_current = m_min; }
|
||||||
{
|
|
||||||
m_current = m_min;
|
|
||||||
}
|
|
||||||
unsigned operator()()
|
unsigned operator()()
|
||||||
{
|
{
|
||||||
unsigned retval = m_current;
|
unsigned retval = m_current;
|
||||||
|
47
launcher/FastFileIconProvider.cpp
Normal file
47
launcher/FastFileIconProvider.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FastFileIconProvider.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QStyle>
|
||||||
|
|
||||||
|
QIcon FastFileIconProvider::icon(const QFileInfo& info) const
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
|
||||||
|
bool link = info.isSymbolicLink() || info.isAlias() || info.isShortcut();
|
||||||
|
#else
|
||||||
|
// in versions prior to 6.4 we don't have access to isAlias
|
||||||
|
bool link = info.isSymLink();
|
||||||
|
#endif
|
||||||
|
QStyle::StandardPixmap icon;
|
||||||
|
|
||||||
|
if (info.isDir()) {
|
||||||
|
if (link)
|
||||||
|
icon = QStyle::SP_DirLinkIcon;
|
||||||
|
else
|
||||||
|
icon = QStyle::SP_DirIcon;
|
||||||
|
} else {
|
||||||
|
if (link)
|
||||||
|
icon = QStyle::SP_FileLinkIcon;
|
||||||
|
else
|
||||||
|
icon = QStyle::SP_FileIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QApplication::style()->standardIcon(icon);
|
||||||
|
}
|
26
launcher/FastFileIconProvider.h
Normal file
26
launcher/FastFileIconProvider.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFileIconProvider>
|
||||||
|
|
||||||
|
class FastFileIconProvider : public QFileIconProvider {
|
||||||
|
public:
|
||||||
|
QIcon icon(const QFileInfo& info) const override;
|
||||||
|
};
|
276
launcher/FileIgnoreProxy.cpp
Normal file
276
launcher/FileIgnoreProxy.cpp
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FileIgnoreProxy.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFileSystemModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QStack>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "SeparatorPrefixTree.h"
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {}
|
||||||
|
// NOTE: Sadly, we have to do sorting ourselves.
|
||||||
|
bool FileIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const
|
||||||
|
{
|
||||||
|
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||||
|
if (!fsm) {
|
||||||
|
return QSortFilterProxyModel::lessThan(left, right);
|
||||||
|
}
|
||||||
|
bool asc = sortOrder() == Qt::AscendingOrder ? true : false;
|
||||||
|
|
||||||
|
QFileInfo leftFileInfo = fsm->fileInfo(left);
|
||||||
|
QFileInfo rightFileInfo = fsm->fileInfo(right);
|
||||||
|
|
||||||
|
if (!leftFileInfo.isDir() && rightFileInfo.isDir()) {
|
||||||
|
return !asc;
|
||||||
|
}
|
||||||
|
if (leftFileInfo.isDir() && !rightFileInfo.isDir()) {
|
||||||
|
return asc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort and proxy model breaks the original model...
|
||||||
|
if (sortColumn() == 0) {
|
||||||
|
return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0;
|
||||||
|
}
|
||||||
|
if (sortColumn() == 1) {
|
||||||
|
auto leftSize = leftFileInfo.size();
|
||||||
|
auto rightSize = rightFileInfo.size();
|
||||||
|
if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) {
|
||||||
|
return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0 ? asc : !asc;
|
||||||
|
}
|
||||||
|
return leftSize < rightSize;
|
||||||
|
}
|
||||||
|
return QSortFilterProxyModel::lessThan(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags FileIgnoreProxy::flags(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return Qt::NoItemFlags;
|
||||||
|
|
||||||
|
auto sourceIndex = mapToSource(index);
|
||||||
|
Qt::ItemFlags flags = sourceIndex.flags();
|
||||||
|
if (index.column() == 0) {
|
||||||
|
flags |= Qt::ItemIsUserCheckable;
|
||||||
|
if (sourceIndex.model()->hasChildren(sourceIndex)) {
|
||||||
|
flags |= Qt::ItemIsAutoTristate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant FileIgnoreProxy::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
QModelIndex sourceIndex = mapToSource(index);
|
||||||
|
|
||||||
|
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||||
|
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||||
|
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||||
|
auto cover = blocked.cover(blockedPath);
|
||||||
|
if (!cover.isNull()) {
|
||||||
|
return QVariant(Qt::Unchecked);
|
||||||
|
} else if (blocked.exists(blockedPath)) {
|
||||||
|
return QVariant(Qt::PartiallyChecked);
|
||||||
|
} else {
|
||||||
|
return QVariant(Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sourceIndex.data(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||||
|
{
|
||||||
|
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||||
|
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
|
||||||
|
return setFilterState(index, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex sourceIndex = mapToSource(index);
|
||||||
|
return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileIgnoreProxy::relPath(const QString& path) const
|
||||||
|
{
|
||||||
|
return QDir(root).relativeFilePath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state)
|
||||||
|
{
|
||||||
|
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||||
|
|
||||||
|
if (!fsm) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex sourceIndex = mapToSource(index);
|
||||||
|
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||||
|
bool changed = false;
|
||||||
|
if (state == Qt::Unchecked) {
|
||||||
|
// blocking a path
|
||||||
|
auto& node = blocked.insert(blockedPath);
|
||||||
|
// get rid of all blocked nodes below
|
||||||
|
node.clear();
|
||||||
|
changed = true;
|
||||||
|
} else if (state == Qt::Checked || state == Qt::PartiallyChecked) {
|
||||||
|
if (!blocked.remove(blockedPath)) {
|
||||||
|
auto cover = blocked.cover(blockedPath);
|
||||||
|
qDebug() << "Blocked by cover" << cover;
|
||||||
|
// uncover
|
||||||
|
blocked.remove(cover);
|
||||||
|
// block all contents, except for any cover
|
||||||
|
QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover));
|
||||||
|
QModelIndex doing = rootIndex;
|
||||||
|
int row = 0;
|
||||||
|
QStack<QModelIndex> todo;
|
||||||
|
while (1) {
|
||||||
|
auto node = fsm->index(row, 0, doing);
|
||||||
|
if (!node.isValid()) {
|
||||||
|
if (!todo.size()) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
doing = todo.pop();
|
||||||
|
row = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto relpath = relPath(fsm->filePath(node));
|
||||||
|
if (blockedPath.startsWith(relpath)) // cover found?
|
||||||
|
{
|
||||||
|
// continue processing cover later
|
||||||
|
todo.push(node);
|
||||||
|
} else {
|
||||||
|
// or just block this one.
|
||||||
|
blocked.insert(relpath);
|
||||||
|
}
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
// update the thing
|
||||||
|
emit dataChanged(index, index, { Qt::CheckStateRole });
|
||||||
|
// update everything above index
|
||||||
|
QModelIndex up = index.parent();
|
||||||
|
while (1) {
|
||||||
|
if (!up.isValid())
|
||||||
|
break;
|
||||||
|
emit dataChanged(up, up, { Qt::CheckStateRole });
|
||||||
|
up = up.parent();
|
||||||
|
}
|
||||||
|
// and everything below the index
|
||||||
|
QModelIndex doing = index;
|
||||||
|
int row = 0;
|
||||||
|
QStack<QModelIndex> todo;
|
||||||
|
while (1) {
|
||||||
|
auto node = this->index(row, 0, doing);
|
||||||
|
if (!node.isValid()) {
|
||||||
|
if (!todo.size()) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
doing = todo.pop();
|
||||||
|
row = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit dataChanged(node, node, { Qt::CheckStateRole });
|
||||||
|
todo.push(node);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
// siblings and unrelated nodes are ignored
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::shouldExpand(QModelIndex index)
|
||||||
|
{
|
||||||
|
QModelIndex sourceIndex = mapToSource(index);
|
||||||
|
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||||
|
if (!fsm) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||||
|
auto found = blocked.find(blockedPath);
|
||||||
|
if (found) {
|
||||||
|
return !found->leaf();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileIgnoreProxy::setBlockedPaths(QStringList paths)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
blocked.clear();
|
||||||
|
blocked.insert(paths);
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(source_parent)
|
||||||
|
|
||||||
|
// adjust the columns you want to filter out here
|
||||||
|
// return false for those that will be hidden
|
||||||
|
if (source_column == 2 || source_column == 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||||
|
QFileSystemModel* fsm = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||||
|
|
||||||
|
auto fileInfo = fsm->fileInfo(index);
|
||||||
|
return !ignoreFile(fileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const
|
||||||
|
{
|
||||||
|
return m_ignoreFiles.contains(fileInfo.fileName()) || m_ignoreFilePaths.covers(relPath(fileInfo.absoluteFilePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileIgnoreProxy::filterFile(const QString& fileName) const
|
||||||
|
{
|
||||||
|
return blocked.covers(fileName) || ignoreFile(QFileInfo(QDir(root), fileName));
|
||||||
|
}
|
85
launcher/FileIgnoreProxy.h
Normal file
85
launcher/FileIgnoreProxy.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include "SeparatorPrefixTree.h"
|
||||||
|
|
||||||
|
class FileIgnoreProxy : public QSortFilterProxyModel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileIgnoreProxy(QString root, QObject* parent);
|
||||||
|
// NOTE: Sadly, we have to do sorting ourselves.
|
||||||
|
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
|
||||||
|
|
||||||
|
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||||
|
|
||||||
|
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||||
|
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
||||||
|
|
||||||
|
QString relPath(const QString& path) const;
|
||||||
|
|
||||||
|
bool setFilterState(QModelIndex index, Qt::CheckState state);
|
||||||
|
|
||||||
|
bool shouldExpand(QModelIndex index);
|
||||||
|
|
||||||
|
void setBlockedPaths(QStringList paths);
|
||||||
|
|
||||||
|
inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; }
|
||||||
|
inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; }
|
||||||
|
|
||||||
|
// list of file names that need to be removed completely from model
|
||||||
|
inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; }
|
||||||
|
// list of relative paths that need to be removed completely from model
|
||||||
|
inline SeparatorPrefixTree<'/'>& ignoreFilesWithPath() { return m_ignoreFilePaths; }
|
||||||
|
|
||||||
|
bool filterFile(const QString& fileName) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const;
|
||||||
|
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
|
||||||
|
|
||||||
|
bool ignoreFile(QFileInfo file) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString root;
|
||||||
|
SeparatorPrefixTree<'/'> blocked;
|
||||||
|
QStringList m_ignoreFiles;
|
||||||
|
SeparatorPrefixTree<'/'> m_ignoreFilePaths;
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
@ -1,36 +1,85 @@
|
|||||||
// Licensed under the Apache-2.0 license. See README.md for details.
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
||||||
|
* Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
#include "pathmatcher/IPathMatcher.h"
|
#include "pathmatcher/IPathMatcher.h"
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFlags>
|
#include <QFlags>
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
namespace FS
|
namespace FS {
|
||||||
{
|
|
||||||
|
|
||||||
class FileSystemException : public ::Exception
|
class FileSystemException : public ::Exception {
|
||||||
{
|
public:
|
||||||
public:
|
FileSystemException(const QString& message) : Exception(message) {}
|
||||||
FileSystemException(const QString &message) : Exception(message) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write data to a file safely
|
* write data to a file safely
|
||||||
*/
|
*/
|
||||||
void write(const QString &filename, const QByteArray &data);
|
void write(const QString& filename, const QByteArray& data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* append data to a file safely
|
||||||
|
*/
|
||||||
|
void appendSafe(const QString& filename, const QByteArray& data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* append data to a file
|
||||||
|
*/
|
||||||
|
void append(const QString& filename, const QByteArray& data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read data from a file safely\
|
* read data from a file safely\
|
||||||
*/
|
*/
|
||||||
QByteArray read(const QString &filename);
|
QByteArray read(const QString& filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the last changed timestamp of an existing file
|
* Update the last changed timestamp of an existing file
|
||||||
*/
|
*/
|
||||||
bool updateTimestamp(const QString & filename);
|
bool updateTimestamp(const QString& filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates all the folders in a path for the specified path
|
* Creates all the folders in a path for the specified path
|
||||||
@ -44,49 +93,224 @@ bool ensureFilePathExists(QString filenamepath);
|
|||||||
*/
|
*/
|
||||||
bool ensureFolderPathExists(QString filenamepath);
|
bool ensureFolderPathExists(QString filenamepath);
|
||||||
|
|
||||||
class copy
|
/**
|
||||||
{
|
* @brief Copies a directory and it's contents from src to dest
|
||||||
public:
|
*/
|
||||||
copy(const QString & src, const QString & dst)
|
class copy : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
copy(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
|
||||||
{
|
{
|
||||||
m_src = src;
|
m_src.setPath(src);
|
||||||
m_dst = dst;
|
m_dst.setPath(dst);
|
||||||
}
|
}
|
||||||
copy & followSymlinks(const bool follow)
|
copy& followSymlinks(const bool follow)
|
||||||
{
|
{
|
||||||
m_followSymlinks = follow;
|
m_followSymlinks = follow;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
copy & blacklist(const IPathMatcher * filter)
|
copy& matcher(const IPathMatcher* filter)
|
||||||
{
|
{
|
||||||
m_blacklist = filter;
|
m_matcher = filter;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
bool operator()()
|
copy& whitelist(bool whitelist)
|
||||||
{
|
{
|
||||||
return operator()(QString());
|
m_whitelist = whitelist;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
copy& overwrite(const bool overwrite)
|
||||||
|
{
|
||||||
|
m_overwrite = overwrite;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
|
||||||
bool operator()(const QString &offset);
|
|
||||||
|
|
||||||
private:
|
qsizetype totalCopied() { return m_copied; }
|
||||||
|
qsizetype totalFailed() { return m_failedPaths.length(); }
|
||||||
|
QStringList failed() { return m_failedPaths; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fileCopied(const QString& relativeName);
|
||||||
|
void copyFailed(const QString& relativeName);
|
||||||
|
// TODO: maybe add a "shouldCopy" signal in the future?
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool operator()(const QString& offset, bool dryRun = false);
|
||||||
|
|
||||||
|
private:
|
||||||
bool m_followSymlinks = true;
|
bool m_followSymlinks = true;
|
||||||
const IPathMatcher * m_blacklist = nullptr;
|
const IPathMatcher* m_matcher = nullptr;
|
||||||
|
bool m_whitelist = false;
|
||||||
|
bool m_overwrite = false;
|
||||||
QDir m_src;
|
QDir m_src;
|
||||||
QDir m_dst;
|
QDir m_dst;
|
||||||
|
qsizetype m_copied;
|
||||||
|
QStringList m_failedPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LinkPair {
|
||||||
|
QString src;
|
||||||
|
QString dst;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinkResult {
|
||||||
|
QString src;
|
||||||
|
QString dst;
|
||||||
|
QString err_msg;
|
||||||
|
int err_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExternalLinkFileProcess : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ExternalLinkFileProcess(QString server, bool useHardLinks, QObject* parent = nullptr)
|
||||||
|
: QThread(parent), m_useHardLinks(useHardLinks), m_server(server)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
runLinkFile();
|
||||||
|
emit processExited();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void processExited();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void runLinkFile();
|
||||||
|
|
||||||
|
bool m_useHardLinks = false;
|
||||||
|
|
||||||
|
QString m_server;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief links (a file / a directory and it's contents) from src to dest
|
||||||
|
*/
|
||||||
|
class create_link : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
create_link(const QList<LinkPair> path_pairs, QObject* parent = nullptr) : QObject(parent) { m_path_pairs.append(path_pairs); }
|
||||||
|
create_link(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
|
||||||
|
{
|
||||||
|
LinkPair pair = { src, dst };
|
||||||
|
m_path_pairs.append(pair);
|
||||||
|
}
|
||||||
|
create_link& useHardLinks(const bool useHard)
|
||||||
|
{
|
||||||
|
m_useHardLinks = useHard;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
create_link& matcher(const IPathMatcher* filter)
|
||||||
|
{
|
||||||
|
m_matcher = filter;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
create_link& whitelist(bool whitelist)
|
||||||
|
{
|
||||||
|
m_whitelist = whitelist;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
create_link& linkRecursively(bool recursive)
|
||||||
|
{
|
||||||
|
m_recursive = recursive;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
create_link& setMaxDepth(int depth)
|
||||||
|
{
|
||||||
|
m_max_depth = depth;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
create_link& debug(bool d)
|
||||||
|
{
|
||||||
|
m_debug = d;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code getOSError() { return m_os_err; }
|
||||||
|
|
||||||
|
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
|
||||||
|
|
||||||
|
int totalLinked() { return m_linked; }
|
||||||
|
|
||||||
|
void runPrivileged() { runPrivileged(QString()); }
|
||||||
|
void runPrivileged(const QString& offset);
|
||||||
|
|
||||||
|
QList<LinkResult> getResults() { return m_path_results; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fileLinked(const QString& srcName, const QString& dstName);
|
||||||
|
void linkFailed(const QString& srcName, const QString& dstName, const QString& err_msg, int err_value);
|
||||||
|
void finished();
|
||||||
|
void finishedPrivileged(bool gotResults);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool operator()(const QString& offset, bool dryRun = false);
|
||||||
|
void make_link_list(const QString& offset);
|
||||||
|
bool make_links();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_useHardLinks = false;
|
||||||
|
const IPathMatcher* m_matcher = nullptr;
|
||||||
|
bool m_whitelist = false;
|
||||||
|
bool m_recursive = true;
|
||||||
|
|
||||||
|
/// @brief >= -1 = infinite, 0 = link files at src/* to dest/*, 1 = link files at src/*/* to dest/*/*, etc.
|
||||||
|
int m_max_depth = -1;
|
||||||
|
|
||||||
|
QList<LinkPair> m_path_pairs;
|
||||||
|
QList<LinkResult> m_path_results;
|
||||||
|
QList<LinkPair> m_links_to_make;
|
||||||
|
|
||||||
|
int m_linked;
|
||||||
|
bool m_debug = false;
|
||||||
|
std::error_code m_os_err;
|
||||||
|
|
||||||
|
QLocalServer m_linkServer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief moves a file by renaming it
|
||||||
|
* @param source source file path
|
||||||
|
* @param dest destination filepath
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool move(const QString& source, const QString& dest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a folder recursively
|
* Delete a folder recursively
|
||||||
*/
|
*/
|
||||||
bool deletePath(QString path);
|
bool deletePath(QString path);
|
||||||
|
|
||||||
QString PathCombine(const QString &path1, const QString &path2);
|
/**
|
||||||
QString PathCombine(const QString &path1, const QString &path2, const QString &path3);
|
* Trash a folder / file
|
||||||
QString PathCombine(const QString &path1, const QString &path2, const QString &path3, const QString &path4);
|
*/
|
||||||
|
bool trash(QString path, QString* pathInTrash = nullptr);
|
||||||
|
|
||||||
QString AbsolutePath(QString path);
|
QString PathCombine(const QString& path1, const QString& path2);
|
||||||
|
QString PathCombine(const QString& path1, const QString& path2, const QString& path3);
|
||||||
|
QString PathCombine(const QString& path1, const QString& path2, const QString& path3, const QString& path4);
|
||||||
|
|
||||||
|
QString AbsolutePath(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief depth of path. "foo.txt" -> 0 , "bar/foo.txt" -> 1, /baz/bar/foo.txt -> 2, etc.
|
||||||
|
*
|
||||||
|
* @param path path to measure
|
||||||
|
* @return int number of components before base path
|
||||||
|
*/
|
||||||
|
int pathDepth(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief cut off segments of path until it is a max of length depth
|
||||||
|
*
|
||||||
|
* @param path path to truncate
|
||||||
|
* @param depth max depth of new path
|
||||||
|
* @return QString truncated path
|
||||||
|
*/
|
||||||
|
QString pathTruncate(const QString& path, int depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve an executable
|
* Resolve an executable
|
||||||
@ -120,8 +344,205 @@ bool checkProblemticPathJava(QDir folder);
|
|||||||
// Get the Directory representing the User's Desktop
|
// Get the Directory representing the User's Desktop
|
||||||
QString getDesktopDir();
|
QString getDesktopDir();
|
||||||
|
|
||||||
// Create a shortcut at *location*, pointing to *dest* called with the arguments *args*
|
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
|
||||||
// call it *name* and assign it the icon *icon*
|
// Equivalent to doing QDir::rename, but allowing for overrides
|
||||||
// return true if operation succeeded
|
bool overrideFolder(QString overwritten_path, QString override_path);
|
||||||
bool createShortCut(QString location, QString dest, QStringList args, QString name, QString iconLocation);
|
|
||||||
}
|
/**
|
||||||
|
* Creates a shortcut to the specified target file at the specified destination path.
|
||||||
|
*/
|
||||||
|
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
|
||||||
|
|
||||||
|
enum class FilesystemType {
|
||||||
|
FAT,
|
||||||
|
NTFS,
|
||||||
|
REFS,
|
||||||
|
EXT,
|
||||||
|
EXT_2_OLD,
|
||||||
|
EXT_2_3_4,
|
||||||
|
XFS,
|
||||||
|
BTRFS,
|
||||||
|
NFS,
|
||||||
|
ZFS,
|
||||||
|
APFS,
|
||||||
|
HFS,
|
||||||
|
HFSPLUS,
|
||||||
|
HFSX,
|
||||||
|
FUSEBLK,
|
||||||
|
F2FS,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ordered Mapping of enum types to reported filesystem names
|
||||||
|
* this mapping is non exsaustive, it just attempts to capture the filesystems which could be reasonalbly be in use .
|
||||||
|
* all string values are in uppercase, use `QString.toUpper()` or equivalent during lookup.
|
||||||
|
*
|
||||||
|
* QMap is ordered
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static const QMap<FilesystemType, QStringList> s_filesystem_type_names = { { FilesystemType::FAT, { "FAT" } },
|
||||||
|
{ FilesystemType::NTFS, { "NTFS" } },
|
||||||
|
{ FilesystemType::REFS, { "REFS" } },
|
||||||
|
{ FilesystemType::EXT_2_OLD, { "EXT_2_OLD", "EXT2_OLD" } },
|
||||||
|
{ FilesystemType::EXT_2_3_4,
|
||||||
|
{ "EXT2/3/4", "EXT_2_3_4", "EXT2", "EXT3", "EXT4" } },
|
||||||
|
{ FilesystemType::EXT, { "EXT" } },
|
||||||
|
{ FilesystemType::XFS, { "XFS" } },
|
||||||
|
{ FilesystemType::BTRFS, { "BTRFS" } },
|
||||||
|
{ FilesystemType::NFS, { "NFS" } },
|
||||||
|
{ FilesystemType::ZFS, { "ZFS" } },
|
||||||
|
{ FilesystemType::APFS, { "APFS" } },
|
||||||
|
{ FilesystemType::HFS, { "HFS" } },
|
||||||
|
{ FilesystemType::HFSPLUS, { "HFSPLUS" } },
|
||||||
|
{ FilesystemType::HFSX, { "HFSX" } },
|
||||||
|
{ FilesystemType::FUSEBLK, { "FUSEBLK" } },
|
||||||
|
{ FilesystemType::F2FS, { "F2FS" } },
|
||||||
|
{ FilesystemType::UNKNOWN, { "UNKNOWN" } } };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the string name of Filesystem enum object
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @return QString
|
||||||
|
*/
|
||||||
|
QString getFilesystemTypeName(FilesystemType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the Filesystem enum object from a name
|
||||||
|
* Does a lookup of the type name and returns an exact match
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return FilesystemType
|
||||||
|
*/
|
||||||
|
FilesystemType getFilesystemType(const QString& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the Filesystem enum object from a name
|
||||||
|
* Does a fuzzy lookup of the type name and returns an apropreate match
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return FilesystemType
|
||||||
|
*/
|
||||||
|
FilesystemType getFilesystemTypeFuzzy(const QString& name);
|
||||||
|
|
||||||
|
struct FilesystemInfo {
|
||||||
|
FilesystemType fsType = FilesystemType::UNKNOWN;
|
||||||
|
QString fsTypeName;
|
||||||
|
int blockSize;
|
||||||
|
qint64 bytesAvailable;
|
||||||
|
qint64 bytesFree;
|
||||||
|
qint64 bytesTotal;
|
||||||
|
QString name;
|
||||||
|
QString rootPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief path to the near ancestor that exists
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
QString nearestExistentAncestor(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief colect information about the filesystem under a file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
FilesystemInfo statFS(const QString& path);
|
||||||
|
|
||||||
|
static const QList<FilesystemType> s_clone_filesystems = { FilesystemType::BTRFS, FilesystemType::APFS, FilesystemType::ZFS,
|
||||||
|
FilesystemType::XFS, FilesystemType::REFS };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief if the Filesystem is reflink/clone capable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool canCloneOnFS(const QString& path);
|
||||||
|
bool canCloneOnFS(const FilesystemInfo& info);
|
||||||
|
bool canCloneOnFS(FilesystemType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief if the Filesystems are reflink/clone capable and both are on the same device
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool canClone(const QString& src, const QString& dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copies a directory and it's contents from src to dest
|
||||||
|
*/
|
||||||
|
class clone : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
clone(const QString& src, const QString& dst, QObject* parent = nullptr) : QObject(parent)
|
||||||
|
{
|
||||||
|
m_src.setPath(src);
|
||||||
|
m_dst.setPath(dst);
|
||||||
|
}
|
||||||
|
clone& matcher(const IPathMatcher* filter)
|
||||||
|
{
|
||||||
|
m_matcher = filter;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
clone& whitelist(bool whitelist)
|
||||||
|
{
|
||||||
|
m_whitelist = whitelist;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); }
|
||||||
|
|
||||||
|
qsizetype totalCloned() { return m_cloned; }
|
||||||
|
qsizetype totalFailed() { return m_failedClones.length(); }
|
||||||
|
|
||||||
|
QList<QPair<QString, QString>> failed() { return m_failedClones; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fileCloned(const QString& src, const QString& dst);
|
||||||
|
void cloneFailed(const QString& src, const QString& dst);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool operator()(const QString& offset, bool dryRun = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const IPathMatcher* m_matcher = nullptr;
|
||||||
|
bool m_whitelist = false;
|
||||||
|
QDir m_src;
|
||||||
|
QDir m_dst;
|
||||||
|
qsizetype m_cloned;
|
||||||
|
QList<QPair<QString, QString>> m_failedClones;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief clone/reflink file from src to dst
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool clone_file(const QString& src, const QString& dst, std::error_code& ec);
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
bool win_ioctl_clone(const std::wstring& src_path, const std::wstring& dst_path, std::error_code& ec);
|
||||||
|
#elif defined(Q_OS_LINUX)
|
||||||
|
bool linux_ficlone(const std::string& src_path, const std::string& dst_path, std::error_code& ec);
|
||||||
|
#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
|
bool macos_bsd_clonefile(const std::string& src_path, const std::string& dst_path, std::error_code& ec);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const QList<FilesystemType> s_non_link_filesystems = {
|
||||||
|
FilesystemType::FAT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief if the Filesystem is symlink capable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool canLinkOnFS(const QString& path);
|
||||||
|
bool canLinkOnFS(const FilesystemInfo& info);
|
||||||
|
bool canLinkOnFS(FilesystemType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief if the Filesystem is symlink capable on both ends
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool canLink(const QString& src, const QString& dst);
|
||||||
|
|
||||||
|
uintmax_t hardLinkCount(const QString& path);
|
||||||
|
|
||||||
|
} // namespace FS
|
||||||
|
@ -1,164 +0,0 @@
|
|||||||
#include <QTest>
|
|
||||||
#include <QTemporaryDir>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
#include "TestUtil.h"
|
|
||||||
|
|
||||||
#include "FileSystem.h"
|
|
||||||
|
|
||||||
class FileSystemTest : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
const QString bothSlash = "/foo/";
|
|
||||||
const QString trailingSlash = "foo/";
|
|
||||||
const QString leadingSlash = "/foo";
|
|
||||||
|
|
||||||
private
|
|
||||||
slots:
|
|
||||||
void test_pathCombine()
|
|
||||||
{
|
|
||||||
QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash));
|
|
||||||
QCOMPARE(QString("foo/foo"), FS::PathCombine(trailingSlash, trailingSlash));
|
|
||||||
QCOMPARE(QString("/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash));
|
|
||||||
|
|
||||||
QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(bothSlash, bothSlash, bothSlash));
|
|
||||||
QCOMPARE(QString("foo/foo/foo"), FS::PathCombine(trailingSlash, trailingSlash, trailingSlash));
|
|
||||||
QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash, leadingSlash));
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_PathCombine1_data()
|
|
||||||
{
|
|
||||||
QTest::addColumn<QString>("result");
|
|
||||||
QTest::addColumn<QString>("path1");
|
|
||||||
QTest::addColumn<QString>("path2");
|
|
||||||
|
|
||||||
QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc/def" << "ghi/jkl";
|
|
||||||
QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/def/" << "ghi/jkl";
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
QTest::newRow("win native, from C:") << "C:/abc" << "C:" << "abc";
|
|
||||||
QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def" << "ghi\\jkl";
|
|
||||||
QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def\\" << "ghi\\jkl";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_PathCombine1()
|
|
||||||
{
|
|
||||||
QFETCH(QString, result);
|
|
||||||
QFETCH(QString, path1);
|
|
||||||
QFETCH(QString, path2);
|
|
||||||
|
|
||||||
QCOMPARE(FS::PathCombine(path1, path2), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_PathCombine2_data()
|
|
||||||
{
|
|
||||||
QTest::addColumn<QString>("result");
|
|
||||||
QTest::addColumn<QString>("path1");
|
|
||||||
QTest::addColumn<QString>("path2");
|
|
||||||
QTest::addColumn<QString>("path3");
|
|
||||||
|
|
||||||
QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc" << "def" << "ghi/jkl";
|
|
||||||
QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/" << "def" << "ghi/jkl";
|
|
||||||
QTest::newRow("qt 3") << "/abc/def/ghi/jkl" << "/abc" << "def/" << "ghi/jkl";
|
|
||||||
QTest::newRow("qt 4") << "/abc/def/ghi/jkl" << "/abc/" << "def/" << "ghi/jkl";
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
QTest::newRow("win 1") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def" << "ghi\\jkl";
|
|
||||||
QTest::newRow("win 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
|
|
||||||
QTest::newRow("win 3") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def\\" << "ghi\\jkl";
|
|
||||||
QTest::newRow("win 4") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_PathCombine2()
|
|
||||||
{
|
|
||||||
QFETCH(QString, result);
|
|
||||||
QFETCH(QString, path1);
|
|
||||||
QFETCH(QString, path2);
|
|
||||||
QFETCH(QString, path3);
|
|
||||||
|
|
||||||
QCOMPARE(FS::PathCombine(path1, path2, path3), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_copy()
|
|
||||||
{
|
|
||||||
QString folder = QFINDTESTDATA("data/test_folder");
|
|
||||||
auto f = [&folder]()
|
|
||||||
{
|
|
||||||
QTemporaryDir tempDir;
|
|
||||||
tempDir.setAutoRemove(true);
|
|
||||||
qDebug() << "From:" << folder << "To:" << tempDir.path();
|
|
||||||
|
|
||||||
QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
|
|
||||||
qDebug() << tempDir.path();
|
|
||||||
qDebug() << target_dir.path();
|
|
||||||
FS::copy c(folder, target_dir.path());
|
|
||||||
c();
|
|
||||||
|
|
||||||
for(auto entry: target_dir.entryList())
|
|
||||||
{
|
|
||||||
qDebug() << entry;
|
|
||||||
}
|
|
||||||
QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
|
|
||||||
QVERIFY(target_dir.entryList().contains("assets"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// first try variant without trailing /
|
|
||||||
QVERIFY(!folder.endsWith('/'));
|
|
||||||
f();
|
|
||||||
|
|
||||||
// then variant with trailing /
|
|
||||||
folder.append('/');
|
|
||||||
QVERIFY(folder.endsWith('/'));
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_getDesktop()
|
|
||||||
{
|
|
||||||
QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is only valid on linux
|
|
||||||
// FIXME: implement on windows, OSX, then test.
|
|
||||||
#if defined(Q_OS_LINUX)
|
|
||||||
void test_createShortcut_data()
|
|
||||||
{
|
|
||||||
QTest::addColumn<QString>("location");
|
|
||||||
QTest::addColumn<QString>("dest");
|
|
||||||
QTest::addColumn<QStringList>("args");
|
|
||||||
QTest::addColumn<QString>("name");
|
|
||||||
QTest::addColumn<QString>("iconLocation");
|
|
||||||
QTest::addColumn<QByteArray>("result");
|
|
||||||
|
|
||||||
QTest::newRow("unix") << QDir::currentPath()
|
|
||||||
<< "asdfDest"
|
|
||||||
<< (QStringList() << "arg1" << "arg2")
|
|
||||||
<< "asdf"
|
|
||||||
<< QString()
|
|
||||||
#if defined(Q_OS_LINUX)
|
|
||||||
<< GET_TEST_FILE("data/FileSystem-test_createShortcut-unix")
|
|
||||||
#elif defined(Q_OS_WIN)
|
|
||||||
<< QByteArray()
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_createShortcut()
|
|
||||||
{
|
|
||||||
QFETCH(QString, location);
|
|
||||||
QFETCH(QString, dest);
|
|
||||||
QFETCH(QStringList, args);
|
|
||||||
QFETCH(QString, name);
|
|
||||||
QFETCH(QString, iconLocation);
|
|
||||||
QFETCH(QByteArray, result);
|
|
||||||
|
|
||||||
QVERIFY(FS::createShortCut(location, dest, args, name, iconLocation));
|
|
||||||
QCOMPARE(QString::fromLocal8Bit(TestsInternal::readFile(location + QDir::separator() + name + ".desktop")), QString::fromLocal8Bit(result));
|
|
||||||
|
|
||||||
//QDir().remove(location);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(FileSystemTest)
|
|
||||||
|
|
||||||
#include "FileSystem_test.moc"
|
|
@ -1,28 +1,33 @@
|
|||||||
#include "Filter.h"
|
#include "Filter.h"
|
||||||
|
|
||||||
Filter::~Filter(){}
|
Filter::~Filter() {}
|
||||||
|
|
||||||
ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern){}
|
ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {}
|
||||||
ContainsFilter::~ContainsFilter(){}
|
ContainsFilter::~ContainsFilter() {}
|
||||||
bool ContainsFilter::accepts(const QString& value)
|
bool ContainsFilter::accepts(const QString& value)
|
||||||
{
|
{
|
||||||
return value.contains(pattern);
|
return value.contains(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern){}
|
ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {}
|
||||||
ExactFilter::~ExactFilter(){}
|
ExactFilter::~ExactFilter() {}
|
||||||
bool ExactFilter::accepts(const QString& value)
|
bool ExactFilter::accepts(const QString& value)
|
||||||
{
|
{
|
||||||
return value == pattern;
|
return value == pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegexpFilter::RegexpFilter(const QString& regexp, bool invert)
|
ExactIfPresentFilter::ExactIfPresentFilter(const QString& pattern) : pattern(pattern) {}
|
||||||
:invert(invert)
|
bool ExactIfPresentFilter::accepts(const QString& value)
|
||||||
|
{
|
||||||
|
return value.isEmpty() || value == pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert)
|
||||||
{
|
{
|
||||||
pattern.setPattern(regexp);
|
pattern.setPattern(regexp);
|
||||||
pattern.optimize();
|
pattern.optimize();
|
||||||
}
|
}
|
||||||
RegexpFilter::~RegexpFilter(){}
|
RegexpFilter::~RegexpFilter() {}
|
||||||
bool RegexpFilter::accepts(const QString& value)
|
bool RegexpFilter::accepts(const QString& value)
|
||||||
{
|
{
|
||||||
auto match = pattern.match(value);
|
auto match = pattern.match(value);
|
||||||
|
@ -1,42 +1,51 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
class Filter
|
class Filter {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
virtual ~Filter();
|
virtual ~Filter();
|
||||||
virtual bool accepts(const QString & value) = 0;
|
virtual bool accepts(const QString& value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContainsFilter: public Filter
|
class ContainsFilter : public Filter {
|
||||||
{
|
public:
|
||||||
public:
|
ContainsFilter(const QString& pattern);
|
||||||
ContainsFilter(const QString &pattern);
|
|
||||||
virtual ~ContainsFilter();
|
virtual ~ContainsFilter();
|
||||||
bool accepts(const QString & value) override;
|
bool accepts(const QString& value) override;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
QString pattern;
|
QString pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExactFilter: public Filter
|
class ExactFilter : public Filter {
|
||||||
{
|
public:
|
||||||
public:
|
ExactFilter(const QString& pattern);
|
||||||
ExactFilter(const QString &pattern);
|
|
||||||
virtual ~ExactFilter();
|
virtual ~ExactFilter();
|
||||||
bool accepts(const QString & value) override;
|
bool accepts(const QString& value) override;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
QString pattern;
|
QString pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegexpFilter: public Filter
|
class ExactIfPresentFilter : public Filter {
|
||||||
{
|
public:
|
||||||
public:
|
ExactIfPresentFilter(const QString& pattern);
|
||||||
RegexpFilter(const QString ®exp, bool invert);
|
~ExactIfPresentFilter() override = default;
|
||||||
|
bool accepts(const QString& value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegexpFilter : public Filter {
|
||||||
|
public:
|
||||||
|
RegexpFilter(const QString& regexp, bool invert);
|
||||||
virtual ~RegexpFilter();
|
virtual ~RegexpFilter();
|
||||||
bool accepts(const QString & value) override;
|
bool accepts(const QString& value) override;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
QRegularExpression pattern;
|
QRegularExpression pattern;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,45 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "GZip.h"
|
#include "GZip.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes)
|
bool GZip::unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes)
|
||||||
{
|
{
|
||||||
if (compressedBytes.size() == 0)
|
if (compressedBytes.size() == 0) {
|
||||||
{
|
|
||||||
uncompressedBytes = compressedBytes;
|
uncompressedBytes = compressedBytes;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -16,42 +50,37 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte
|
|||||||
|
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
memset(&strm, 0, sizeof(strm));
|
memset(&strm, 0, sizeof(strm));
|
||||||
strm.next_in = (Bytef *)compressedBytes.data();
|
strm.next_in = (Bytef*)compressedBytes.data();
|
||||||
strm.avail_in = compressedBytes.size();
|
strm.avail_in = compressedBytes.size();
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK)
|
if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = Z_OK;
|
int err = Z_OK;
|
||||||
|
|
||||||
while (!done)
|
while (!done) {
|
||||||
{
|
|
||||||
// If our output buffer is too small
|
// If our output buffer is too small
|
||||||
if (strm.total_out >= uncompLength)
|
if (strm.total_out >= uncompLength) {
|
||||||
{
|
|
||||||
uncompressedBytes.resize(uncompLength * 2);
|
uncompressedBytes.resize(uncompLength * 2);
|
||||||
uncompLength *= 2;
|
uncompLength *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
strm.next_out = (Bytef *)(uncompressedBytes.data() + strm.total_out);
|
strm.next_out = reinterpret_cast<Bytef*>((uncompressedBytes.data() + strm.total_out));
|
||||||
strm.avail_out = uncompLength - strm.total_out;
|
strm.avail_out = uncompLength - strm.total_out;
|
||||||
|
|
||||||
// Inflate another chunk.
|
// Inflate another chunk.
|
||||||
err = inflate(&strm, Z_SYNC_FLUSH);
|
err = inflate(&strm, Z_SYNC_FLUSH);
|
||||||
if (err == Z_STREAM_END)
|
if (err == Z_STREAM_END)
|
||||||
done = true;
|
done = true;
|
||||||
else if (err != Z_OK)
|
else if (err != Z_OK) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inflateEnd(&strm) != Z_OK || !done)
|
if (inflateEnd(&strm) != Z_OK || !done) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,23 +88,21 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
|
bool GZip::zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes)
|
||||||
{
|
{
|
||||||
if (uncompressedBytes.size() == 0)
|
if (uncompressedBytes.size() == 0) {
|
||||||
{
|
|
||||||
compressedBytes = uncompressedBytes;
|
compressedBytes = uncompressedBytes;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned compLength = std::min(uncompressedBytes.size(), 16);
|
unsigned compLength = qMin(uncompressedBytes.size(), 16);
|
||||||
compressedBytes.clear();
|
compressedBytes.clear();
|
||||||
compressedBytes.resize(compLength);
|
compressedBytes.resize(compLength);
|
||||||
|
|
||||||
z_stream zs;
|
z_stream zs;
|
||||||
memset(&zs, 0, sizeof(zs));
|
memset(&zs, 0, sizeof(zs));
|
||||||
|
|
||||||
if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK)
|
if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,14 +114,12 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
|
|||||||
|
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
unsigned temp = 0;
|
unsigned temp = 0;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
auto remaining = compressedBytes.size() - offset;
|
auto remaining = compressedBytes.size() - offset;
|
||||||
if(remaining < 1)
|
if (remaining < 1) {
|
||||||
{
|
|
||||||
compressedBytes.resize(compressedBytes.size() * 2);
|
compressedBytes.resize(compressedBytes.size() * 2);
|
||||||
}
|
}
|
||||||
zs.next_out = (Bytef *) (compressedBytes.data() + offset);
|
zs.next_out = reinterpret_cast<Bytef*>((compressedBytes.data() + offset));
|
||||||
temp = zs.avail_out = compressedBytes.size() - offset;
|
temp = zs.avail_out = compressedBytes.size() - offset;
|
||||||
ret = deflate(&zs, Z_FINISH);
|
ret = deflate(&zs, Z_FINISH);
|
||||||
offset += temp - zs.avail_out;
|
offset += temp - zs.avail_out;
|
||||||
@ -102,14 +127,12 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
|
|||||||
|
|
||||||
compressedBytes.resize(offset);
|
compressedBytes.resize(offset);
|
||||||
|
|
||||||
if (deflateEnd(&zs) != Z_OK)
|
if (deflateEnd(&zs) != Z_OK) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != Z_STREAM_END)
|
if (ret != Z_STREAM_END) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
class GZip
|
class GZip {
|
||||||
{
|
public:
|
||||||
public:
|
static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes);
|
||||||
static bool unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes);
|
static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes);
|
||||||
static bool zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <hoedown/html.h>
|
|
||||||
#include <hoedown/document.h>
|
|
||||||
#include <QString>
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* hoedown wrapper, because dealing with resource lifetime in C is stupid
|
|
||||||
*/
|
|
||||||
class HoeDown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class buffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
buffer(size_t unit = 4096)
|
|
||||||
{
|
|
||||||
buf = hoedown_buffer_new(unit);
|
|
||||||
}
|
|
||||||
~buffer()
|
|
||||||
{
|
|
||||||
hoedown_buffer_free(buf);
|
|
||||||
}
|
|
||||||
const char * cstr()
|
|
||||||
{
|
|
||||||
return hoedown_buffer_cstr(buf);
|
|
||||||
}
|
|
||||||
void put(QByteArray input)
|
|
||||||
{
|
|
||||||
hoedown_buffer_put(buf, (uint8_t *) input.data(), input.size());
|
|
||||||
}
|
|
||||||
const uint8_t * data() const
|
|
||||||
{
|
|
||||||
return buf->data;
|
|
||||||
}
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
return buf->size;
|
|
||||||
}
|
|
||||||
hoedown_buffer * buf;
|
|
||||||
} ib, ob;
|
|
||||||
HoeDown()
|
|
||||||
{
|
|
||||||
renderer = hoedown_html_renderer_new((hoedown_html_flags) 0,0);
|
|
||||||
document = hoedown_document_new(renderer, (hoedown_extensions) 0, 8);
|
|
||||||
}
|
|
||||||
~HoeDown()
|
|
||||||
{
|
|
||||||
hoedown_document_free(document);
|
|
||||||
hoedown_html_renderer_free(renderer);
|
|
||||||
}
|
|
||||||
QString process(QByteArray input)
|
|
||||||
{
|
|
||||||
ib.put(input);
|
|
||||||
hoedown_document_render(document, ob.buf, ib.data(), ib.size());
|
|
||||||
return ob.cstr();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
hoedown_document * document;
|
|
||||||
hoedown_renderer * renderer;
|
|
||||||
};
|
|
192
launcher/InstanceCopyPrefs.cpp
Normal file
192
launcher/InstanceCopyPrefs.cpp
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
//
|
||||||
|
// Created by marcelohdez on 10/22/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "InstanceCopyPrefs.h"
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::allTrue() const
|
||||||
|
{
|
||||||
|
return copySaves && keepPlaytime && copyGameOptions && copyResourcePacks && copyShaderPacks && copyServers && copyMods &&
|
||||||
|
copyScreenshots;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat")
|
||||||
|
QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const
|
||||||
|
{
|
||||||
|
return getSelectedFiltersAsRegex({});
|
||||||
|
}
|
||||||
|
QString InstanceCopyPrefs::getSelectedFiltersAsRegex(const QStringList& additionalFilters) const
|
||||||
|
{
|
||||||
|
QStringList filters;
|
||||||
|
|
||||||
|
if (!copySaves)
|
||||||
|
filters << "saves";
|
||||||
|
|
||||||
|
if (!copyGameOptions)
|
||||||
|
filters << "options.txt";
|
||||||
|
|
||||||
|
if (!copyResourcePacks)
|
||||||
|
filters << "resourcepacks"
|
||||||
|
<< "texturepacks";
|
||||||
|
|
||||||
|
if (!copyShaderPacks)
|
||||||
|
filters << "shaderpacks";
|
||||||
|
|
||||||
|
if (!copyServers)
|
||||||
|
filters << "servers.dat"
|
||||||
|
<< "servers.dat_old"
|
||||||
|
<< "server-resource-packs";
|
||||||
|
|
||||||
|
if (!copyMods)
|
||||||
|
filters << "coremods"
|
||||||
|
<< "mods"
|
||||||
|
<< "config";
|
||||||
|
|
||||||
|
if (!copyScreenshots)
|
||||||
|
filters << "screenshots";
|
||||||
|
|
||||||
|
for (auto filter : additionalFilters) {
|
||||||
|
filters << filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have any filters to add, join them as a single regex string to return:
|
||||||
|
if (!filters.isEmpty()) {
|
||||||
|
const QString MC_ROOT = "[.]?minecraft/";
|
||||||
|
// Ensure first filter starts with root, then join other filters with OR regex before root (ex: ".minecraft/saves|.minecraft/mods"):
|
||||||
|
return MC_ROOT + filters.join("|" + MC_ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======= Getters =======
|
||||||
|
bool InstanceCopyPrefs::isCopySavesEnabled() const
|
||||||
|
{
|
||||||
|
return copySaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isKeepPlaytimeEnabled() const
|
||||||
|
{
|
||||||
|
return keepPlaytime;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isCopyGameOptionsEnabled() const
|
||||||
|
{
|
||||||
|
return copyGameOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isCopyResourcePacksEnabled() const
|
||||||
|
{
|
||||||
|
return copyResourcePacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isCopyShaderPacksEnabled() const
|
||||||
|
{
|
||||||
|
return copyShaderPacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isCopyServersEnabled() const
|
||||||
|
{
|
||||||
|
return copyServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isCopyModsEnabled() const
|
||||||
|
{
|
||||||
|
return copyMods;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isCopyScreenshotsEnabled() const
|
||||||
|
{
|
||||||
|
return copyScreenshots;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isUseSymLinksEnabled() const
|
||||||
|
{
|
||||||
|
return useSymLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isUseHardLinksEnabled() const
|
||||||
|
{
|
||||||
|
return useHardLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isLinkRecursivelyEnabled() const
|
||||||
|
{
|
||||||
|
return linkRecursively;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isDontLinkSavesEnabled() const
|
||||||
|
{
|
||||||
|
return dontLinkSaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceCopyPrefs::isUseCloneEnabled() const
|
||||||
|
{
|
||||||
|
return useClone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======= Setters =======
|
||||||
|
void InstanceCopyPrefs::enableCopySaves(bool b)
|
||||||
|
{
|
||||||
|
copySaves = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableKeepPlaytime(bool b)
|
||||||
|
{
|
||||||
|
keepPlaytime = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableCopyGameOptions(bool b)
|
||||||
|
{
|
||||||
|
copyGameOptions = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableCopyResourcePacks(bool b)
|
||||||
|
{
|
||||||
|
copyResourcePacks = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableCopyShaderPacks(bool b)
|
||||||
|
{
|
||||||
|
copyShaderPacks = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableCopyServers(bool b)
|
||||||
|
{
|
||||||
|
copyServers = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableCopyMods(bool b)
|
||||||
|
{
|
||||||
|
copyMods = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableCopyScreenshots(bool b)
|
||||||
|
{
|
||||||
|
copyScreenshots = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableUseSymLinks(bool b)
|
||||||
|
{
|
||||||
|
useSymLinks = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableLinkRecursively(bool b)
|
||||||
|
{
|
||||||
|
linkRecursively = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableUseHardLinks(bool b)
|
||||||
|
{
|
||||||
|
useHardLinks = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableDontLinkSaves(bool b)
|
||||||
|
{
|
||||||
|
dontLinkSaves = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceCopyPrefs::enableUseClone(bool b)
|
||||||
|
{
|
||||||
|
useClone = b;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user