Compare commits
583 Commits
1.2_M2.fin
...
1.2_M3.fin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
320558f494 | ||
|
|
0cfceaa53b | ||
|
|
7fee190f67 | ||
|
|
c97ebae788 | ||
|
|
05c7d5d512 | ||
|
|
a4624063ed | ||
|
|
426b7fd111 | ||
|
|
d86e3082e6 | ||
|
|
2474e6c55c | ||
|
|
7f67843c32 | ||
|
|
2684714480 | ||
|
|
0e39107047 | ||
|
|
8fbdf5faa6 | ||
|
|
b82a793bdb | ||
|
|
f60a5d159b | ||
|
|
126f634207 | ||
|
|
93d157b724 | ||
|
|
3152baea3e | ||
|
|
aebb13e885 | ||
|
|
2902bbe44f | ||
|
|
695a609057 | ||
|
|
991e34ca89 | ||
|
|
13949f2100 | ||
|
|
36a0bde559 | ||
|
|
1919ba235f | ||
|
|
b3f05552bc | ||
|
|
e42bc47ef8 | ||
|
|
df329ad709 | ||
|
|
6beb61f3ca | ||
|
|
84ad6671d5 | ||
|
|
d1130b4b21 | ||
|
|
9fff795f12 | ||
|
|
7f27de5bdf | ||
|
|
622327145c | ||
|
|
68f2485a83 | ||
|
|
adc53a00f8 | ||
|
|
9a3d725780 | ||
|
|
d6e0cbc087 | ||
|
|
4ab5d64b96 | ||
|
|
4770a6e6ad | ||
|
|
5fb90bc29c | ||
|
|
86d3f776aa | ||
|
|
debd4da669 | ||
|
|
79e8d533ee | ||
|
|
ef461c4a2a | ||
|
|
caea5b9610 | ||
|
|
0733f7a4a9 | ||
|
|
afc6d1bb31 | ||
|
|
6be627fd5f | ||
|
|
76c1712202 | ||
|
|
cf87669e7c | ||
|
|
835197d65c | ||
|
|
36a2f338f3 | ||
|
|
c3a23ec304 | ||
|
|
ce0ecf5d84 | ||
|
|
e7952c1883 | ||
|
|
959981da53 | ||
|
|
927bec5f72 | ||
|
|
a295cdc19f | ||
|
|
f420fb3de1 | ||
|
|
6cf61b30aa | ||
|
|
3349b88a76 | ||
|
|
36e918b8a8 | ||
|
|
21f2c0b5cd | ||
|
|
c02bea652b | ||
|
|
43d9193f69 | ||
|
|
eb8ce05d13 | ||
|
|
6aa3a09876 | ||
|
|
1adeb37d79 | ||
|
|
5ecae0be86 | ||
|
|
9674ea28ff | ||
|
|
aac45679fb | ||
|
|
1cb4614f1d | ||
|
|
56bbea6dcf | ||
|
|
17fe2963c9 | ||
|
|
745f5c329d | ||
|
|
7160f874c4 | ||
|
|
be1443b9d0 | ||
|
|
e17c709b43 | ||
|
|
a54932dc37 | ||
|
|
2ff96d664e | ||
|
|
c9e95d3363 | ||
|
|
e894f0e71c | ||
|
|
ee86f899e1 | ||
|
|
b6bd0f8a32 | ||
|
|
d7cef163e4 | ||
|
|
5272e883ff | ||
|
|
cde25845a7 | ||
|
|
3be2c7d611 | ||
|
|
21ddc964ce | ||
|
|
f496389aa8 | ||
|
|
3a20beb260 | ||
|
|
656f9a0758 | ||
|
|
14df6d53b6 | ||
|
|
db94ad4cf3 | ||
|
|
c8af05547e | ||
|
|
ef36dc896d | ||
|
|
189a854e8d | ||
|
|
dfd6c546c4 | ||
|
|
5dc51532b6 | ||
|
|
16b715bc84 | ||
|
|
408fd37529 | ||
|
|
72ce5c4cde | ||
|
|
5ac604e67a | ||
|
|
ae34e43b24 | ||
|
|
c867e31f7e | ||
|
|
7c46f0b109 | ||
|
|
f017b9b6b8 | ||
|
|
d02f7b4649 | ||
|
|
e6230da00e | ||
|
|
5aca6a7e94 | ||
|
|
826c1a1e44 | ||
|
|
cc2ef82c0c | ||
|
|
99c805a168 | ||
|
|
9531161d40 | ||
|
|
f378918c79 | ||
|
|
95eb87b7f6 | ||
|
|
6ad11cba63 | ||
|
|
2fb9aace07 | ||
|
|
e7caf3d1bc | ||
|
|
fa10f797e3 | ||
|
|
2065d3999d | ||
|
|
68a738e538 | ||
|
|
050be51c1d | ||
|
|
bd7f819b1f | ||
|
|
b899244305 | ||
|
|
f409cf4bbd | ||
|
|
b1d418e315 | ||
|
|
1d7728e8cb | ||
|
|
da1b26c350 | ||
|
|
1eec640238 | ||
|
|
6224e30834 | ||
|
|
ef29851fe8 | ||
|
|
136d9cd07d | ||
|
|
5d04c6e173 | ||
|
|
1792a02606 | ||
|
|
8ea3bf3821 | ||
|
|
4fe569e949 | ||
|
|
dced0c16e8 | ||
|
|
83d1d135d6 | ||
|
|
c6580ce1e4 | ||
|
|
8d26a9f7e6 | ||
|
|
578b6f222d | ||
|
|
762966eaae | ||
|
|
566ae9796b | ||
|
|
aba82ec3cd | ||
|
|
d8a78f3e32 | ||
|
|
af57b2e7ca | ||
|
|
adbe09435a | ||
|
|
a470400cf8 | ||
|
|
a6fb1939c1 | ||
|
|
daeb5beb8f | ||
|
|
831e0b5cd7 | ||
|
|
5a4b06ddec | ||
|
|
30b709c50c | ||
|
|
331540ca8b | ||
|
|
9d6d5e37ab | ||
|
|
26882fdd67 | ||
|
|
77988c32f1 | ||
|
|
2ede6787ea | ||
|
|
571c9c7980 | ||
|
|
8fa33800ef | ||
|
|
de77b9752a | ||
|
|
85fa989df7 | ||
|
|
cb873084d0 | ||
|
|
c42f973180 | ||
|
|
19089aca83 | ||
|
|
b70bcb353d | ||
|
|
8e737db4fc | ||
|
|
99d326a818 | ||
|
|
ebc0d4252a | ||
|
|
4a1c163b55 | ||
|
|
d8b3718303 | ||
|
|
65c1399be1 | ||
|
|
a578fbce14 | ||
|
|
729a9019bc | ||
|
|
f409a49c3a | ||
|
|
83007574cc | ||
|
|
ea2c8defd5 | ||
|
|
3a2338607b | ||
|
|
30d0bbfb01 | ||
|
|
c8286e049f | ||
|
|
8e0c7b3c0d | ||
|
|
e228289bf0 | ||
|
|
b62249f3db | ||
|
|
5210cc40db | ||
|
|
0aedc60b02 | ||
|
|
f7c0488bd5 | ||
|
|
52ebd5ff1b | ||
|
|
cf60f95d9f | ||
|
|
87e32edb88 | ||
|
|
d27351a2c2 | ||
|
|
92dd65f05a | ||
|
|
9c16786928 | ||
|
|
b2a84e717e | ||
|
|
888f9d59a9 | ||
|
|
5aec33be72 | ||
|
|
79eb4b8fdb | ||
|
|
e155952b4d | ||
|
|
1b7014ffc5 | ||
|
|
04c290a492 | ||
|
|
3cce3196fa | ||
|
|
7b3ea97051 | ||
|
|
9eab86041f | ||
|
|
0f00536d0a | ||
|
|
ab5eed4af1 | ||
|
|
2101ea6367 | ||
|
|
63b680ed05 | ||
|
|
b2196ca256 | ||
|
|
0761649736 | ||
|
|
c3b3a681f7 | ||
|
|
7f880ca20d | ||
|
|
362fd558fe | ||
|
|
8a31618c35 | ||
|
|
cf10b9b847 | ||
|
|
8e7cd329b1 | ||
|
|
f273c04175 | ||
|
|
0656f57235 | ||
|
|
41a83ccfe5 | ||
|
|
754847f34b | ||
|
|
d366c1890e | ||
|
|
d3d11016de | ||
|
|
a2a03ba68b | ||
|
|
c62296dab6 | ||
|
|
12306d01a0 | ||
|
|
d60912993d | ||
|
|
765547eb71 | ||
|
|
84983afa63 | ||
|
|
a142cbd47e | ||
|
|
65d296a235 | ||
|
|
18c3197911 | ||
|
|
970fcc886e | ||
|
|
15ff81be40 | ||
|
|
51c719d779 | ||
|
|
0de4750a57 | ||
|
|
c56792ce08 | ||
|
|
433f2ead93 | ||
|
|
ef5bad08de | ||
|
|
af85900ba7 | ||
|
|
d90565366c | ||
|
|
8d41b0ddbf | ||
|
|
1e8b62991a | ||
|
|
1a35ed4f5d | ||
|
|
8653bf474e | ||
|
|
4255cb85a0 | ||
|
|
57b7b8a7ba | ||
|
|
b5b4066b08 | ||
|
|
af1ddab5c3 | ||
|
|
8054217a35 | ||
|
|
be174f37b9 | ||
|
|
eb1be234fc | ||
|
|
0c1386ccad | ||
|
|
b9ff9682b3 | ||
|
|
54fd9ad71b | ||
|
|
d6b885b1b5 | ||
|
|
41936cd5bc | ||
|
|
bdc50cbfbb | ||
|
|
a50eeb884a | ||
|
|
a4021674ed | ||
|
|
fadd554603 | ||
|
|
7d9ac1db13 | ||
|
|
fd2983e5fc | ||
|
|
a481c10d72 | ||
|
|
7215c25ec3 | ||
|
|
8df37ad549 | ||
|
|
5d02d8dc17 | ||
|
|
a6065e7fc2 | ||
|
|
bb1e769cf1 | ||
|
|
568bdc78f9 | ||
|
|
44f0a2cfc5 | ||
|
|
23c4961ace | ||
|
|
98a994acff | ||
|
|
c2c215b887 | ||
|
|
3709697117 | ||
|
|
ce0740fbb5 | ||
|
|
5a33401b84 | ||
|
|
f2b55ac391 | ||
|
|
83dcff4042 | ||
|
|
e33f828d88 | ||
|
|
cc036d4c4e | ||
|
|
c54070c0b1 | ||
|
|
4825e2af65 | ||
|
|
0e80bb7a26 | ||
|
|
67cfa74744 | ||
|
|
50a097be16 | ||
|
|
cb89d43473 | ||
|
|
8fcfbaeb48 | ||
|
|
6034d1c512 | ||
|
|
3301dc44b2 | ||
|
|
3b1ad76c87 | ||
|
|
4be9d82596 | ||
|
|
a29939639b | ||
|
|
79e48d853b | ||
|
|
cbe0a0dd8a | ||
|
|
c0d7e9b062 | ||
|
|
b942a8ee6a | ||
|
|
34ba3b689e | ||
|
|
6cafc0011e | ||
|
|
bb5704a4ee | ||
|
|
14e6b02ceb | ||
|
|
e1be40cdd2 | ||
|
|
e87bbf1250 | ||
|
|
85beca9f88 | ||
|
|
f0262b7ab2 | ||
|
|
a03c350074 | ||
|
|
f5d505e0cd | ||
|
|
0637f1b409 | ||
|
|
6c988aa5f3 | ||
|
|
e7973af409 | ||
|
|
735371dcd2 | ||
|
|
6e28930bdd | ||
|
|
30049f0e7b | ||
|
|
b1d4d3599f | ||
|
|
954a0bf236 | ||
|
|
cba606f260 | ||
|
|
d54c972888 | ||
|
|
e2d9ed9539 | ||
|
|
7b36125097 | ||
|
|
31f34914db | ||
|
|
45228d39f3 | ||
|
|
f7a1bd43e8 | ||
|
|
a402d0e921 | ||
|
|
15f09b1cfe | ||
|
|
cd5225adfd | ||
|
|
7bc766b9f8 | ||
|
|
5c3323b7e7 | ||
|
|
f408dd164e | ||
|
|
ac62f06e09 | ||
|
|
7923ba87a2 | ||
|
|
ae21dc189f | ||
|
|
aa2c4e3879 | ||
|
|
6028cd196e | ||
|
|
a95445cf7b | ||
|
|
8d4d9a15c4 | ||
|
|
8ac227e4ac | ||
|
|
58026ecc28 | ||
|
|
76640582e8 | ||
|
|
ef328622c2 | ||
|
|
2175842116 | ||
|
|
89b71a5062 | ||
|
|
6719d3e9e7 | ||
|
|
1655fd11d3 | ||
|
|
64662290d3 | ||
|
|
38daf8b7eb | ||
|
|
555262744d | ||
|
|
90e99a5cae | ||
|
|
86a5fcd2c6 | ||
|
|
526264e7d7 | ||
|
|
3d2f6d5610 | ||
|
|
cf425a13a2 | ||
|
|
936aca72c9 | ||
|
|
22181a759d | ||
|
|
0de413782e | ||
|
|
dc153672aa | ||
|
|
a092311949 | ||
|
|
e670fdc7ae | ||
|
|
278e53ca6b | ||
|
|
0d1dee2a56 | ||
|
|
ae3184c96e | ||
|
|
2805ff120e | ||
|
|
a26a2cba60 | ||
|
|
37d93b9818 | ||
|
|
9123e9eb9b | ||
|
|
84e24f0f00 | ||
|
|
636d7e308f | ||
|
|
b719d7e10b | ||
|
|
df823d5958 | ||
|
|
973f93c031 | ||
|
|
75fcfde061 | ||
|
|
3b47c5310a | ||
|
|
0a3a15c8dd | ||
|
|
9a58e312ef | ||
|
|
de7a6ab1ba | ||
|
|
9aeb38a5b8 | ||
|
|
2a361cdb39 | ||
|
|
238a47d800 | ||
|
|
f54a443aa7 | ||
|
|
7aa33dba3b | ||
|
|
cd7da08486 | ||
|
|
494a500032 | ||
|
|
3a9e5682a9 | ||
|
|
e60acb7e0b | ||
|
|
5ff048d979 | ||
|
|
609f637ff0 | ||
|
|
d8aada2b9a | ||
|
|
8549ebb873 | ||
|
|
6882a60b18 | ||
|
|
0d7dfedca4 | ||
|
|
0287f645f1 | ||
|
|
8f55130e6f | ||
|
|
0bf6f8035c | ||
|
|
7c8899662b | ||
|
|
6b2cb82802 | ||
|
|
ef3c1dd356 | ||
|
|
f13ee1e877 | ||
|
|
5c6aa87a91 | ||
|
|
19561311a3 | ||
|
|
803850a0ee | ||
|
|
87b3c3f813 | ||
|
|
27aec8bef6 | ||
|
|
be76d89496 | ||
|
|
07b940b752 | ||
|
|
d6dcd8de12 | ||
|
|
d6a55ca79c | ||
|
|
e96ec29709 | ||
|
|
a3c6899639 | ||
|
|
1483a6c5d7 | ||
|
|
e36a3c16d5 | ||
|
|
d70f34fddd | ||
|
|
71dbcbcdcb | ||
|
|
35200aa6b9 | ||
|
|
ab315a3b68 | ||
|
|
12e10a653a | ||
|
|
80b9d5125d | ||
|
|
eccece9553 | ||
|
|
307fcba065 | ||
|
|
b227700cac | ||
|
|
7843f8ec97 | ||
|
|
70b6b6bdf4 | ||
|
|
930424bf2f | ||
|
|
c6c3f87450 | ||
|
|
a64c2a90ad | ||
|
|
662666046c | ||
|
|
9ed7ac6ffa | ||
|
|
14953b7c51 | ||
|
|
50a073fe04 | ||
|
|
ed08326255 | ||
|
|
a15f44464e | ||
|
|
8d54a0de69 | ||
|
|
f514242c8d | ||
|
|
3507c03f16 | ||
|
|
3346afefa3 | ||
|
|
d74c85201e | ||
|
|
bb52d385c6 | ||
|
|
ca848609cb | ||
|
|
79af7541e2 | ||
|
|
7301b4c187 | ||
|
|
2896b4a1c4 | ||
|
|
7b81ef8d95 | ||
|
|
b68ea54360 | ||
|
|
127d1fd1c2 | ||
|
|
6b2b5d2acd | ||
|
|
c6a2c300d1 | ||
|
|
d4a942fb51 | ||
|
|
21b3f5ddb1 | ||
|
|
c47def3b04 | ||
|
|
4ad01bdf3f | ||
|
|
a7b32bd9ef | ||
|
|
85cf3ed593 | ||
|
|
b454cb7366 | ||
|
|
280e5fd212 | ||
|
|
76c16c4fa8 | ||
|
|
3fe81df640 | ||
|
|
3c5f108001 | ||
|
|
7a8bae92ed | ||
|
|
c4a8fab1a4 | ||
|
|
8878ee89ba | ||
|
|
42645b0965 | ||
|
|
f3e51862f1 | ||
|
|
11cce80137 | ||
|
|
0779a90e2a | ||
|
|
299fa3489b | ||
|
|
7a8e1ef418 | ||
|
|
967de59f35 | ||
|
|
11e5d7bc81 | ||
|
|
adb3ed29db | ||
|
|
dac8259131 | ||
|
|
5cf28333a7 | ||
|
|
c1cebf6a2b | ||
|
|
2f4f8ef0fc | ||
|
|
ffa93f0e25 | ||
|
|
6ddf0b2b97 | ||
|
|
34f4ab18bd | ||
|
|
225a24a390 | ||
|
|
4cf1776ebc | ||
|
|
d8063119fc | ||
|
|
b44c25b72b | ||
|
|
38b034168f | ||
|
|
cb06a5aa2b | ||
|
|
b5dee63c2e | ||
|
|
cdd2f4e474 | ||
|
|
40fcaac48e | ||
|
|
522c6b376d | ||
|
|
5664e3c14f | ||
|
|
2280404731 | ||
|
|
4f108e93b7 | ||
|
|
c2a74cc148 | ||
|
|
89705eadb4 | ||
|
|
ea8e63df24 | ||
|
|
13a62254e8 | ||
|
|
80038a0352 | ||
|
|
05f421f200 | ||
|
|
b19b27676e | ||
|
|
6455292b96 | ||
|
|
8a7a7fef73 | ||
|
|
3ba7426bbf | ||
|
|
35d1c6821d | ||
|
|
42f0d50fa3 | ||
|
|
030bdde04a | ||
|
|
cbc784f4eb | ||
|
|
703e1f06fd | ||
|
|
4884ccd236 | ||
|
|
f127738aad | ||
|
|
1fedd166b7 | ||
|
|
5724ee9c3a | ||
|
|
39a991880a | ||
|
|
9ea681fffb | ||
|
|
e2a3695ad4 | ||
|
|
8773ebef26 | ||
|
|
8ca0061744 | ||
|
|
925433d6e6 | ||
|
|
1ca0401f33 | ||
|
|
8b11a2f3f0 | ||
|
|
ac27587f93 | ||
|
|
7edf3dc059 | ||
|
|
93d70e4b86 | ||
|
|
e1d3a32bb1 | ||
|
|
95386cfb96 | ||
|
|
6d769b286e | ||
|
|
6f3d52ec11 | ||
|
|
a9095e5cb2 | ||
|
|
f290935151 | ||
|
|
ee7fb2b86d | ||
|
|
9d6bf93e9d | ||
|
|
edef415be6 | ||
|
|
3287e4be35 | ||
|
|
b6b909abd8 | ||
|
|
432c6cff0f | ||
|
|
c86797abdf | ||
|
|
79b6192d21 | ||
|
|
f07793dd77 | ||
|
|
464a2d66a4 | ||
|
|
6ce82eac3b | ||
|
|
35759f977e | ||
|
|
73a7876b27 | ||
|
|
023fe87943 | ||
|
|
866ed43c12 | ||
|
|
f20d49315d | ||
|
|
2eb5811da7 | ||
|
|
e0ae57d9f4 | ||
|
|
e7a31cf67d | ||
|
|
a521f9d679 | ||
|
|
5fabe90808 | ||
|
|
1db019ac7c | ||
|
|
1cabda965d | ||
|
|
19247e44a3 | ||
|
|
7ce97336aa | ||
|
|
49a0821376 | ||
|
|
6d73a199e4 | ||
|
|
7561d5b204 | ||
|
|
bec7def38d | ||
|
|
57e78fa12d | ||
|
|
b98851cc6f | ||
|
|
523f6b69c6 | ||
|
|
573daf6734 | ||
|
|
7a20966e05 | ||
|
|
fb878477cb | ||
|
|
d0cc840977 | ||
|
|
f93408805a | ||
|
|
ccd2a31003 | ||
|
|
8f44e9030b | ||
|
|
dd04a42df4 | ||
|
|
3754d75e49 | ||
|
|
4807e0b3ae | ||
|
|
b5ad3773af | ||
|
|
254b9de1af | ||
|
|
7c8ebf6f0d | ||
|
|
b02e7d45e0 | ||
|
|
f17c9d3b38 | ||
|
|
18fe75dd84 | ||
|
|
16d911d191 | ||
|
|
094118031c | ||
|
|
e2948feae8 | ||
|
|
beb601f79f | ||
|
|
684c6ef2d0 | ||
|
|
9fd17bbe1c | ||
|
|
5f5ae14ee3 | ||
|
|
eb6291b36f | ||
|
|
ecdfc1ebbe | ||
|
|
4e8085ccfa | ||
|
|
dcf6b641fe | ||
|
|
98a610b3db | ||
|
|
8a98af2bb5 |
@@ -40,7 +40,7 @@ from bb import cooker
|
||||
from bb import ui
|
||||
from bb import server
|
||||
|
||||
__version__ = "1.15.0"
|
||||
__version__ = "1.15.1"
|
||||
logger = logging.getLogger("BitBake")
|
||||
|
||||
|
||||
@@ -168,6 +168,8 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
parser.add_option("", "--server-only", help = "Run bitbake without UI, the frontend can connect with bitbake server itself",
|
||||
action = "store_true", dest = "server_only", default = False)
|
||||
|
||||
parser.add_option("-B", "--bind", help = "The name/address for the bitbake server to bind to",
|
||||
action = "store", dest = "bind", default = False)
|
||||
options, args = parser.parse_args(sys.argv)
|
||||
|
||||
configuration = BBConfiguration(options)
|
||||
@@ -189,8 +191,14 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
sys.exit("FATAL: Invalid server type '%s' specified.\n"
|
||||
"Valid interfaces: xmlrpc, process [default], none." % servertype)
|
||||
|
||||
if configuration.server_only and configuration.servertype != "xmlrpc":
|
||||
sys.exit("FATAL: If '--server-only' is defined, we must set the servertype as 'xmlrpc'.\n")
|
||||
if configuration.server_only:
|
||||
if configuration.servertype != "xmlrpc":
|
||||
sys.exit("FATAL: If '--server-only' is defined, we must set the servertype as 'xmlrpc'.\n")
|
||||
if not configuration.bind:
|
||||
sys.exit("FATAL: The '--server-only' option requires a name/address to bind to with the -B option.\n")
|
||||
|
||||
if configuration.bind and configuration.servertype != "xmlrpc":
|
||||
sys.exit("FATAL: If '-B' or '--bind' is defined, we must set the servertype as 'xmlrpc'.\n")
|
||||
|
||||
# Save a logfile for cooker into the current working directory. When the
|
||||
# server is daemonized this logfile will be truncated.
|
||||
@@ -212,8 +220,11 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
bb.utils.clean_environment()
|
||||
|
||||
server = server.BitBakeServer()
|
||||
if configuration.bind:
|
||||
server.initServer((configuration.bind, 0))
|
||||
else:
|
||||
server.initServer()
|
||||
|
||||
server.initServer()
|
||||
idle = server.getServerIdleCB()
|
||||
|
||||
cooker = bb.cooker.BBCooker(configuration, idle, initialenv)
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
# displaying useful information, or acting against them.
|
||||
# See the help output for details on available commands.
|
||||
|
||||
# Copyright (C) 2011 Mentor Graphics Corporation
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
|
||||
import cmd
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import fnmatch
|
||||
from collections import defaultdict
|
||||
|
||||
bindir = os.path.dirname(__file__)
|
||||
topdir = os.path.dirname(bindir)
|
||||
@@ -38,6 +42,8 @@ def main(args):
|
||||
|
||||
cmds = Commands(initialenv)
|
||||
if args:
|
||||
# Allow user to specify e.g. show-layers instead of show_layers
|
||||
args = [args[0].replace('-', '_')] + args[1:]
|
||||
cmds.onecmd(' '.join(args))
|
||||
else:
|
||||
cmds.do_help('')
|
||||
@@ -55,6 +61,7 @@ class Commands(cmd.Cmd):
|
||||
self.config_data = self.cooker.configuration.data
|
||||
bb.providers.logger.setLevel(logging.ERROR)
|
||||
self.cooker_data = None
|
||||
self.bblayers = (self.config_data.getVar('BBLAYERS', True) or "").split()
|
||||
|
||||
def register_idle_function(self, function, data):
|
||||
pass
|
||||
@@ -90,14 +97,14 @@ class Commands(cmd.Cmd):
|
||||
"""display general help or help on a specified command"""
|
||||
if topic:
|
||||
sys.stdout.write('%s: ' % topic)
|
||||
cmd.Cmd.do_help(self,topic)
|
||||
cmd.Cmd.do_help(self, topic.replace('-', '_'))
|
||||
else:
|
||||
sys.stdout.write("usage: bitbake-layers <command> [arguments]\n\n")
|
||||
sys.stdout.write("Available commands:\n")
|
||||
procnames = self.get_names()
|
||||
for procname in procnames:
|
||||
if procname[:3] == 'do_':
|
||||
sys.stdout.write(" %s\n" % procname[3:])
|
||||
sys.stdout.write(" %s\n" % procname[3:].replace('_', '-'))
|
||||
doc = getattr(self, procname).__doc__
|
||||
if doc:
|
||||
sys.stdout.write(" %s\n" % doc.splitlines()[0])
|
||||
@@ -108,34 +115,219 @@ class Commands(cmd.Cmd):
|
||||
logger.plain('')
|
||||
logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
|
||||
logger.plain('=' * 74)
|
||||
layerdirs = str(self.config_data.getVar('BBLAYERS', True)).split()
|
||||
for layerdir in layerdirs:
|
||||
layername = '?'
|
||||
for layerdir in self.bblayers:
|
||||
layername = self.get_layer_name(layerdir)
|
||||
layerpri = 0
|
||||
for layer, _, regex, pri in self.cooker.status.bbfile_config_priorities:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
layername = layer
|
||||
layerpri = pri
|
||||
break
|
||||
|
||||
logger.plain("%s %s %d" % (layername.ljust(20), layerdir.ljust(40), layerpri))
|
||||
|
||||
|
||||
def version_str(self, pe, pv, pr = None):
|
||||
verstr = "%s" % pv
|
||||
if pr:
|
||||
verstr = "%s-%s" % (verstr, pr)
|
||||
if pe:
|
||||
verstr = "%s:%s" % (pe, verstr)
|
||||
return verstr
|
||||
|
||||
|
||||
def do_show_overlayed(self, args):
|
||||
"""list overlayed recipes (where there is a recipe in another layer that has a higher layer priority)
|
||||
"""list overlayed recipes (where the same recipe exists in another layer that has a higher layer priority)
|
||||
|
||||
usage: show_overlayed
|
||||
usage: show-overlayed [-f] [-s]
|
||||
|
||||
Highest priority recipes are listed with the recipes they overlay as subitems.
|
||||
Lists the names of overlayed recipes and the available versions in each
|
||||
layer, with the preferred version first. Note that skipped recipes that
|
||||
are overlayed will also be listed, with a " (skipped)" suffix.
|
||||
|
||||
Options:
|
||||
-f instead of the default formatting, list filenames of higher priority
|
||||
recipes with the ones they overlay indented underneath
|
||||
-s only list overlayed recipes where the version is the same
|
||||
"""
|
||||
self.check_prepare_cooker()
|
||||
if self.cooker.overlayed:
|
||||
logger.plain('Overlayed recipes:')
|
||||
for f in self.cooker.overlayed.iterkeys():
|
||||
logger.plain('%s' % f)
|
||||
for of in self.cooker.overlayed[f]:
|
||||
logger.plain(' %s' % of)
|
||||
else:
|
||||
logger.plain('No overlayed recipes found')
|
||||
|
||||
show_filenames = False
|
||||
show_same_ver_only = False
|
||||
for arg in args.split():
|
||||
if arg == '-f':
|
||||
show_filenames = True
|
||||
elif arg == '-s':
|
||||
show_same_ver_only = True
|
||||
else:
|
||||
sys.stderr.write("show-overlayed: invalid option %s\n" % arg)
|
||||
self.do_help('')
|
||||
return
|
||||
|
||||
items_listed = self.list_recipes('Overlayed recipes', None, True, show_same_ver_only, show_filenames, True)
|
||||
|
||||
# Check for overlayed .bbclass files
|
||||
classes = defaultdict(list)
|
||||
for layerdir in self.bblayers:
|
||||
classdir = os.path.join(layerdir, 'classes')
|
||||
if os.path.exists(classdir):
|
||||
for classfile in os.listdir(classdir):
|
||||
if os.path.splitext(classfile)[1] == '.bbclass':
|
||||
classes[classfile].append(classdir)
|
||||
|
||||
# Locating classes and other files is a bit more complicated than recipes -
|
||||
# layer priority is not a factor; instead BitBake uses the first matching
|
||||
# file in BBPATH, which is manipulated directly by each layer's
|
||||
# conf/layer.conf in turn, thus the order of layers in bblayers.conf is a
|
||||
# factor - however, each layer.conf is free to either prepend or append to
|
||||
# BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
|
||||
# not be exactly the order present in bblayers.conf either.
|
||||
bbpath = str(self.config_data.getVar('BBPATH', True))
|
||||
overlayed_class_found = False
|
||||
for (classfile, classdirs) in classes.items():
|
||||
if len(classdirs) > 1:
|
||||
if not overlayed_class_found:
|
||||
logger.plain('=== Overlayed classes ===')
|
||||
overlayed_class_found = True
|
||||
|
||||
mainfile = bb.utils.which(bbpath, os.path.join('classes', classfile))
|
||||
if show_filenames:
|
||||
logger.plain('%s' % mainfile)
|
||||
else:
|
||||
# We effectively have to guess the layer here
|
||||
logger.plain('%s:' % classfile)
|
||||
mainlayername = '?'
|
||||
for layerdir in self.bblayers:
|
||||
classdir = os.path.join(layerdir, 'classes')
|
||||
if mainfile.startswith(classdir):
|
||||
mainlayername = self.get_layer_name(layerdir)
|
||||
logger.plain(' %s' % mainlayername)
|
||||
for classdir in classdirs:
|
||||
fullpath = os.path.join(classdir, classfile)
|
||||
if fullpath != mainfile:
|
||||
if show_filenames:
|
||||
print(' %s' % fullpath)
|
||||
else:
|
||||
print(' %s' % self.get_layer_name(os.path.dirname(classdir)))
|
||||
|
||||
if overlayed_class_found:
|
||||
items_listed = True;
|
||||
|
||||
if not items_listed:
|
||||
logger.note('No overlayed files found')
|
||||
|
||||
|
||||
def do_show_recipes(self, args):
|
||||
"""list available recipes, showing the layer they are provided by
|
||||
|
||||
usage: show-recipes [-f] [-m] [pnspec]
|
||||
|
||||
Lists the names of overlayed recipes and the available versions in each
|
||||
layer, with the preferred version first. Optionally you may specify
|
||||
pnspec to match a specified recipe name (supports wildcards). Note that
|
||||
skipped recipes will also be listed, with a " (skipped)" suffix.
|
||||
|
||||
Options:
|
||||
-f instead of the default formatting, list filenames of higher priority
|
||||
recipes with other available recipes indented underneath
|
||||
-m only list where multiple recipes (in the same layer or different
|
||||
layers) exist for the same recipe name
|
||||
"""
|
||||
self.check_prepare_cooker()
|
||||
|
||||
show_filenames = False
|
||||
show_multi_provider_only = False
|
||||
pnspec = None
|
||||
title = 'Available recipes:'
|
||||
for arg in args.split():
|
||||
if arg == '-f':
|
||||
show_filenames = True
|
||||
elif arg == '-m':
|
||||
show_multi_provider_only = True
|
||||
elif not arg.startswith('-'):
|
||||
pnspec = arg
|
||||
title = 'Available recipes matching %s:' % pnspec
|
||||
else:
|
||||
sys.stderr.write("show-recipes: invalid option %s\n" % arg)
|
||||
self.do_help('')
|
||||
return
|
||||
self.list_recipes(title, pnspec, False, False, show_filenames, show_multi_provider_only)
|
||||
|
||||
|
||||
def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only):
|
||||
pkg_pn = self.cooker.status.pkg_pn
|
||||
(latest_versions, preferred_versions) = bb.providers.findProviders(self.cooker.configuration.data, self.cooker.status, pkg_pn)
|
||||
allproviders = bb.providers.allProviders(self.cooker.status)
|
||||
|
||||
# Ensure we list skipped recipes
|
||||
# We are largely guessing about PN, PV and the preferred version here,
|
||||
# but we have no choice since skipped recipes are not fully parsed
|
||||
skiplist = self.cooker.skiplist.keys()
|
||||
skiplist.sort( key=lambda fileitem: self.cooker.calc_bbfile_priority(fileitem) )
|
||||
skiplist.reverse()
|
||||
for fn in skiplist:
|
||||
recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
|
||||
p = recipe_parts[0]
|
||||
if len(recipe_parts) > 1:
|
||||
ver = (None, recipe_parts[1], None)
|
||||
else:
|
||||
ver = (None, 'unknown', None)
|
||||
allproviders[p].append((ver, fn))
|
||||
if not p in pkg_pn:
|
||||
pkg_pn[p] = 'dummy'
|
||||
preferred_versions[p] = (ver, fn)
|
||||
|
||||
def print_item(f, pn, ver, layer, ispref):
|
||||
if f in skiplist:
|
||||
skipped = ' (skipped)'
|
||||
else:
|
||||
skipped = ''
|
||||
if show_filenames:
|
||||
if ispref:
|
||||
logger.plain("%s%s", f, skipped)
|
||||
else:
|
||||
logger.plain(" %s%s", f, skipped)
|
||||
else:
|
||||
if ispref:
|
||||
logger.plain("%s:", pn)
|
||||
logger.plain(" %s %s%s", layer.ljust(20), ver, skipped)
|
||||
|
||||
preffiles = []
|
||||
items_listed = False
|
||||
for p in sorted(pkg_pn):
|
||||
if pnspec:
|
||||
if not fnmatch.fnmatch(p, pnspec):
|
||||
continue
|
||||
|
||||
if len(allproviders[p]) > 1 or not show_multi_provider_only:
|
||||
pref = preferred_versions[p]
|
||||
preffile = bb.cache.Cache.virtualfn2realfn(pref[1])[0]
|
||||
if preffile not in preffiles:
|
||||
preflayer = self.get_file_layer(preffile)
|
||||
multilayer = False
|
||||
same_ver = True
|
||||
provs = []
|
||||
for prov in allproviders[p]:
|
||||
provfile = bb.cache.Cache.virtualfn2realfn(prov[1])[0]
|
||||
provlayer = self.get_file_layer(provfile)
|
||||
provs.append((provfile, provlayer, prov[0]))
|
||||
if provlayer != preflayer:
|
||||
multilayer = True
|
||||
if prov[0] != pref[0]:
|
||||
same_ver = False
|
||||
|
||||
if (multilayer or not show_overlayed_only) and (same_ver or not show_same_ver_only):
|
||||
if not items_listed:
|
||||
logger.plain('=== %s ===' % title)
|
||||
items_listed = True
|
||||
print_item(preffile, p, self.version_str(pref[0][0], pref[0][1]), preflayer, True)
|
||||
for (provfile, provlayer, provver) in provs:
|
||||
if provfile != preffile:
|
||||
print_item(provfile, p, self.version_str(provver[0], provver[1]), provlayer, False)
|
||||
# Ensure we don't show two entries for BBCLASSEXTENDed recipes
|
||||
preffiles.append(preffile)
|
||||
|
||||
return items_listed
|
||||
|
||||
|
||||
def do_flatten(self, args):
|
||||
"""flattens layer configuration into a separate output directory.
|
||||
@@ -179,22 +371,20 @@ build results (as the layer priority order has effectively changed).
|
||||
return
|
||||
|
||||
self.check_prepare_cooker()
|
||||
layers = (self.config_data.getVar('BBLAYERS', True) or "").split()
|
||||
layers = self.bblayers
|
||||
if len(arglist) > 2:
|
||||
layernames = arglist[:-1]
|
||||
found_layernames = []
|
||||
found_layerdirs = []
|
||||
for layerdir in layers:
|
||||
for layername, _, regex, _ in self.cooker.status.bbfile_config_priorities:
|
||||
if layername in layernames:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
found_layerdirs.append(layerdir)
|
||||
found_layernames.append(layername)
|
||||
break
|
||||
layername = self.get_layer_name(layerdir)
|
||||
if layername in layernames:
|
||||
found_layerdirs.append(layerdir)
|
||||
found_layernames.append(layername)
|
||||
|
||||
for layername in layernames:
|
||||
if not layername in found_layernames:
|
||||
logger.error('Unable to find layer %s in current configuration, please run "%s show_layers" to list configured layers' % (layername, os.path.basename(sys.argv[0])))
|
||||
logger.error('Unable to find layer %s in current configuration, please run "%s show-layers" to list configured layers' % (layername, os.path.basename(sys.argv[0])))
|
||||
return
|
||||
layers = found_layerdirs
|
||||
else:
|
||||
@@ -266,10 +456,9 @@ build results (as the layer priority order has effectively changed).
|
||||
first_regex = None
|
||||
layerdir = layers[0]
|
||||
for layername, pattern, regex, _ in self.cooker.status.bbfile_config_priorities:
|
||||
if (not layernames) or layername in layernames:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
first_regex = regex
|
||||
break
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
first_regex = regex
|
||||
break
|
||||
|
||||
if first_regex:
|
||||
# Find the BBFILES entries that match (which will have come from this conf/layer.conf file)
|
||||
@@ -295,17 +484,22 @@ build results (as the layer priority order has effectively changed).
|
||||
if not entry_found:
|
||||
logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full)
|
||||
|
||||
def get_append_layer(self, appendname):
|
||||
def get_file_layer(self, filename):
|
||||
for layer, _, regex, _ in self.cooker.status.bbfile_config_priorities:
|
||||
if regex.match(appendname):
|
||||
return layer
|
||||
if regex.match(filename):
|
||||
for layerdir in self.bblayers:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
return self.get_layer_name(layerdir)
|
||||
return "?"
|
||||
|
||||
def get_layer_name(self, layerdir):
|
||||
return os.path.basename(layerdir.rstrip(os.sep))
|
||||
|
||||
def apply_append(self, appendname, recipename):
|
||||
appendfile = open(appendname, 'r')
|
||||
recipefile = open(recipename, 'a')
|
||||
recipefile.write('\n')
|
||||
recipefile.write('##### bbappended from %s #####\n' % self.get_append_layer(appendname))
|
||||
recipefile.write('##### bbappended from %s #####\n' % self.get_file_layer(appendname))
|
||||
recipefile.writelines(appendfile.readlines())
|
||||
recipefile.close()
|
||||
appendfile.close()
|
||||
@@ -313,7 +507,7 @@ build results (as the layer priority order has effectively changed).
|
||||
def do_show_appends(self, args):
|
||||
"""list bbappend files and recipe files they apply to
|
||||
|
||||
usage: show_appends
|
||||
usage: show-appends
|
||||
|
||||
Recipes are listed with the bbappends that apply to them as subitems.
|
||||
"""
|
||||
|
||||
@@ -204,7 +204,7 @@ include</literal> directive.</para>
|
||||
<section>
|
||||
<title>Inheritance</title>
|
||||
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
|
||||
<para>The <literal>inherit</literal> directive is a means of specifying what classes of functionality your .bb requires. It is a rudimentary form of inheritance. For example, you can easily abstract out the tasks involved in building a package that uses autoconf and automake, and put that into a bbclass for your packages to make use of. A given bbclass is located by searching for classes/filename.oeclass in <envar>BBPATH</envar>, where filename is what you inherited.</para>
|
||||
<para>The <literal>inherit</literal> directive is a means of specifying what classes of functionality your .bb requires. It is a rudimentary form of inheritance. For example, you can easily abstract out the tasks involved in building a package that uses autoconf and automake, and put that into a bbclass for your packages to make use of. A given bbclass is located by searching for classes/filename.bbclass in <envar>BBPATH</envar>, where filename is what you inherited.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Tasks</title>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
__version__ = "1.15.0"
|
||||
__version__ = "1.15.1"
|
||||
|
||||
import sys
|
||||
if sys.version_info < (2, 6, 0):
|
||||
|
||||
@@ -53,7 +53,7 @@ class FuncFailed(Exception):
|
||||
self.logfile = logfile
|
||||
self.name = name
|
||||
if name:
|
||||
self.msg = "Function '%s' failed" % name
|
||||
self.msg = 'Function failed: %s' % name
|
||||
else:
|
||||
self.msg = "Function failed"
|
||||
|
||||
@@ -91,9 +91,16 @@ class TaskSucceeded(TaskBase):
|
||||
class TaskFailed(TaskBase):
|
||||
"""Task execution failed"""
|
||||
|
||||
def __init__(self, task, logfile, metadata, errprinted = False):
|
||||
self.logfile = logfile
|
||||
self.errprinted = errprinted
|
||||
super(TaskFailed, self).__init__(task, metadata)
|
||||
|
||||
class TaskFailedSilent(TaskBase):
|
||||
"""Task execution failed (silently)"""
|
||||
def __init__(self, task, logfile, metadata):
|
||||
self.logfile = logfile
|
||||
super(TaskFailed, self).__init__(task, metadata)
|
||||
super(TaskFailedSilent, self).__init__(task, metadata)
|
||||
|
||||
class TaskInvalid(TaskBase):
|
||||
|
||||
@@ -152,8 +159,6 @@ def exec_func(func, d, dirs = None):
|
||||
bb.utils.mkdirhier(adir)
|
||||
|
||||
ispython = flags.get('python')
|
||||
if flags.get('fakeroot') and not flags.get('task'):
|
||||
bb.fatal("Function %s specifies fakeroot but isn't a task?!" % func)
|
||||
|
||||
lockflag = flags.get('lockfiles')
|
||||
if lockflag:
|
||||
@@ -222,9 +227,10 @@ def exec_func_shell(function, d, runfile, cwd=None):
|
||||
|
||||
with open(runfile, 'w') as script:
|
||||
script.write('#!/bin/sh -e\n')
|
||||
if bb.msg.loggerDefaultVerbose:
|
||||
script.write("set -x\n")
|
||||
data.emit_func(function, script, d)
|
||||
|
||||
if bb.msg.loggerVerboseLogs:
|
||||
script.write("set -x\n")
|
||||
if cwd:
|
||||
script.write("cd %s\n" % cwd)
|
||||
script.write("%s\n" % function)
|
||||
@@ -232,6 +238,10 @@ def exec_func_shell(function, d, runfile, cwd=None):
|
||||
os.chmod(runfile, 0775)
|
||||
|
||||
cmd = runfile
|
||||
if d.getVarFlag(function, 'fakeroot'):
|
||||
fakerootcmd = d.getVar('FAKEROOT', True)
|
||||
if fakerootcmd:
|
||||
cmd = [fakerootcmd, runfile]
|
||||
|
||||
if bb.msg.loggerDefaultVerbose:
|
||||
logfile = LogTee(logger, sys.stdout)
|
||||
@@ -286,6 +296,13 @@ def _exec_task(fn, task, d, quieterr):
|
||||
prefuncs = localdata.getVarFlag(task, 'prefuncs', expand=True)
|
||||
postfuncs = localdata.getVarFlag(task, 'postfuncs', expand=True)
|
||||
|
||||
class ErrorCheckHandler(logging.Handler):
|
||||
def __init__(self):
|
||||
self.triggered = False
|
||||
logging.Handler.__init__(self, logging.ERROR)
|
||||
def emit(self, record):
|
||||
self.triggered = True
|
||||
|
||||
# Handle logfiles
|
||||
si = file('/dev/null', 'r')
|
||||
try:
|
||||
@@ -311,6 +328,9 @@ def _exec_task(fn, task, d, quieterr):
|
||||
handler.setLevel(logging.DEBUG - 2)
|
||||
bblogger.addHandler(handler)
|
||||
|
||||
errchk = ErrorCheckHandler()
|
||||
bblogger.addHandler(errchk)
|
||||
|
||||
localdata.setVar('BB_LOGFILE', logfn)
|
||||
|
||||
event.fire(TaskStarted(task, localdata), localdata)
|
||||
@@ -321,9 +341,12 @@ def _exec_task(fn, task, d, quieterr):
|
||||
for func in (postfuncs or '').split():
|
||||
exec_func(func, localdata)
|
||||
except FuncFailed as exc:
|
||||
if not quieterr:
|
||||
if quieterr:
|
||||
event.fire(TaskFailedSilent(task, logfn, localdata), localdata)
|
||||
else:
|
||||
errprinted = errchk.triggered
|
||||
logger.error(str(exc))
|
||||
event.fire(TaskFailed(task, logfn, localdata), localdata)
|
||||
event.fire(TaskFailed(task, logfn, localdata, errprinted), localdata)
|
||||
return 1
|
||||
finally:
|
||||
sys.stdout.flush()
|
||||
@@ -366,7 +389,7 @@ def exec_task(fn, task, d):
|
||||
if not quieterr:
|
||||
logger.error("Build of %s failed" % (task))
|
||||
logger.error(format_exc())
|
||||
failedevent = TaskFailed(task, None, d)
|
||||
failedevent = TaskFailed(task, None, d, True)
|
||||
event.fire(failedevent, d)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ except ImportError:
|
||||
logger.info("Importing cPickle failed. "
|
||||
"Falling back to a very slow implementation.")
|
||||
|
||||
__cache_version__ = "142"
|
||||
__cache_version__ = "143"
|
||||
|
||||
def getCacheFile(path, filename):
|
||||
return os.path.join(path, filename)
|
||||
def getCacheFile(path, filename, data_hash):
|
||||
return os.path.join(path, filename + "." + data_hash)
|
||||
|
||||
# RecipeInfoCommon defines common data retrieving methods
|
||||
# from meta data for caches. CoreRecipeInfo as well as other
|
||||
@@ -137,9 +137,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
self.rdepends_pkg = self.pkgvar('RDEPENDS', self.packages, metadata)
|
||||
self.rrecommends_pkg = self.pkgvar('RRECOMMENDS', self.packages, metadata)
|
||||
self.inherits = self.getvar('__inherit_cache', metadata)
|
||||
self.summary = self.getvar('SUMMARY', metadata)
|
||||
self.license = self.getvar('LICENSE', metadata)
|
||||
self.section = self.getvar('SECTION', metadata)
|
||||
self.fakerootenv = self.getvar('FAKEROOTENV', metadata)
|
||||
self.fakerootdirs = self.getvar('FAKEROOTDIRS', metadata)
|
||||
self.fakerootnoenv = self.getvar('FAKEROOTNOENV', metadata)
|
||||
@@ -174,9 +171,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
|
||||
cachedata.basetaskhash = {}
|
||||
cachedata.inherits = {}
|
||||
cachedata.summary = {}
|
||||
cachedata.license = {}
|
||||
cachedata.section = {}
|
||||
cachedata.fakerootenv = {}
|
||||
cachedata.fakerootnoenv = {}
|
||||
cachedata.fakerootdirs = {}
|
||||
@@ -240,9 +234,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
cachedata.basetaskhash[identifier] = taskhash
|
||||
|
||||
cachedata.inherits[fn] = self.inherits
|
||||
cachedata.summary[fn] = self.summary
|
||||
cachedata.license[fn] = self.license
|
||||
cachedata.section[fn] = self.section
|
||||
cachedata.fakerootenv[fn] = self.fakerootenv
|
||||
cachedata.fakerootnoenv[fn] = self.fakerootnoenv
|
||||
cachedata.fakerootdirs[fn] = self.fakerootdirs
|
||||
@@ -254,7 +245,7 @@ class Cache(object):
|
||||
BitBake Cache implementation
|
||||
"""
|
||||
|
||||
def __init__(self, data, caches_array):
|
||||
def __init__(self, data, data_hash, caches_array):
|
||||
# Pass caches_array information into Cache Constructor
|
||||
# It will be used in later for deciding whether we
|
||||
# need extra cache file dump/load support
|
||||
@@ -266,6 +257,7 @@ class Cache(object):
|
||||
self.data = None
|
||||
self.data_fn = None
|
||||
self.cacheclean = True
|
||||
self.data_hash = data_hash
|
||||
|
||||
if self.cachedir in [None, '']:
|
||||
self.has_cache = False
|
||||
@@ -274,26 +266,17 @@ class Cache(object):
|
||||
return
|
||||
|
||||
self.has_cache = True
|
||||
self.cachefile = getCacheFile(self.cachedir, "bb_cache.dat")
|
||||
self.cachefile = getCacheFile(self.cachedir, "bb_cache.dat", self.data_hash)
|
||||
|
||||
logger.debug(1, "Using cache in '%s'", self.cachedir)
|
||||
bb.utils.mkdirhier(self.cachedir)
|
||||
|
||||
# If any of configuration.data's dependencies are newer than the
|
||||
# cache there isn't even any point in loading it...
|
||||
newest_mtime = 0
|
||||
deps = data.getVar("__base_depends")
|
||||
|
||||
old_mtimes = [old_mtime for _, old_mtime in deps]
|
||||
old_mtimes.append(newest_mtime)
|
||||
newest_mtime = max(old_mtimes)
|
||||
|
||||
cache_ok = True
|
||||
if self.caches_array:
|
||||
for cache_class in self.caches_array:
|
||||
if type(cache_class) is type and issubclass(cache_class, RecipeInfoCommon):
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile)
|
||||
cache_ok = cache_ok and (bb.parse.cached_mtime_noerror(cachefile) >= newest_mtime)
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
|
||||
cache_ok = cache_ok and os.path.exists(cachefile)
|
||||
cache_class.init_cacheData(self)
|
||||
if cache_ok:
|
||||
self.load_cachefile()
|
||||
@@ -327,7 +310,7 @@ class Cache(object):
|
||||
# Calculate the correct cachesize of all those cache files
|
||||
for cache_class in self.caches_array:
|
||||
if type(cache_class) is type and issubclass(cache_class, RecipeInfoCommon):
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile)
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
|
||||
with open(cachefile, "rb") as cachefile:
|
||||
cachesize += os.fstat(cachefile.fileno()).st_size
|
||||
|
||||
@@ -335,7 +318,7 @@ class Cache(object):
|
||||
|
||||
for cache_class in self.caches_array:
|
||||
if type(cache_class) is type and issubclass(cache_class, RecipeInfoCommon):
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile)
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
|
||||
with open(cachefile, "rb") as cachefile:
|
||||
pickled = pickle.Unpickler(cachefile)
|
||||
while cachefile:
|
||||
@@ -353,7 +336,7 @@ class Cache(object):
|
||||
current_percent = 100 * current_progress / cachesize
|
||||
if current_percent > previous_percent:
|
||||
previous_percent = current_percent
|
||||
bb.event.fire(bb.event.CacheLoadProgress(current_progress),
|
||||
bb.event.fire(bb.event.CacheLoadProgress(current_progress, cachesize),
|
||||
self.data)
|
||||
|
||||
previous_progress += current_progress
|
||||
@@ -588,7 +571,7 @@ class Cache(object):
|
||||
for cache_class in self.caches_array:
|
||||
if type(cache_class) is type and issubclass(cache_class, RecipeInfoCommon):
|
||||
cache_class_name = cache_class.__name__
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile)
|
||||
cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
|
||||
file_dict[cache_class_name] = open(cachefile, "wb")
|
||||
pickler_dict[cache_class_name] = pickle.Pickler(file_dict[cache_class_name], pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
@@ -693,7 +676,7 @@ def init(cooker):
|
||||
Files causing parsing errors are evicted from the cache.
|
||||
|
||||
"""
|
||||
return Cache(cooker.configuration.data)
|
||||
return Cache(cooker.configuration.data, cooker.configuration.data_hash)
|
||||
|
||||
|
||||
class CacheData(object):
|
||||
|
||||
@@ -40,6 +40,7 @@ class HobRecipeInfo(RecipeInfoCommon):
|
||||
self.summary = self.getvar('SUMMARY', metadata)
|
||||
self.license = self.getvar('LICENSE', metadata)
|
||||
self.section = self.getvar('SECTION', metadata)
|
||||
self.description = self.getvar('DESCRIPTION', metadata)
|
||||
|
||||
@classmethod
|
||||
def init_cacheData(cls, cachedata):
|
||||
@@ -47,8 +48,10 @@ class HobRecipeInfo(RecipeInfoCommon):
|
||||
cachedata.summary = {}
|
||||
cachedata.license = {}
|
||||
cachedata.section = {}
|
||||
cachedata.description = {}
|
||||
|
||||
def add_cacheData(self, cachedata, fn):
|
||||
cachedata.summary[fn] = self.summary
|
||||
cachedata.license[fn] = self.license
|
||||
cachedata.section[fn] = self.section
|
||||
cachedata.description[fn] = self.description
|
||||
|
||||
@@ -173,6 +173,18 @@ class CommandsSync:
|
||||
"""
|
||||
command.cooker.reset()
|
||||
|
||||
def getCpuCount(self, command, params):
|
||||
"""
|
||||
Get the CPU count on the bitbake server
|
||||
"""
|
||||
return bb.utils.cpu_count()
|
||||
|
||||
def triggerEvent(self, command, params):
|
||||
"""
|
||||
Trigger a certain event
|
||||
"""
|
||||
event = params[0]
|
||||
bb.event.fire(eval(event), command.cooker.configuration.data)
|
||||
|
||||
class CommandsAsync:
|
||||
"""
|
||||
@@ -230,14 +242,21 @@ class CommandsAsync:
|
||||
included in the package list.
|
||||
If pkg_list provided use that list (plus any extras brought in by
|
||||
klass) rather than generating a tree for all packages.
|
||||
|
||||
Add a new option "resolve" to indicate if we need to resolve the
|
||||
replacement for "virtual/xxx" like pn.
|
||||
"""
|
||||
klass = params[0]
|
||||
if len(params) > 1:
|
||||
resolve = False
|
||||
if len(params) > 2:
|
||||
pkg_list = params[1]
|
||||
resolve = params[2]
|
||||
elif len(params) > 1:
|
||||
pkg_list = params[1]
|
||||
else:
|
||||
pkg_list = []
|
||||
|
||||
command.cooker.generateTargetsTree(klass, pkg_list)
|
||||
command.cooker.generateTargetsTree(klass, pkg_list, resolve)
|
||||
command.finishAsyncCommand()
|
||||
generateTargetsTree.needcache = True
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ from functools import wraps
|
||||
from collections import defaultdict
|
||||
import bb, bb.exceptions, bb.command
|
||||
from bb import utils, data, parse, event, cache, providers, taskdata, runqueue
|
||||
import Queue
|
||||
import prserv.serv
|
||||
|
||||
logger = logging.getLogger("BitBake")
|
||||
@@ -44,9 +45,9 @@ buildlog = logging.getLogger("BitBake.Build")
|
||||
parselog = logging.getLogger("BitBake.Parsing")
|
||||
providerlog = logging.getLogger("BitBake.Provider")
|
||||
|
||||
class MultipleMatches(Exception):
|
||||
class NoSpecificMatch(bb.BBHandledException):
|
||||
"""
|
||||
Exception raised when multiple file matches are found
|
||||
Exception raised when no or multiple file matches are found
|
||||
"""
|
||||
|
||||
class NothingToBuild(Exception):
|
||||
@@ -54,6 +55,11 @@ class NothingToBuild(Exception):
|
||||
Exception raised when there is nothing to build
|
||||
"""
|
||||
|
||||
class CollectionError(bb.BBHandledException):
|
||||
"""
|
||||
Exception raised when layer configuration is incorrect
|
||||
"""
|
||||
|
||||
class state:
|
||||
initial, parsing, running, shutdown, stop = range(5)
|
||||
|
||||
@@ -200,6 +206,10 @@ class BBCooker:
|
||||
|
||||
def parseConfiguration(self):
|
||||
|
||||
# Set log file verbosity
|
||||
verboselogs = bb.utils.to_boolean(self.configuration.data.getVar("BB_VERBOSE_LOGS", "0"))
|
||||
if verboselogs:
|
||||
bb.msg.loggerVerboseLogs = True
|
||||
|
||||
# Change nice level if we're asked to
|
||||
nice = self.configuration.data.getVar("BB_NICE_LEVEL", True)
|
||||
@@ -258,20 +268,8 @@ class BBCooker:
|
||||
# Need files parsed
|
||||
self.updateCache()
|
||||
|
||||
# Need to ensure data store is expanded
|
||||
localdata = data.createCopy(self.configuration.data)
|
||||
bb.data.update_data(localdata)
|
||||
bb.data.expandKeys(localdata)
|
||||
|
||||
pkg_pn = self.status.pkg_pn
|
||||
preferred_versions = {}
|
||||
latest_versions = {}
|
||||
|
||||
# Sort by priority
|
||||
for pn in pkg_pn:
|
||||
(last_ver, last_file, pref_ver, pref_file) = bb.providers.findBestProvider(pn, localdata, self.status)
|
||||
preferred_versions[pn] = (pref_ver, pref_file)
|
||||
latest_versions[pn] = (last_ver, last_file)
|
||||
(latest_versions, preferred_versions) = bb.providers.findProviders(self.configuration.data, self.status, pkg_pn)
|
||||
|
||||
logger.plain("%-35s %25s %25s", "Package Name", "Latest Version", "Preferred Version")
|
||||
logger.plain("%-35s %25s %25s\n", "============", "==============", "=================")
|
||||
@@ -345,6 +343,7 @@ class BBCooker:
|
||||
"""
|
||||
Prepare a runqueue and taskdata object for iteration over pkgs_to_build
|
||||
"""
|
||||
bb.event.fire(bb.event.TreeDataPreparationStarted(), self.configuration.data)
|
||||
# Need files parsed
|
||||
self.updateCache()
|
||||
# If we are told to do the None task then query the default task
|
||||
@@ -361,11 +360,14 @@ class BBCooker:
|
||||
taskdata = bb.taskdata.TaskData(False, skiplist=self.skiplist)
|
||||
|
||||
runlist = []
|
||||
current = 0
|
||||
for k in pkgs_to_build:
|
||||
taskdata.add_provider(localdata, self.status, k)
|
||||
runlist.append([k, "do_%s" % task])
|
||||
current += 1
|
||||
bb.event.fire(bb.event.TreeDataPreparationProgress(current, len(pkgs_to_build)), self.configuration.data)
|
||||
taskdata.add_unresolved(localdata, self.status)
|
||||
|
||||
bb.event.fire(bb.event.TreeDataPreparationCompleted(len(pkgs_to_build)), self.configuration.data)
|
||||
return runlist, taskdata
|
||||
|
||||
def generateTaskDepTreeData(self, pkgs_to_build, task):
|
||||
@@ -440,7 +442,20 @@ class BBCooker:
|
||||
|
||||
return depend_tree
|
||||
|
||||
def generatePkgDepTreeData(self, pkgs_to_build, task):
|
||||
def append_package(self, taskdata, depend_tree_package, package):
|
||||
if package not in depend_tree_package:
|
||||
targetid = taskdata.getrun_id(package)
|
||||
if targetid in taskdata.run_targets and taskdata.run_targets[targetid]:
|
||||
fnid = taskdata.run_targets[targetid][0]
|
||||
fn = taskdata.fn_index[fnid]
|
||||
pn = self.status.pkg_fn[fn]
|
||||
version = "%s:%s-%s" % self.status.pkg_pepvpr[fn]
|
||||
depend_tree_package[package] = {}
|
||||
depend_tree_package[package]["pn"] = pn
|
||||
depend_tree_package[package]["filename"] = fn
|
||||
depend_tree_package[package]["version"] = version
|
||||
|
||||
def generatePkgDepTreeData(self, pkgs_to_build, task, resolve=False):
|
||||
"""
|
||||
Create a dependency tree of pkgs_to_build, returning the data.
|
||||
"""
|
||||
@@ -457,6 +472,7 @@ class BBCooker:
|
||||
depend_tree["rdepends-pn"] = {}
|
||||
depend_tree["packages"] = {}
|
||||
depend_tree["rdepends-pkg"] = {}
|
||||
depend_tree["rrecs-pkg"] = {}
|
||||
|
||||
for task in xrange(len(tasks_fnid)):
|
||||
fnid = tasks_fnid[task]
|
||||
@@ -466,6 +482,9 @@ class BBCooker:
|
||||
summary = self.status.summary[fn]
|
||||
lic = self.status.license[fn]
|
||||
section = self.status.section[fn]
|
||||
description = self.status.description[fn]
|
||||
rdepends = self.status.rundeps[fn]
|
||||
rrecs = self.status.runrecs[fn]
|
||||
if pn not in depend_tree["pn"]:
|
||||
depend_tree["pn"][pn] = {}
|
||||
depend_tree["pn"][pn]["filename"] = fn
|
||||
@@ -473,6 +492,8 @@ class BBCooker:
|
||||
depend_tree["pn"][pn]["summary"] = summary
|
||||
depend_tree["pn"][pn]["license"] = lic
|
||||
depend_tree["pn"][pn]["section"] = section
|
||||
depend_tree["pn"][pn]["description"] = description
|
||||
depend_tree["pn"][pn]["packages"] = rdepends.keys()
|
||||
|
||||
if fnid not in seen_fnids:
|
||||
seen_fnids.append(fnid)
|
||||
@@ -480,25 +501,44 @@ class BBCooker:
|
||||
|
||||
depend_tree["depends"][pn] = []
|
||||
for dep in taskdata.depids[fnid]:
|
||||
depend_tree["depends"][pn].append(taskdata.build_names_index[dep])
|
||||
if resolve:
|
||||
item = taskdata.build_names_index[dep]
|
||||
pn_provider = ""
|
||||
targetid = taskdata.getbuild_id(item)
|
||||
if targetid in taskdata.build_targets and taskdata.build_targets[targetid]:
|
||||
fnid = taskdata.build_targets[targetid][0]
|
||||
fn_provider = taskdata.fn_index[fnid]
|
||||
pn_provider = self.status.pkg_fn[fn_provider]
|
||||
else:
|
||||
pn_provider = item
|
||||
depend_tree["depends"][pn].append(pn_provider)
|
||||
else:
|
||||
depend_tree["depends"][pn].append(taskdata.build_names_index[dep])
|
||||
|
||||
depend_tree["rdepends-pn"][pn] = []
|
||||
for rdep in taskdata.rdepids[fnid]:
|
||||
depend_tree["rdepends-pn"][pn].append(taskdata.run_names_index[rdep])
|
||||
|
||||
rdepends = self.status.rundeps[fn]
|
||||
for package in rdepends:
|
||||
depend_tree["rdepends-pkg"][package] = []
|
||||
for rdepend in rdepends[package]:
|
||||
depend_tree["rdepends-pkg"][package].append(rdepend)
|
||||
packages.append(package)
|
||||
if resolve:
|
||||
self.append_package(taskdata, depend_tree["packages"], rdepend)
|
||||
if not package in packages:
|
||||
packages.append(package)
|
||||
|
||||
for package in rrecs:
|
||||
depend_tree["rrecs-pkg"][package] = []
|
||||
for rrec in rrecs[package]:
|
||||
depend_tree["rrecs-pkg"][package].append(rrec)
|
||||
if resolve:
|
||||
self.append_package(taskdata, depend_tree["packages"], rrec)
|
||||
if not package in packages:
|
||||
packages.append(package)
|
||||
|
||||
for package in packages:
|
||||
if package not in depend_tree["packages"]:
|
||||
depend_tree["packages"][package] = {}
|
||||
depend_tree["packages"][package]["pn"] = pn
|
||||
depend_tree["packages"][package]["filename"] = fn
|
||||
depend_tree["packages"][package]["version"] = version
|
||||
self.append_package(taskdata, depend_tree["packages"], package)
|
||||
|
||||
return depend_tree
|
||||
|
||||
@@ -744,7 +784,7 @@ class BBCooker:
|
||||
|
||||
return pkg_list
|
||||
|
||||
def generateTargetsTree(self, klass=None, pkgs=[]):
|
||||
def generateTargetsTree(self, klass=None, pkgs=[], resolve=False):
|
||||
"""
|
||||
Generate a dependency tree of buildable targets
|
||||
Generate an event with the result
|
||||
@@ -759,7 +799,7 @@ class BBCooker:
|
||||
pkgs = pkgs + extra_pkgs
|
||||
|
||||
# generate a dependency tree for all our packages
|
||||
tree = self.generatePkgDepTreeData(pkgs, 'build')
|
||||
tree = self.generatePkgDepTreeData(pkgs, 'build', resolve)
|
||||
bb.event.fire(bb.event.TargetsTreeGenerated(tree), self.configuration.data)
|
||||
|
||||
def buildWorldTargetList(self):
|
||||
@@ -855,12 +895,15 @@ class BBCooker:
|
||||
if data.getVar("BB_WORKERCONTEXT", False) is None:
|
||||
bb.fetch.fetcher_init(data)
|
||||
bb.codeparser.parser_cache_init(data)
|
||||
bb.parse.init_parser(data)
|
||||
bb.event.fire(bb.event.ConfigParsed(), data)
|
||||
bb.parse.init_parser(data)
|
||||
data.setVar('BBINCLUDED',bb.parse.get_file_depends(data))
|
||||
self.configuration.data = data
|
||||
self.configuration.data_hash = data.get_hash()
|
||||
|
||||
def handleCollections( self, collections ):
|
||||
"""Handle collections"""
|
||||
errors = False
|
||||
self.status.bbfile_config_priorities = []
|
||||
if collections:
|
||||
collection_priorities = {}
|
||||
@@ -875,6 +918,7 @@ class BBCooker:
|
||||
prio = int(priority)
|
||||
except ValueError:
|
||||
parselog.error("invalid value for BBFILE_PRIORITY_%s: \"%s\"", c, priority)
|
||||
errors = True
|
||||
if min_prio == 0 or prio < min_prio:
|
||||
min_prio = prio
|
||||
collection_priorities[c] = prio
|
||||
@@ -893,6 +937,7 @@ class BBCooker:
|
||||
depver = int(depsplit[1])
|
||||
except ValueError:
|
||||
parselog.error("invalid version value in LAYERDEPENDS_%s: \"%s\"", c, dep)
|
||||
errors = True
|
||||
continue
|
||||
else:
|
||||
depver = None
|
||||
@@ -907,13 +952,17 @@ class BBCooker:
|
||||
lver = int(layerver)
|
||||
except ValueError:
|
||||
parselog.error("invalid value for LAYERVERSION_%s: \"%s\"", c, layerver)
|
||||
errors = True
|
||||
continue
|
||||
if lver <> depver:
|
||||
parselog.error("Layer dependency %s of layer %s is at version %d, expected %d", dep, c, lver, depver)
|
||||
errors = True
|
||||
else:
|
||||
parselog.error("Layer dependency %s of layer %s has no version, expected %d", dep, c, depver)
|
||||
errors = True
|
||||
else:
|
||||
parselog.error("Layer dependency %s of layer %s not found", dep, c)
|
||||
errors = True
|
||||
collection_depends[c] = depnamelist
|
||||
else:
|
||||
collection_depends[c] = []
|
||||
@@ -937,13 +986,18 @@ class BBCooker:
|
||||
regex = self.configuration.data.getVar("BBFILE_PATTERN_%s" % c, 1)
|
||||
if regex == None:
|
||||
parselog.error("BBFILE_PATTERN_%s not defined" % c)
|
||||
errors = True
|
||||
continue
|
||||
try:
|
||||
cre = re.compile(regex)
|
||||
except re.error:
|
||||
parselog.error("BBFILE_PATTERN_%s \"%s\" is not a valid regular expression", c, regex)
|
||||
errors = True
|
||||
continue
|
||||
self.status.bbfile_config_priorities.append((c, regex, cre, collection_priorities[c]))
|
||||
if errors:
|
||||
# We've already printed the actual error(s)
|
||||
raise CollectionError("Errors during parsing layer configuration")
|
||||
|
||||
def buildSetVars(self):
|
||||
"""
|
||||
@@ -979,10 +1033,15 @@ class BBCooker:
|
||||
"""
|
||||
matches = self.matchFiles(buildfile)
|
||||
if len(matches) != 1:
|
||||
parselog.error("Unable to match %s (%s matches found):" % (buildfile, len(matches)))
|
||||
for f in matches:
|
||||
parselog.error(" %s" % f)
|
||||
raise MultipleMatches
|
||||
if matches:
|
||||
msg = "Unable to match '%s' to a specific recipe file - %s matches found:" % (buildfile, len(matches))
|
||||
if matches:
|
||||
for f in matches:
|
||||
msg += "\n %s" % f
|
||||
parselog.error(msg)
|
||||
else:
|
||||
parselog.error("Unable to find any recipe file matching '%s'" % buildfile)
|
||||
raise NoSpecificMatch
|
||||
return matches[0]
|
||||
|
||||
def buildFile(self, buildfile, task):
|
||||
@@ -1060,8 +1119,6 @@ class BBCooker:
|
||||
try:
|
||||
retval = rq.execute_runqueue()
|
||||
except runqueue.TaskFailure as exc:
|
||||
for fnid in exc.args:
|
||||
buildlog.error("'%s' failed" % taskdata.fn_index[fnid])
|
||||
failures += len(exc.args)
|
||||
retval = False
|
||||
except SystemExit as exc:
|
||||
@@ -1069,7 +1126,7 @@ class BBCooker:
|
||||
return False
|
||||
|
||||
if not retval:
|
||||
bb.event.fire(bb.event.BuildCompleted(buildname, item, failures), self.configuration.event_data)
|
||||
bb.event.fire(bb.event.BuildCompleted(len(rq.rqdata.runq_fnid), buildname, item, failures), self.configuration.event_data)
|
||||
self.command.finishAsyncCommand()
|
||||
return False
|
||||
if retval is True:
|
||||
@@ -1090,6 +1147,7 @@ class BBCooker:
|
||||
if (task == None):
|
||||
task = self.configuration.cmd
|
||||
|
||||
universe = ('universe' in targets)
|
||||
targets = self.checkPackages(targets)
|
||||
|
||||
def buildTargetsIdle(server, rq, abort):
|
||||
@@ -1101,8 +1159,6 @@ class BBCooker:
|
||||
try:
|
||||
retval = rq.execute_runqueue()
|
||||
except runqueue.TaskFailure as exc:
|
||||
for fnid in exc.args:
|
||||
buildlog.error("'%s' failed" % taskdata.fn_index[fnid])
|
||||
failures += len(exc.args)
|
||||
retval = False
|
||||
except SystemExit as exc:
|
||||
@@ -1110,7 +1166,7 @@ class BBCooker:
|
||||
return False
|
||||
|
||||
if not retval:
|
||||
bb.event.fire(bb.event.BuildCompleted(buildname, targets, failures), self.configuration.data)
|
||||
bb.event.fire(bb.event.BuildCompleted(len(rq.rqdata.runq_fnid), buildname, targets, failures), self.configuration.data)
|
||||
self.command.finishAsyncCommand()
|
||||
return False
|
||||
if retval is True:
|
||||
@@ -1135,6 +1191,8 @@ class BBCooker:
|
||||
taskdata.add_unresolved(localdata, self.status)
|
||||
|
||||
rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist)
|
||||
if universe:
|
||||
rq.rqdata.warn_multi_bb = True
|
||||
|
||||
self.server_registration_cb(buildTargetsIdle, rq)
|
||||
|
||||
@@ -1188,6 +1246,7 @@ class BBCooker:
|
||||
pkgs_to_build.append(t)
|
||||
|
||||
if 'universe' in pkgs_to_build:
|
||||
parselog.warn("The \"universe\" target is only intended for testing and may produce errors.")
|
||||
parselog.debug(1, "collating packages for \"universe\"")
|
||||
pkgs_to_build.remove('universe')
|
||||
for t in self.status.universe_target:
|
||||
@@ -1402,7 +1461,7 @@ def _parse(fn, data, include=True):
|
||||
|
||||
@catch_parse_error
|
||||
def _inherit(bbclass, data):
|
||||
bb.parse.BBHandler.inherit([bbclass], data)
|
||||
bb.parse.BBHandler.inherit([bbclass], "configuration INHERITs", 0, data)
|
||||
return data
|
||||
|
||||
class ParsingFailure(Exception):
|
||||
@@ -1411,26 +1470,94 @@ class ParsingFailure(Exception):
|
||||
self.recipe = recipe
|
||||
Exception.__init__(self, realexception, recipe)
|
||||
|
||||
def parse_file(task):
|
||||
filename, appends, caches_array = task
|
||||
try:
|
||||
return True, bb.cache.Cache.parse(filename, appends, parse_file.cfg, caches_array)
|
||||
except Exception as exc:
|
||||
tb = sys.exc_info()[2]
|
||||
exc.recipe = filename
|
||||
exc.traceback = list(bb.exceptions.extract_traceback(tb, context=3))
|
||||
raise exc
|
||||
# Need to turn BaseExceptions into Exceptions here so we gracefully shutdown
|
||||
# and for example a worker thread doesn't just exit on its own in response to
|
||||
# a SystemExit event for example.
|
||||
except BaseException as exc:
|
||||
raise ParsingFailure(exc, filename)
|
||||
class Feeder(multiprocessing.Process):
|
||||
def __init__(self, jobs, to_parsers, quit):
|
||||
self.quit = quit
|
||||
self.jobs = jobs
|
||||
self.to_parsers = to_parsers
|
||||
multiprocessing.Process.__init__(self)
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
try:
|
||||
quit = self.quit.get_nowait()
|
||||
except Queue.Empty:
|
||||
pass
|
||||
else:
|
||||
if quit == 'cancel':
|
||||
self.to_parsers.cancel_join_thread()
|
||||
break
|
||||
|
||||
try:
|
||||
job = self.jobs.pop()
|
||||
except IndexError:
|
||||
break
|
||||
|
||||
try:
|
||||
self.to_parsers.put(job, timeout=0.5)
|
||||
except Queue.Full:
|
||||
self.jobs.insert(0, job)
|
||||
continue
|
||||
|
||||
class Parser(multiprocessing.Process):
|
||||
def __init__(self, jobs, results, quit, init):
|
||||
self.jobs = jobs
|
||||
self.results = results
|
||||
self.quit = quit
|
||||
self.init = init
|
||||
multiprocessing.Process.__init__(self)
|
||||
|
||||
def run(self):
|
||||
if self.init:
|
||||
self.init()
|
||||
|
||||
pending = []
|
||||
while True:
|
||||
try:
|
||||
self.quit.get_nowait()
|
||||
except Queue.Empty:
|
||||
pass
|
||||
else:
|
||||
self.results.cancel_join_thread()
|
||||
break
|
||||
|
||||
if pending:
|
||||
result = pending.pop()
|
||||
else:
|
||||
try:
|
||||
job = self.jobs.get(timeout=0.25)
|
||||
except Queue.Empty:
|
||||
continue
|
||||
|
||||
if job is None:
|
||||
break
|
||||
result = self.parse(*job)
|
||||
|
||||
try:
|
||||
self.results.put(result, timeout=0.25)
|
||||
except Queue.Full:
|
||||
pending.append(result)
|
||||
|
||||
def parse(self, filename, appends, caches_array):
|
||||
try:
|
||||
return True, bb.cache.Cache.parse(filename, appends, self.cfg, caches_array)
|
||||
except Exception as exc:
|
||||
tb = sys.exc_info()[2]
|
||||
exc.recipe = filename
|
||||
exc.traceback = list(bb.exceptions.extract_traceback(tb, context=3))
|
||||
return True, exc
|
||||
# Need to turn BaseExceptions into Exceptions here so we gracefully shutdown
|
||||
# and for example a worker thread doesn't just exit on its own in response to
|
||||
# a SystemExit event for example.
|
||||
except BaseException as exc:
|
||||
return True, ParsingFailure(exc, filename)
|
||||
|
||||
class CookerParser(object):
|
||||
def __init__(self, cooker, filelist, masked):
|
||||
self.filelist = filelist
|
||||
self.cooker = cooker
|
||||
self.cfgdata = cooker.configuration.data
|
||||
self.cfghash = cooker.configuration.data_hash
|
||||
|
||||
# Accounting statistics
|
||||
self.parsed = 0
|
||||
@@ -1446,7 +1573,7 @@ class CookerParser(object):
|
||||
self.num_processes = int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
|
||||
multiprocessing.cpu_count())
|
||||
|
||||
self.bb_cache = bb.cache.Cache(self.cfgdata, cooker.caches_array)
|
||||
self.bb_cache = bb.cache.Cache(self.cfgdata, self.cfghash, cooker.caches_array)
|
||||
self.fromcache = []
|
||||
self.willparse = []
|
||||
for filename in self.filelist:
|
||||
@@ -1461,22 +1588,28 @@ class CookerParser(object):
|
||||
self.start()
|
||||
|
||||
def start(self):
|
||||
def init(cfg):
|
||||
parse_file.cfg = cfg
|
||||
multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, args=(self.cooker.configuration.data, ), exitpriority=1)
|
||||
|
||||
self.results = self.load_cached()
|
||||
|
||||
self.processes = []
|
||||
if self.toparse:
|
||||
bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata)
|
||||
def init():
|
||||
Parser.cfg = self.cfgdata
|
||||
multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, args=(self.cfgdata,), exitpriority=1)
|
||||
|
||||
self.pool = multiprocessing.Pool(self.num_processes, init, [self.cfgdata])
|
||||
parsed = self.pool.imap(parse_file, self.willparse)
|
||||
self.pool.close()
|
||||
self.feeder_quit = multiprocessing.Queue(maxsize=1)
|
||||
self.parser_quit = multiprocessing.Queue(maxsize=self.num_processes)
|
||||
self.jobs = multiprocessing.Queue(maxsize=self.num_processes)
|
||||
self.result_queue = multiprocessing.Queue()
|
||||
self.feeder = Feeder(self.willparse, self.jobs, self.feeder_quit)
|
||||
self.feeder.start()
|
||||
for i in range(0, self.num_processes):
|
||||
parser = Parser(self.jobs, self.result_queue, self.parser_quit, init)
|
||||
parser.start()
|
||||
self.processes.append(parser)
|
||||
|
||||
self.results = itertools.chain(self.results, parsed)
|
||||
self.results = itertools.chain(self.results, self.parse_generator())
|
||||
|
||||
def shutdown(self, clean=True):
|
||||
def shutdown(self, clean=True, force=False):
|
||||
if not self.toparse:
|
||||
return
|
||||
|
||||
@@ -1486,9 +1619,22 @@ class CookerParser(object):
|
||||
self.virtuals, self.error,
|
||||
self.total)
|
||||
bb.event.fire(event, self.cfgdata)
|
||||
self.feeder_quit.put(None)
|
||||
for process in self.processes:
|
||||
self.jobs.put(None)
|
||||
else:
|
||||
self.pool.terminate()
|
||||
self.pool.join()
|
||||
self.feeder_quit.put('cancel')
|
||||
|
||||
self.parser_quit.cancel_join_thread()
|
||||
for process in self.processes:
|
||||
self.parser_quit.put(None)
|
||||
|
||||
self.jobs.cancel_join_thread()
|
||||
sys.exit(1)
|
||||
|
||||
for process in self.processes:
|
||||
process.join()
|
||||
self.feeder.join()
|
||||
|
||||
sync = threading.Thread(target=self.bb_cache.sync)
|
||||
sync.start()
|
||||
@@ -1500,6 +1646,22 @@ class CookerParser(object):
|
||||
cached, infos = self.bb_cache.load(filename, appends, self.cfgdata)
|
||||
yield not cached, infos
|
||||
|
||||
def parse_generator(self):
|
||||
while True:
|
||||
if self.parsed >= self.toparse:
|
||||
break
|
||||
|
||||
try:
|
||||
result = self.result_queue.get(timeout=0.25)
|
||||
except Queue.Empty:
|
||||
pass
|
||||
else:
|
||||
value = result[1]
|
||||
if isinstance(value, BaseException):
|
||||
raise value
|
||||
else:
|
||||
yield result
|
||||
|
||||
def parse_next(self):
|
||||
try:
|
||||
parsed, result = self.results.next()
|
||||
@@ -1507,27 +1669,27 @@ class CookerParser(object):
|
||||
self.shutdown()
|
||||
return False
|
||||
except ParsingFailure as exc:
|
||||
self.shutdown(clean=False)
|
||||
bb.fatal('Unable to parse %s: %s' %
|
||||
logger.error('Unable to parse %s: %s' %
|
||||
(exc.recipe, bb.exceptions.to_string(exc.realexception)))
|
||||
self.shutdown(clean=False)
|
||||
except (bb.parse.ParseError, bb.data_smart.ExpansionError) as exc:
|
||||
bb.fatal(str(exc))
|
||||
logger.error(str(exc))
|
||||
self.shutdown(clean=False)
|
||||
except SyntaxError as exc:
|
||||
logger.error('Unable to parse %s', exc.recipe)
|
||||
sys.exit(1)
|
||||
self.shutdown(clean=False)
|
||||
except Exception as exc:
|
||||
etype, value, tb = sys.exc_info()
|
||||
logger.error('Unable to parse %s', value.recipe,
|
||||
exc_info=(etype, value, exc.traceback))
|
||||
self.shutdown(clean=False)
|
||||
sys.exit(1)
|
||||
|
||||
self.current += 1
|
||||
self.virtuals += len(result)
|
||||
if parsed:
|
||||
self.parsed += 1
|
||||
if self.parsed % self.progress_chunk == 0:
|
||||
bb.event.fire(bb.event.ParseProgress(self.parsed),
|
||||
bb.event.fire(bb.event.ParseProgress(self.parsed, self.toparse),
|
||||
self.cfgdata)
|
||||
else:
|
||||
self.cached += 1
|
||||
|
||||
@@ -333,7 +333,7 @@ def generate_dependencies(d):
|
||||
deps[dep], values[dep] = build_dependencies(dep, keys, shelldeps, vardepvals, d)
|
||||
newdeps |= deps[dep]
|
||||
newdeps -= seen
|
||||
#print "For %s: %s" % (task, str(taskdeps[task]))
|
||||
#print "For %s: %s" % (task, str(deps[task]))
|
||||
return tasklist, deps, values
|
||||
|
||||
def inherits_class(klass, d):
|
||||
|
||||
@@ -31,6 +31,7 @@ BitBake build tools.
|
||||
import copy, re
|
||||
from collections import MutableMapping
|
||||
import logging
|
||||
import hashlib
|
||||
import bb, bb.codeparser
|
||||
from bb import utils
|
||||
from bb.COW import COWDictBase
|
||||
@@ -459,3 +460,15 @@ class DataSmart(MutableMapping):
|
||||
|
||||
def __delitem__(self, var):
|
||||
self.delVar(var)
|
||||
|
||||
def get_hash(self):
|
||||
data = ""
|
||||
config_whitelist = set((self.getVar("BB_HASHCONFIG_WHITELIST", True) or "").split())
|
||||
keys = set(key for key in iter(self) if not key.startswith("__"))
|
||||
for key in keys:
|
||||
if key in config_whitelist:
|
||||
continue
|
||||
value = self.getVar(key, False) or ""
|
||||
data = data + key + ': ' + str(value) + '\n'
|
||||
|
||||
return hashlib.md5(data).hexdigest()
|
||||
|
||||
@@ -204,6 +204,27 @@ def getName(e):
|
||||
else:
|
||||
return e.__name__
|
||||
|
||||
class OperationStarted(Event):
|
||||
"""An operation has begun"""
|
||||
def __init__(self, msg = "Operation Started"):
|
||||
Event.__init__(self)
|
||||
self.msg = msg
|
||||
|
||||
class OperationCompleted(Event):
|
||||
"""An operation has completed"""
|
||||
def __init__(self, total, msg = "Operation Completed"):
|
||||
Event.__init__(self)
|
||||
self.total = total
|
||||
self.msg = msg
|
||||
|
||||
class OperationProgress(Event):
|
||||
"""An operation is in progress"""
|
||||
def __init__(self, current, total, msg = "Operation in Progress"):
|
||||
Event.__init__(self)
|
||||
self.current = current
|
||||
self.total = total
|
||||
self.msg = msg + ": %s/%s" % (current, total);
|
||||
|
||||
class ConfigParsed(Event):
|
||||
"""Configuration Parsing Complete"""
|
||||
|
||||
@@ -276,14 +297,20 @@ class BuildBase(Event):
|
||||
|
||||
|
||||
|
||||
class BuildStarted(BuildBase):
|
||||
class BuildStarted(BuildBase, OperationStarted):
|
||||
"""bbmake build run started"""
|
||||
def __init__(self, n, p, failures = 0):
|
||||
OperationStarted.__init__(self, "Building Started")
|
||||
BuildBase.__init__(self, n, p, failures)
|
||||
|
||||
|
||||
class BuildCompleted(BuildBase):
|
||||
class BuildCompleted(BuildBase, OperationCompleted):
|
||||
"""bbmake build run completed"""
|
||||
|
||||
|
||||
def __init__(self, total, n, p, failures = 0):
|
||||
if not failures:
|
||||
OperationCompleted.__init__(self, total, "Building Succeeded")
|
||||
else:
|
||||
OperationCompleted.__init__(self, total, "Building Failed")
|
||||
BuildBase.__init__(self, n, p, failures)
|
||||
|
||||
|
||||
class NoProvider(Event):
|
||||
@@ -329,17 +356,16 @@ class MultipleProviders(Event):
|
||||
"""
|
||||
return self._candidates
|
||||
|
||||
class ParseStarted(Event):
|
||||
class ParseStarted(OperationStarted):
|
||||
"""Recipe parsing for the runqueue has begun"""
|
||||
def __init__(self, total):
|
||||
Event.__init__(self)
|
||||
OperationStarted.__init__(self, "Recipe parsing Started")
|
||||
self.total = total
|
||||
|
||||
class ParseCompleted(Event):
|
||||
class ParseCompleted(OperationCompleted):
|
||||
"""Recipe parsing for the runqueue has completed"""
|
||||
|
||||
def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total):
|
||||
Event.__init__(self)
|
||||
OperationCompleted.__init__(self, total, "Recipe parsing Completed")
|
||||
self.cached = cached
|
||||
self.parsed = parsed
|
||||
self.skipped = skipped
|
||||
@@ -347,33 +373,44 @@ class ParseCompleted(Event):
|
||||
self.masked = masked
|
||||
self.errors = errors
|
||||
self.sofar = cached + parsed
|
||||
self.total = total
|
||||
|
||||
class ParseProgress(Event):
|
||||
class ParseProgress(OperationProgress):
|
||||
"""Recipe parsing progress"""
|
||||
def __init__(self, current, total):
|
||||
OperationProgress.__init__(self, current, total, "Recipe parsing")
|
||||
|
||||
def __init__(self, current):
|
||||
self.current = current
|
||||
|
||||
class CacheLoadStarted(Event):
|
||||
class CacheLoadStarted(OperationStarted):
|
||||
"""Loading of the dependency cache has begun"""
|
||||
def __init__(self, total):
|
||||
Event.__init__(self)
|
||||
OperationStarted.__init__(self, "Loading cache Started")
|
||||
self.total = total
|
||||
|
||||
class CacheLoadProgress(Event):
|
||||
class CacheLoadProgress(OperationProgress):
|
||||
"""Cache loading progress"""
|
||||
def __init__(self, current):
|
||||
Event.__init__(self)
|
||||
self.current = current
|
||||
def __init__(self, current, total):
|
||||
OperationProgress.__init__(self, current, total, "Loading cache")
|
||||
|
||||
class CacheLoadCompleted(Event):
|
||||
class CacheLoadCompleted(OperationCompleted):
|
||||
"""Cache loading is complete"""
|
||||
def __init__(self, total, num_entries):
|
||||
Event.__init__(self)
|
||||
self.total = total
|
||||
OperationCompleted.__init__(self, total, "Loading cache Completed")
|
||||
self.num_entries = num_entries
|
||||
|
||||
class TreeDataPreparationStarted(OperationStarted):
|
||||
"""Tree data preparation started"""
|
||||
def __init__(self):
|
||||
OperationStarted.__init__(self, "Preparing tree data Started")
|
||||
|
||||
class TreeDataPreparationProgress(OperationProgress):
|
||||
"""Tree data preparation is in progress"""
|
||||
def __init__(self, current, total):
|
||||
OperationProgress.__init__(self, current, total, "Preparing tree data")
|
||||
|
||||
class TreeDataPreparationCompleted(OperationCompleted):
|
||||
"""Tree data preparation completed"""
|
||||
def __init__(self, total):
|
||||
OperationCompleted.__init__(self, total, "Preparing tree data Completed")
|
||||
|
||||
class DepTreeGenerated(Event):
|
||||
"""
|
||||
@@ -467,3 +504,16 @@ class LogHandler(logging.Handler):
|
||||
def filter(self, record):
|
||||
record.taskpid = worker_pid
|
||||
return True
|
||||
|
||||
class RequestPackageInfo(Event):
|
||||
"""
|
||||
Event to request package information
|
||||
"""
|
||||
|
||||
class PackageInfo(Event):
|
||||
"""
|
||||
Package information for GUI
|
||||
"""
|
||||
def __init__(self, pkginfolist):
|
||||
Event.__init__(self)
|
||||
self._pkginfolist = pkginfolist
|
||||
|
||||
@@ -55,7 +55,10 @@ class MalformedUrl(BBFetchException):
|
||||
class FetchError(BBFetchException):
|
||||
"""General fetcher exception when something happens incorrectly"""
|
||||
def __init__(self, message, url = None):
|
||||
msg = "Fetcher failure for URL: '%s'. %s" % (url, message)
|
||||
if url:
|
||||
msg = "Fetcher failure for URL: '%s'. %s" % (url, message)
|
||||
else:
|
||||
msg = "Fetcher failure: %s" % message
|
||||
self.url = url
|
||||
BBFetchException.__init__(self, msg)
|
||||
self.args = (message, url)
|
||||
@@ -302,10 +305,10 @@ def verify_checksum(u, ud, d):
|
||||
# it does not match.
|
||||
msg = ""
|
||||
if md5mismatch and ud.md5_expected:
|
||||
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected (from URL: '%s')" % (ud.localpath, 'md5', md5data, ud.md5_expected, u)
|
||||
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'md5', md5data, ud.md5_expected)
|
||||
|
||||
if sha256mismatch and ud.sha256_expected:
|
||||
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected (from URL: '%s')" % (ud.localpath, 'sha256', sha256data, ud.sha256_expected, u)
|
||||
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'sha256', sha256data, ud.sha256_expected)
|
||||
|
||||
if len(msg):
|
||||
raise FetchError('Checksum mismatch!%s' % msg, u)
|
||||
@@ -419,8 +422,11 @@ def runfetchcmd(cmd, d, quiet = False, cleanup = []):
|
||||
output += line
|
||||
|
||||
status = stdout_handle.close() or 0
|
||||
signal = status >> 8
|
||||
exitstatus = status & 0xff
|
||||
signal = os.WTERMSIG(status)
|
||||
if os.WIFEXITED(status):
|
||||
exitstatus = os.WEXITSTATUS(status)
|
||||
else:
|
||||
exitstatus = 0
|
||||
|
||||
if (signal or status != 0):
|
||||
for f in cleanup:
|
||||
@@ -431,8 +437,8 @@ def runfetchcmd(cmd, d, quiet = False, cleanup = []):
|
||||
|
||||
if signal:
|
||||
raise FetchError("Fetch command %s failed with signal %s, output:\n%s" % (cmd, signal, output))
|
||||
elif status != 0:
|
||||
raise FetchError("Fetch command %s failed with exit code %s, output:\n%s" % (cmd, status, output))
|
||||
elif exitstatus:
|
||||
raise FetchError("Fetch command %s failed with exit code %s, output:\n%s" % (cmd, exitstatus, output))
|
||||
|
||||
return output
|
||||
|
||||
@@ -473,7 +479,7 @@ def try_mirrors(d, origud, mirrors, check = False):
|
||||
return found
|
||||
continue
|
||||
|
||||
if ud.method.need_update(newuri, ud, ld):
|
||||
if not os.path.exists(ud.donestamp) or ud.method.need_update(newuri, ud, ld):
|
||||
ud.method.download(newuri, ud, ld)
|
||||
if hasattr(ud.method,"build_mirror_data"):
|
||||
ud.method.build_mirror_data(newuri, ud, ld)
|
||||
@@ -949,7 +955,7 @@ class Fetch(object):
|
||||
try:
|
||||
self.d.setVar("BB_NO_NETWORK", network)
|
||||
|
||||
if not m.need_update(u, ud, self.d):
|
||||
if os.path.exists(ud.donestamp) and not m.need_update(u, ud, self.d):
|
||||
localpath = ud.localpath
|
||||
elif m.try_premirror(u, ud, self.d):
|
||||
logger.debug(1, "Trying PREMIRRORS")
|
||||
@@ -959,7 +965,8 @@ class Fetch(object):
|
||||
if premirroronly:
|
||||
self.d.setVar("BB_NO_NETWORK", "1")
|
||||
|
||||
if not localpath and m.need_update(u, ud, self.d):
|
||||
firsterr = None
|
||||
if not localpath and ((not os.path.exists(ud.donestamp)) or m.need_update(u, ud, self.d)):
|
||||
try:
|
||||
logger.debug(1, "Trying Upstream")
|
||||
m.download(u, ud, self.d)
|
||||
@@ -974,7 +981,9 @@ class Fetch(object):
|
||||
raise
|
||||
|
||||
except BBFetchException as e:
|
||||
logger.warn(str(e))
|
||||
logger.warn('Failed to fetch URL %s' % u)
|
||||
logger.debug(1, str(e))
|
||||
firsterr = e
|
||||
# Remove any incomplete fetch
|
||||
if os.path.isfile(ud.localpath):
|
||||
bb.utils.remove(ud.localpath)
|
||||
@@ -983,7 +992,9 @@ class Fetch(object):
|
||||
localpath = try_mirrors (self.d, ud, mirrors)
|
||||
|
||||
if not localpath or ((not os.path.exists(localpath)) and localpath.find("*") == -1):
|
||||
raise FetchError("Unable to fetch URL %s from any source." % u, u)
|
||||
if firsterr:
|
||||
logger.error(str(firsterr))
|
||||
raise FetchError("Unable to fetch URL from any source.", u)
|
||||
|
||||
update_stamp(u, ud, self.d)
|
||||
|
||||
|
||||
@@ -38,6 +38,12 @@ Supported SRC_URI options are:
|
||||
who has its own routine to checkout code.
|
||||
The default is "0", set nocheckout=1 if needed.
|
||||
|
||||
- bareclone
|
||||
Create a bare clone of the source code and don't checkout the source code
|
||||
when unpacking. Set this option for the recipe who has its own routine to
|
||||
checkout code and tracking branch requirements.
|
||||
The default is "0", set bareclone=1 if needed.
|
||||
|
||||
"""
|
||||
|
||||
#Copyright (C) 2005 Richard Purdie
|
||||
@@ -95,6 +101,11 @@ class Git(FetchMethod):
|
||||
|
||||
ud.rebaseable = ud.parm.get("rebaseable","0") == "1"
|
||||
|
||||
# bareclone implies nocheckout
|
||||
ud.bareclone = ud.parm.get("bareclone","0") == "1"
|
||||
if ud.bareclone:
|
||||
ud.nocheckout = 1
|
||||
|
||||
branches = ud.parm.get("branch", "master").split(',')
|
||||
if len(branches) != len(ud.names):
|
||||
raise bb.fetch2.ParameterError("The number of name and branch parameters is not balanced", ud.url)
|
||||
@@ -220,7 +231,11 @@ class Git(FetchMethod):
|
||||
if os.path.exists(destdir):
|
||||
bb.utils.prunedir(destdir)
|
||||
|
||||
runfetchcmd("git clone -s -n %s %s" % (ud.clonedir, destdir), d)
|
||||
cloneflags = "-s -n"
|
||||
if ud.bareclone:
|
||||
cloneflags += " --mirror"
|
||||
|
||||
runfetchcmd("git clone %s %s/ %s" % (cloneflags, ud.clonedir, destdir), d)
|
||||
if not ud.nocheckout:
|
||||
os.chdir(destdir)
|
||||
if subdir != "":
|
||||
|
||||
237
bitbake/lib/bb/monitordisk.py
Normal file
@@ -0,0 +1,237 @@
|
||||
#!/usr/bin/env python
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright (C) 2012 Robert Yang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import os, logging, re, sys
|
||||
import bb
|
||||
logger = logging.getLogger("BitBake.Monitor")
|
||||
|
||||
def printErr(info):
|
||||
logger.error("%s\n Disk space monitor will NOT be enabled" % info)
|
||||
|
||||
def convertGMK(unit):
|
||||
|
||||
""" Convert the space unit G, M, K, the unit is case-insensitive """
|
||||
|
||||
unitG = re.match('([1-9][0-9]*)[gG]\s?$', unit)
|
||||
if unitG:
|
||||
return int(unitG.group(1)) * (1024 ** 3)
|
||||
unitM = re.match('([1-9][0-9]*)[mM]\s?$', unit)
|
||||
if unitM:
|
||||
return int(unitM.group(1)) * (1024 ** 2)
|
||||
unitK = re.match('([1-9][0-9]*)[kK]\s?$', unit)
|
||||
if unitK:
|
||||
return int(unitK.group(1)) * 1024
|
||||
unitN = re.match('([1-9][0-9]*)\s?$', unit)
|
||||
if unitN:
|
||||
return int(unitN.group(1))
|
||||
else:
|
||||
return None
|
||||
|
||||
def getMountedDev(path):
|
||||
|
||||
""" Get the device mounted at the path, uses /proc/mounts """
|
||||
|
||||
# Get the mount point of the filesystem containing path
|
||||
# st_dev is the ID of device containing file
|
||||
parentDev = os.stat(path).st_dev
|
||||
currentDev = parentDev
|
||||
# When the current directory's device is different from the
|
||||
# parrent's, then the current directory is a mount point
|
||||
while parentDev == currentDev:
|
||||
mountPoint = path
|
||||
# Use dirname to get the parrent's directory
|
||||
path = os.path.dirname(path)
|
||||
# Reach the "/"
|
||||
if path == mountPoint:
|
||||
break
|
||||
parentDev= os.stat(path).st_dev
|
||||
|
||||
try:
|
||||
with open("/proc/mounts", "r") as ifp:
|
||||
for line in ifp:
|
||||
procLines = line.rstrip('\n').split()
|
||||
if procLines[1] == mountPoint:
|
||||
return procLines[0]
|
||||
except EnvironmentError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def getDiskData(BBDirs, configuration):
|
||||
|
||||
"""Prepare disk data for disk space monitor"""
|
||||
|
||||
# Save the device IDs, need the ID to be unique (the dictionary's key is
|
||||
# unique), so that when more than one directories are located in the same
|
||||
# device, we just monitor it once
|
||||
devDict = {}
|
||||
for pathSpaceInode in BBDirs.split():
|
||||
# The input format is: "dir,space,inode", dir is a must, space
|
||||
# and inode are optional
|
||||
pathSpaceInodeRe = re.match('([^,]*),([^,]*),([^,]*),?(.*)', pathSpaceInode)
|
||||
if not pathSpaceInodeRe:
|
||||
printErr("Invalid value in BB_DISKMON_DIRS: %s" % pathSpaceInode)
|
||||
return None
|
||||
|
||||
action = pathSpaceInodeRe.group(1)
|
||||
if action not in ("ABORT", "STOPTASKS", "WARN"):
|
||||
printErr("Unknown disk space monitor action: %s" % action)
|
||||
return None
|
||||
|
||||
path = os.path.realpath(pathSpaceInodeRe.group(2))
|
||||
if not path:
|
||||
printErr("Invalid path value in BB_DISKMON_DIRS: %s" % pathSpaceInode)
|
||||
return None
|
||||
|
||||
# The disk space or inode is optional, but it should have a correct
|
||||
# value once it is specified
|
||||
minSpace = pathSpaceInodeRe.group(3)
|
||||
if minSpace:
|
||||
minSpace = convertGMK(minSpace)
|
||||
if not minSpace:
|
||||
printErr("Invalid disk space value in BB_DISKMON_DIRS: %s" % pathSpaceInodeRe.group(3))
|
||||
return None
|
||||
else:
|
||||
# 0 means that it is not specified
|
||||
minSpace = None
|
||||
|
||||
minInode = pathSpaceInodeRe.group(4)
|
||||
if minInode:
|
||||
minInode = convertGMK(minInode)
|
||||
if not minInode:
|
||||
printErr("Invalid inode value in BB_DISKMON_DIRS: %s" % pathSpaceInodeRe.group(4))
|
||||
return None
|
||||
else:
|
||||
# 0 means that it is not specified
|
||||
minInode = None
|
||||
|
||||
if minSpace is None and minInode is None:
|
||||
printErr("No disk space or inode value in found BB_DISKMON_DIRS: %s" % pathSpaceInode)
|
||||
return None
|
||||
# mkdir for the directory since it may not exist, for example the
|
||||
# DL_DIR may not exist at the very beginning
|
||||
if not os.path.exists(path):
|
||||
bb.utils.mkdirhier(path)
|
||||
mountedDev = getMountedDev(path)
|
||||
devDict[mountedDev] = action, path, minSpace, minInode
|
||||
|
||||
return devDict
|
||||
|
||||
def getInterval(configuration):
|
||||
|
||||
""" Get the disk space interval """
|
||||
|
||||
interval = configuration.getVar("BB_DISKMON_WARNINTERVAL", 1)
|
||||
if not interval:
|
||||
# The default value is 50M and 5K.
|
||||
return 50 * 1024 * 1024, 5 * 1024
|
||||
else:
|
||||
# The disk space or inode interval is optional, but it should
|
||||
# have a correct value once it is specified
|
||||
intervalRe = re.match('([^,]*),?\s*(.*)', interval)
|
||||
if intervalRe:
|
||||
intervalSpace = intervalRe.group(1)
|
||||
if intervalSpace:
|
||||
intervalSpace = convertGMK(intervalSpace)
|
||||
if not intervalSpace:
|
||||
printErr("Invalid disk space interval value in BB_DISKMON_WARNINTERVAL: %s" % intervalRe.group(1))
|
||||
return None, None
|
||||
intervalInode = intervalRe.group(2)
|
||||
if intervalInode:
|
||||
intervalInode = convertGMK(intervalInode)
|
||||
if not intervalInode:
|
||||
printErr("Invalid disk inode interval value in BB_DISKMON_WARNINTERVAL: %s" % intervalRe.group(2))
|
||||
return None, None
|
||||
return intervalSpace, intervalInode
|
||||
else:
|
||||
printErr("Invalid interval value in BB_DISKMON_WARNINTERVAL: %s" % interval)
|
||||
return None, None
|
||||
|
||||
class diskMonitor:
|
||||
|
||||
"""Prepare the disk space monitor data"""
|
||||
|
||||
def __init__(self, configuration):
|
||||
|
||||
self.enableMonitor = False
|
||||
|
||||
BBDirs = configuration.getVar("BB_DISKMON_DIRS", 1) or None
|
||||
if BBDirs:
|
||||
self.devDict = getDiskData(BBDirs, configuration)
|
||||
if self.devDict:
|
||||
self.spaceInterval, self.inodeInterval = getInterval(configuration)
|
||||
if self.spaceInterval and self.inodeInterval:
|
||||
self.enableMonitor = True
|
||||
# These are for saving the previous disk free space and inode, we
|
||||
# use them to avoid print too many warning messages
|
||||
self.preFreeS = {}
|
||||
self.preFreeI = {}
|
||||
# This is for STOPTASKS and ABORT, to avoid print the message repeatly
|
||||
# during waiting the tasks to finish
|
||||
self.checked = {}
|
||||
for dev in self.devDict:
|
||||
self.preFreeS[dev] = 0
|
||||
self.preFreeI[dev] = 0
|
||||
self.checked[dev] = False
|
||||
if self.spaceInterval is None and self.inodeInterval is None:
|
||||
self.enableMonitor = False
|
||||
|
||||
def check(self, rq):
|
||||
|
||||
""" Take action for the monitor """
|
||||
|
||||
if self.enableMonitor:
|
||||
for dev in self.devDict:
|
||||
st = os.statvfs(self.devDict[dev][1])
|
||||
|
||||
# The free space, float point number
|
||||
freeSpace = st.f_bavail * st.f_frsize
|
||||
|
||||
if self.devDict[dev][2] and freeSpace < self.devDict[dev][2]:
|
||||
# Always show warning, the self.checked would always be False if the action is WARN
|
||||
if self.preFreeS[dev] == 0 or self.preFreeS[dev] - freeSpace > self.spaceInterval and not self.checked[dev]:
|
||||
logger.warn("The free space of %s is running low (%.3fGB left)" % (dev, freeSpace / 1024 / 1024 / 1024.0))
|
||||
self.preFreeS[dev] = freeSpace
|
||||
|
||||
if self.devDict[dev][0] == "STOPTASKS" and not self.checked[dev]:
|
||||
logger.error("No new tasks can be excuted since the disk space monitor action is \"STOPTASKS\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(False)
|
||||
elif self.devDict[dev][0] == "ABORT" and not self.checked[dev]:
|
||||
logger.error("Immediately abort since the disk space monitor action is \"ABORT\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(True)
|
||||
|
||||
# The free inodes, float point number
|
||||
freeInode = st.f_favail
|
||||
|
||||
if self.devDict[dev][3] and freeInode < self.devDict[dev][3]:
|
||||
# Always show warning, the self.checked would always be False if the action is WARN
|
||||
if self.preFreeI[dev] == 0 or self.preFreeI[dev] - freeInode > self.inodeInterval and not self.checked[dev]:
|
||||
logger.warn("The free inode of %s is running low (%.3fK left)" % (dev, freeInode / 1024.0))
|
||||
self.preFreeI[dev] = freeInode
|
||||
|
||||
if self.devDict[dev][0] == "STOPTASKS" and not self.checked[dev]:
|
||||
logger.error("No new tasks can be excuted since the disk space monitor action is \"STOPTASKS\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(False)
|
||||
elif self.devDict[dev][0] == "ABORT" and not self.checked[dev]:
|
||||
logger.error("Immediately abort since the disk space monitor action is \"ABORT\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(True)
|
||||
return
|
||||
@@ -100,6 +100,7 @@ class BBLogFilter(object):
|
||||
|
||||
loggerDefaultDebugLevel = 0
|
||||
loggerDefaultVerbose = False
|
||||
loggerVerboseLogs = False
|
||||
loggerDefaultDomains = []
|
||||
|
||||
def init_msgconfig(verbose, debug, debug_domains = []):
|
||||
@@ -108,6 +109,8 @@ def init_msgconfig(verbose, debug, debug_domains = []):
|
||||
"""
|
||||
bb.msg.loggerDefaultDebugLevel = debug
|
||||
bb.msg.loggerDefaultVerbose = verbose
|
||||
if verbose:
|
||||
bb.msg.loggerVerboseLogs = True
|
||||
bb.msg.loggerDefaultDomains = debug_domains
|
||||
|
||||
def addDefaultlogFilter(handler):
|
||||
|
||||
@@ -37,6 +37,17 @@ logger = logging.getLogger("BitBake.Parsing")
|
||||
|
||||
class ParseError(Exception):
|
||||
"""Exception raised when parsing fails"""
|
||||
def __init__(self, msg, filename, lineno=0):
|
||||
self.msg = msg
|
||||
self.filename = filename
|
||||
self.lineno = lineno
|
||||
Exception.__init__(self, msg, filename, lineno)
|
||||
|
||||
def __str__(self):
|
||||
if self.lineno:
|
||||
return "ParseError at %s:%d: %s" % (self.filename, self.lineno, self.msg)
|
||||
else:
|
||||
return "ParseError in %s: %s" % (self.filename, self.msg)
|
||||
|
||||
class SkipPackage(Exception):
|
||||
"""Exception raised to skip this package"""
|
||||
@@ -78,7 +89,7 @@ def handle(fn, data, include = 0):
|
||||
for h in handlers:
|
||||
if h['supports'](fn, data):
|
||||
return h['handle'](fn, data, include)
|
||||
raise ParseError("%s is not a BitBake file" % fn)
|
||||
raise ParseError("not a BitBake file", fn)
|
||||
|
||||
def init(fn, data):
|
||||
for h in handlers:
|
||||
@@ -111,7 +122,7 @@ def vars_from_file(mypkg, d):
|
||||
parts = myfile[0].split('_')
|
||||
__pkgsplit_cache__[mypkg] = parts
|
||||
if len(parts) > 3:
|
||||
raise ParseError("Unable to generate default variables from the filename: %s (too many underscores)" % mypkg)
|
||||
raise ParseError("Unable to generate default variables from filename (too many underscores)", mypkg)
|
||||
exp = 3 - len(parts)
|
||||
tmplist = []
|
||||
while exp != 0:
|
||||
@@ -120,4 +131,13 @@ def vars_from_file(mypkg, d):
|
||||
parts.extend(tmplist)
|
||||
return parts
|
||||
|
||||
def get_file_depends(d):
|
||||
'''Return the dependent files'''
|
||||
dep_files = []
|
||||
depends = d.getVar('__depends', True) or set()
|
||||
depends = depends.union(d.getVar('__base_depends', True) or set())
|
||||
for (fn, _) in depends:
|
||||
dep_files.append(os.path.abspath(fn))
|
||||
return " ".join(dep_files)
|
||||
|
||||
from bb.parse.parse_py import __version__, ConfHandler, BBHandler
|
||||
|
||||
@@ -59,9 +59,9 @@ class IncludeNode(AstNode):
|
||||
|
||||
# TODO: Cache those includes... maybe not here though
|
||||
if self.force:
|
||||
bb.parse.ConfHandler.include(self.filename, s, data, "include required")
|
||||
bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, "include required")
|
||||
else:
|
||||
bb.parse.ConfHandler.include(self.filename, s, data, False)
|
||||
bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, False)
|
||||
|
||||
class ExportNode(AstNode):
|
||||
def __init__(self, filename, lineno, var):
|
||||
@@ -267,7 +267,7 @@ class InheritNode(AstNode):
|
||||
self.classes = classes
|
||||
|
||||
def eval(self, data):
|
||||
bb.parse.BBHandler.inherit(self.classes, data)
|
||||
bb.parse.BBHandler.inherit(self.classes, self.filename, self.lineno, data)
|
||||
|
||||
def handleInclude(statements, filename, lineno, m, force):
|
||||
statements.append(IncludeNode(filename, lineno, m.group(1), force))
|
||||
@@ -328,6 +328,8 @@ def finalize(fn, d, variant = None):
|
||||
|
||||
bb.parse.siggen.finalise(fn, d, variant)
|
||||
|
||||
d.setVar('BBINCLUDED', bb.parse.get_file_depends(d))
|
||||
|
||||
bb.event.fire(bb.event.RecipeParsed(fn), d)
|
||||
|
||||
def _create_variants(datastores, names, function):
|
||||
@@ -450,7 +452,7 @@ def multi_finalize(fn, d):
|
||||
d.setVar("BBEXTENDVARIANT", variantmap[name])
|
||||
else:
|
||||
d.setVar("PN", "%s-%s" % (pn, name))
|
||||
bb.parse.BBHandler.inherit([extendedmap[name]], d)
|
||||
bb.parse.BBHandler.inherit([extendedmap[name]], fn, 0, d)
|
||||
|
||||
safe_d.setVar("BBCLASSEXTEND", extended)
|
||||
_create_variants(datastores, extendedmap.keys(), extendfunc)
|
||||
|
||||
@@ -68,10 +68,8 @@ def supports(fn, d):
|
||||
"""Return True if fn has a supported extension"""
|
||||
return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"]
|
||||
|
||||
def inherit(files, d):
|
||||
def inherit(files, fn, lineno, d):
|
||||
__inherit_cache = data.getVar('__inherit_cache', d) or []
|
||||
fn = ""
|
||||
lineno = 0
|
||||
for file in files:
|
||||
file = data.expand(file, d)
|
||||
if not os.path.isabs(file) and not file.endswith(".bbclass"):
|
||||
@@ -81,7 +79,7 @@ def inherit(files, d):
|
||||
logger.log(logging.DEBUG -1, "BB %s:%d: inheriting %s", fn, lineno, file)
|
||||
__inherit_cache.append( file )
|
||||
data.setVar('__inherit_cache', __inherit_cache, d)
|
||||
include(fn, file, d, "inherit")
|
||||
include(fn, file, lineno, d, "inherit")
|
||||
__inherit_cache = data.getVar('__inherit_cache', d) or []
|
||||
|
||||
def get_statements(filename, absolute_filename, base_name):
|
||||
|
||||
@@ -29,11 +29,10 @@ import logging
|
||||
import bb.utils
|
||||
from bb.parse import ParseError, resolve_file, ast, logger
|
||||
|
||||
#__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}]+)\s*(?P<colon>:)?(?P<ques>\?)?=\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
|
||||
__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<lazyques>\?\?=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
|
||||
__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<lazyques>\?\?=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"])(?P<value>.*)(?P=apo)$")
|
||||
__include_regexp__ = re.compile( r"include\s+(.+)" )
|
||||
__require_regexp__ = re.compile( r"require\s+(.+)" )
|
||||
__export_regexp__ = re.compile( r"export\s+(.+)" )
|
||||
__export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/]+)$" )
|
||||
|
||||
def init(data):
|
||||
topdir = data.getVar('TOPDIR')
|
||||
@@ -44,10 +43,11 @@ def init(data):
|
||||
def supports(fn, d):
|
||||
return fn[-5:] == ".conf"
|
||||
|
||||
def include(oldfn, fn, data, error_out):
|
||||
def include(oldfn, fn, lineno, data, error_out):
|
||||
"""
|
||||
error_out If True a ParseError will be raised if the to be included
|
||||
config-files could not be included.
|
||||
error_out: A string indicating the verb (e.g. "include", "inherit") to be
|
||||
used in a ParseError that will be raised if the file to be included could
|
||||
not be included. Specify False to avoid raising an error in this case.
|
||||
"""
|
||||
if oldfn == fn: # prevent infinite recursion
|
||||
return None
|
||||
@@ -68,7 +68,7 @@ def include(oldfn, fn, data, error_out):
|
||||
ret = handle(fn, data, True)
|
||||
except IOError:
|
||||
if error_out:
|
||||
raise ParseError("Could not %(error_out)s file %(fn)s" % vars() )
|
||||
raise ParseError("Could not %(error_out)s file %(fn)s" % vars(), oldfn, lineno)
|
||||
logger.debug(2, "CONF file '%s' not found", fn)
|
||||
|
||||
def handle(fn, data, include):
|
||||
@@ -131,7 +131,7 @@ def feeder(lineno, s, fn, statements):
|
||||
ast.handleExport(statements, fn, lineno, m)
|
||||
return
|
||||
|
||||
raise ParseError("%s:%d: unparsed line: '%s'" % (fn, lineno, s));
|
||||
raise ParseError("unparsed line: '%s'" % s, fn, lineno);
|
||||
|
||||
# Add us to the handlers list
|
||||
from bb.parse import handlers
|
||||
|
||||
@@ -41,15 +41,19 @@ if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3):
|
||||
|
||||
logger = logging.getLogger("BitBake.PersistData")
|
||||
if hasattr(sqlite3, 'enable_shared_cache'):
|
||||
sqlite3.enable_shared_cache(True)
|
||||
try:
|
||||
sqlite3.enable_shared_cache(True)
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
|
||||
|
||||
@total_ordering
|
||||
class SQLTable(collections.MutableMapping):
|
||||
"""Object representing a table/domain in the database"""
|
||||
def __init__(self, cursor, table):
|
||||
self.cursor = cursor
|
||||
def __init__(self, cachefile, table):
|
||||
self.cachefile = cachefile
|
||||
self.table = table
|
||||
self.cursor = connect(self.cachefile)
|
||||
|
||||
self._execute("CREATE TABLE IF NOT EXISTS %s(key TEXT, value TEXT);"
|
||||
% table)
|
||||
@@ -63,6 +67,8 @@ class SQLTable(collections.MutableMapping):
|
||||
except sqlite3.OperationalError as exc:
|
||||
if 'database is locked' in str(exc) and count < 500:
|
||||
count = count + 1
|
||||
self.cursor.close()
|
||||
self.cursor = connect(self.cachefile)
|
||||
continue
|
||||
raise
|
||||
|
||||
@@ -188,7 +194,7 @@ class PersistData(object):
|
||||
del self.data[domain][key]
|
||||
|
||||
def connect(database):
|
||||
return sqlite3.connect(database, timeout=30, isolation_level=None)
|
||||
return sqlite3.connect(database, timeout=5, isolation_level=None)
|
||||
|
||||
def persist(domain, d):
|
||||
"""Convenience factory for SQLTable objects based upon metadata"""
|
||||
@@ -201,5 +207,4 @@ def persist(domain, d):
|
||||
|
||||
bb.utils.mkdirhier(cachedir)
|
||||
cachefile = os.path.join(cachedir, "bb_persist_data.sqlite3")
|
||||
connection = connect(cachefile)
|
||||
return SQLTable(connection, domain)
|
||||
return SQLTable(cachefile, domain)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
import re
|
||||
import logging
|
||||
from bb import data, utils
|
||||
from collections import defaultdict
|
||||
import bb
|
||||
|
||||
logger = logging.getLogger("BitBake.Provider")
|
||||
@@ -35,6 +36,41 @@ class NoRProvider(bb.BBHandledException):
|
||||
"""Exception raised when no provider of a runtime dependency can be found"""
|
||||
|
||||
|
||||
def findProviders(cfgData, dataCache, pkg_pn = None):
|
||||
"""
|
||||
Convenience function to get latest and preferred providers in pkg_pn
|
||||
"""
|
||||
|
||||
if not pkg_pn:
|
||||
pkg_pn = dataCache.pkg_pn
|
||||
|
||||
# Need to ensure data store is expanded
|
||||
localdata = data.createCopy(cfgData)
|
||||
bb.data.update_data(localdata)
|
||||
bb.data.expandKeys(localdata)
|
||||
|
||||
preferred_versions = {}
|
||||
latest_versions = {}
|
||||
|
||||
for pn in pkg_pn:
|
||||
(last_ver, last_file, pref_ver, pref_file) = findBestProvider(pn, localdata, dataCache, pkg_pn)
|
||||
preferred_versions[pn] = (pref_ver, pref_file)
|
||||
latest_versions[pn] = (last_ver, last_file)
|
||||
|
||||
return (latest_versions, preferred_versions)
|
||||
|
||||
|
||||
def allProviders(dataCache):
|
||||
"""
|
||||
Find all providers for each pn
|
||||
"""
|
||||
all_providers = defaultdict(list)
|
||||
for (fn, pn) in dataCache.pkg_fn.items():
|
||||
ver = dataCache.pkg_pepvpr[fn]
|
||||
all_providers[pn].append((ver, fn))
|
||||
return all_providers
|
||||
|
||||
|
||||
def sortPriorities(pn, dataCache, pkg_pn = None):
|
||||
"""
|
||||
Reorder pkg_pn by file priority and default preference
|
||||
|
||||
@@ -31,6 +31,7 @@ import fcntl
|
||||
import logging
|
||||
import bb
|
||||
from bb import msg, data, event
|
||||
from bb import monitordisk
|
||||
|
||||
bblogger = logging.getLogger("BitBake")
|
||||
logger = logging.getLogger("BitBake.RunQueue")
|
||||
@@ -187,6 +188,7 @@ class RunQueueData:
|
||||
self.taskData = taskData
|
||||
self.targets = targets
|
||||
self.rq = rq
|
||||
self.warn_multi_bb = False
|
||||
|
||||
self.stampwhitelist = cfgData.getVar("BB_STAMP_WHITELIST", 1) or ""
|
||||
self.multi_provider_whitelist = (cfgData.getVar("MULTI_PROVIDER_WHITELIST", 1) or "").split()
|
||||
@@ -674,11 +676,14 @@ class RunQueueData:
|
||||
prov_list[prov] = [fn]
|
||||
elif fn not in prov_list[prov]:
|
||||
prov_list[prov].append(fn)
|
||||
error = False
|
||||
for prov in prov_list:
|
||||
if len(prov_list[prov]) > 1 and prov not in self.multi_provider_whitelist:
|
||||
error = True
|
||||
logger.error("Multiple .bb files are due to be built which each provide %s (%s).\n This usually means one provides something the other doesn't and should.", prov, " ".join(prov_list[prov]))
|
||||
msg = "Multiple .bb files are due to be built which each provide %s (%s)." % (prov, " ".join(prov_list[prov]))
|
||||
if self.warn_multi_bb:
|
||||
logger.warn(msg)
|
||||
else:
|
||||
msg += "\n This usually means one provides something the other doesn't and should."
|
||||
logger.error(msg)
|
||||
|
||||
|
||||
# Create a whitelist usable by the stamp checks
|
||||
@@ -771,6 +776,9 @@ class RunQueue:
|
||||
|
||||
self.state = runQueuePrepare
|
||||
|
||||
# For disk space monitor
|
||||
self.dm = monitordisk.diskMonitor(cfgData)
|
||||
|
||||
def check_stamps(self):
|
||||
unchecked = {}
|
||||
current = []
|
||||
@@ -945,6 +953,9 @@ class RunQueue:
|
||||
else:
|
||||
self.rqexe = RunQueueExecuteScenequeue(self)
|
||||
|
||||
if self.state in [runQueueSceneRun, runQueueRunning, runQueueCleanUp]:
|
||||
self.dm.check(self)
|
||||
|
||||
if self.state is runQueueSceneRun:
|
||||
retval = self.rqexe.execute()
|
||||
|
||||
@@ -959,6 +970,13 @@ class RunQueue:
|
||||
if self.state is runQueueCleanUp:
|
||||
self.rqexe.finish()
|
||||
|
||||
if self.state is runQueueComplete or self.state is runQueueFailed:
|
||||
if self.rqexe.stats.failed:
|
||||
logger.info("Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed.", self.rqexe.stats.completed + self.rqexe.stats.failed, self.rqexe.stats.skipped, self.rqexe.stats.failed)
|
||||
else:
|
||||
# Let's avoid the word "failed" if nothing actually did
|
||||
logger.info("Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and all succeeded.", self.rqexe.stats.completed, self.rqexe.stats.skipped)
|
||||
|
||||
if self.state is runQueueFailed:
|
||||
if not self.rqdata.taskData.tryaltconfigs:
|
||||
raise bb.runqueue.TaskFailure(self.rqexe.failed_fnids)
|
||||
@@ -968,7 +986,6 @@ class RunQueue:
|
||||
|
||||
if self.state is runQueueComplete:
|
||||
# All done
|
||||
logger.info("Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed.", self.rqexe.stats.completed, self.rqexe.stats.skipped, self.rqexe.stats.failed)
|
||||
return False
|
||||
|
||||
if self.state is runQueueChildProcess:
|
||||
@@ -1050,6 +1067,13 @@ class RunQueueExecute:
|
||||
for pipe in self.build_pipes:
|
||||
self.build_pipes[pipe].read()
|
||||
|
||||
if len(self.failed_fnids) != 0:
|
||||
self.rq.state = runQueueFailed
|
||||
return
|
||||
|
||||
self.rq.state = runQueueComplete
|
||||
return
|
||||
|
||||
def finish(self):
|
||||
self.rq.state = runQueueCleanUp
|
||||
|
||||
@@ -1429,18 +1453,20 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
sq_revdeps.append(copy.copy(self.rqdata.runq_revdeps[task]))
|
||||
sq_revdeps_new.append(set())
|
||||
if (len(self.rqdata.runq_revdeps[task]) == 0) and task not in self.rqdata.runq_setscene:
|
||||
endpoints[task] = None
|
||||
endpoints[task] = set()
|
||||
|
||||
for task in self.rqdata.runq_setscene:
|
||||
for dep in self.rqdata.runq_depends[task]:
|
||||
endpoints[dep] = task
|
||||
if dep not in endpoints:
|
||||
endpoints[dep] = set()
|
||||
endpoints[dep].add(task)
|
||||
|
||||
def process_endpoints(endpoints):
|
||||
newendpoints = {}
|
||||
for point, task in endpoints.items():
|
||||
tasks = set()
|
||||
if task:
|
||||
tasks.add(task)
|
||||
tasks |= task
|
||||
if sq_revdeps_new[point]:
|
||||
tasks |= sq_revdeps_new[point]
|
||||
sq_revdeps_new[point] = set()
|
||||
@@ -1465,8 +1491,30 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
elif len(sq_revdeps_new[task]) != 0:
|
||||
bb.msg.fatal("RunQueue", "Something went badly wrong during scenequeue generation, aborting. Please report this problem.")
|
||||
|
||||
# Resolve setscene inter-task dependencies
|
||||
# e.g. do_sometask_setscene[depends] = "targetname:do_someothertask_setscene"
|
||||
# Note that anything explicitly depended upon will have its reverse dependencies removed to avoid circular dependencies
|
||||
for task in self.rqdata.runq_setscene:
|
||||
realid = self.rqdata.taskData.gettask_id(self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]], self.rqdata.runq_task[task] + "_setscene", False)
|
||||
idepends = self.rqdata.taskData.tasks_idepends[realid]
|
||||
for (depid, idependtask) in idepends:
|
||||
if depid not in self.rqdata.taskData.build_targets:
|
||||
continue
|
||||
|
||||
depdata = self.rqdata.taskData.build_targets[depid][0]
|
||||
if depdata is None:
|
||||
continue
|
||||
dep = self.rqdata.taskData.fn_index[depdata]
|
||||
taskid = self.rqdata.get_task_id(self.rqdata.taskData.getfn_id(dep), idependtask.replace("_setscene", ""))
|
||||
if taskid is None:
|
||||
bb.msg.fatal("RunQueue", "Task %s depends upon nonexistant task %s:%s" % (self.rqdata.taskData.tasks_name[realid], dep, idependtask))
|
||||
|
||||
sq_revdeps_squash[self.rqdata.runq_setscene.index(task)].add(self.rqdata.runq_setscene.index(taskid))
|
||||
# Have to zero this to avoid circular dependencies
|
||||
sq_revdeps_squash[self.rqdata.runq_setscene.index(taskid)] = set()
|
||||
|
||||
#for task in xrange(len(sq_revdeps_squash)):
|
||||
# print "Task %s: %s.%s is %s " % (task, self.taskData.fn_index[self.runq_fnid[self.runq_setscene[task]]], self.runq_task[self.runq_setscene[task]] + "_setscene", sq_revdeps_squash[task])
|
||||
# print "Task %s: %s.%s is %s " % (task, self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[self.rqdata.runq_setscene[task]]], self.rqdata.runq_task[self.rqdata.runq_setscene[task]] + "_setscene", sq_revdeps_squash[task])
|
||||
|
||||
self.sq_deps = []
|
||||
self.sq_revdeps = sq_revdeps_squash
|
||||
@@ -1614,8 +1662,8 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
self.task_skip(task)
|
||||
return True
|
||||
|
||||
logger.info("Running setscene task %d of %d (%s:%s)" % (self.stats.completed + self.stats.active + self.stats.failed + 1,
|
||||
self.stats.total, fn, taskname))
|
||||
startevent = sceneQueueTaskStarted(task, self.stats, self.rq)
|
||||
bb.event.fire(startevent, self.cfgData)
|
||||
|
||||
pid, pipein, pipeout = self.fork_off_task(fn, realtask, taskname)
|
||||
|
||||
@@ -1676,6 +1724,15 @@ class runQueueEvent(bb.event.Event):
|
||||
self.stats = stats.copy()
|
||||
bb.event.Event.__init__(self)
|
||||
|
||||
class sceneQueueEvent(runQueueEvent):
|
||||
"""
|
||||
Base sceneQueue event class
|
||||
"""
|
||||
def __init__(self, task, stats, rq, noexec=False):
|
||||
runQueueEvent.__init__(self, task, stats, rq)
|
||||
realtask = rq.rqdata.runq_setscene[task]
|
||||
self.taskstring = rq.rqdata.get_user_idstring(realtask, "_setscene")
|
||||
|
||||
class runQueueTaskStarted(runQueueEvent):
|
||||
"""
|
||||
Event notifing a task was started
|
||||
@@ -1684,6 +1741,14 @@ class runQueueTaskStarted(runQueueEvent):
|
||||
runQueueEvent.__init__(self, task, stats, rq)
|
||||
self.noexec = noexec
|
||||
|
||||
class sceneQueueTaskStarted(sceneQueueEvent):
|
||||
"""
|
||||
Event notifing a setscene task was started
|
||||
"""
|
||||
def __init__(self, task, stats, rq, noexec=False):
|
||||
sceneQueueEvent.__init__(self, task, stats, rq)
|
||||
self.noexec = noexec
|
||||
|
||||
class runQueueTaskFailed(runQueueEvent):
|
||||
"""
|
||||
Event notifing a task failed
|
||||
@@ -1692,13 +1757,13 @@ class runQueueTaskFailed(runQueueEvent):
|
||||
runQueueEvent.__init__(self, task, stats, rq)
|
||||
self.exitcode = exitcode
|
||||
|
||||
class sceneQueueTaskFailed(runQueueTaskFailed):
|
||||
class sceneQueueTaskFailed(sceneQueueEvent):
|
||||
"""
|
||||
Event notifing a setscene task failed
|
||||
"""
|
||||
def __init__(self, task, stats, exitcode, rq):
|
||||
runQueueTaskFailed.__init__(self, task, stats, exitcode, rq)
|
||||
self.taskstring = rq.rqdata.get_user_idstring(task, "_setscene")
|
||||
sceneQueueEvent.__init__(self, task, stats, rq)
|
||||
self.exitcode = exitcode
|
||||
|
||||
class runQueueTaskCompleted(runQueueEvent):
|
||||
"""
|
||||
|
||||
@@ -163,7 +163,7 @@ class BitBakeXMLRPCServer(SimpleXMLRPCServer):
|
||||
# remove this when you're done with debugging
|
||||
# allow_reuse_address = True
|
||||
|
||||
def __init__(self, interface = ("localhost", 0)):
|
||||
def __init__(self, interface):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
@@ -247,9 +247,9 @@ class BitbakeServerInfo():
|
||||
self.port = port
|
||||
|
||||
class BitBakeServerConnection():
|
||||
def __init__(self, serverinfo):
|
||||
def __init__(self, serverinfo, clientinfo=("localhost", 0)):
|
||||
self.connection = _create_server(serverinfo.host, serverinfo.port)
|
||||
self.events = uievent.BBUIEventQueue(self.connection)
|
||||
self.events = uievent.BBUIEventQueue(self.connection, clientinfo)
|
||||
for event in bb.event.ui_queue:
|
||||
self.events.queue_event(event)
|
||||
|
||||
@@ -267,8 +267,8 @@ class BitBakeServerConnection():
|
||||
pass
|
||||
|
||||
class BitBakeServer(object):
|
||||
def initServer(self):
|
||||
self.server = BitBakeXMLRPCServer()
|
||||
def initServer(self, interface = ("localhost", 0)):
|
||||
self.server = BitBakeXMLRPCServer(interface)
|
||||
|
||||
def addcooker(self, cooker):
|
||||
self.cooker = cooker
|
||||
|
||||
@@ -62,9 +62,13 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
self.runtaskdeps = {}
|
||||
self.gendeps = {}
|
||||
self.lookupcache = {}
|
||||
self.pkgnameextract = re.compile("(?P<fn>.*)\..*")
|
||||
self.basewhitelist = set((data.getVar("BB_HASHBASE_WHITELIST", True) or "").split())
|
||||
self.taskwhitelist = data.getVar("BB_HASHTASK_WHITELIST", True) or None
|
||||
self.taskwhitelist = None
|
||||
self.init_rundepcheck(data)
|
||||
|
||||
def init_rundepcheck(self, data):
|
||||
self.taskwhitelist = data.getVar("BB_HASHTASK_WHITELIST", True) or None
|
||||
if self.taskwhitelist:
|
||||
self.twl = re.compile(self.taskwhitelist)
|
||||
else:
|
||||
@@ -131,17 +135,24 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
for task in taskdeps:
|
||||
d.setVar("BB_BASEHASH_task-%s" % task, self.basehash[fn + "." + task])
|
||||
|
||||
def rundep_check(self, fn, recipename, task, dep, depname, dataCache):
|
||||
# Return True if we should keep the dependency, False to drop it
|
||||
# We only manipulate the dependencies for packages not in the whitelist
|
||||
if self.twl and not self.twl.search(recipename):
|
||||
# then process the actual dependencies
|
||||
if self.twl.search(depname):
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_taskhash(self, fn, task, deps, dataCache):
|
||||
k = fn + "." + task
|
||||
data = dataCache.basetaskhash[k]
|
||||
self.runtaskdeps[k] = []
|
||||
recipename = dataCache.pkg_fn[fn]
|
||||
for dep in sorted(deps, key=clean_basepath):
|
||||
# We only manipulate the dependencies for packages not in the whitelist
|
||||
if self.twl and not self.twl.search(dataCache.pkg_fn[fn]):
|
||||
# then process the actual dependencies
|
||||
dep_fn = re.search("(?P<fn>.*)\..*", dep).group('fn')
|
||||
if self.twl.search(dataCache.pkg_fn[dep_fn]):
|
||||
continue
|
||||
depname = dataCache.pkg_fn[self.pkgnameextract.search(dep).group('fn')]
|
||||
if not self.rundep_check(fn, recipename, task, dep, depname, dataCache):
|
||||
continue
|
||||
if dep not in self.taskhash:
|
||||
bb.fatal("%s is not in taskhash, caller isn't calling in dependency order?", dep)
|
||||
data = data + self.taskhash[dep]
|
||||
@@ -250,11 +261,13 @@ def compare_sigfiles(a, b):
|
||||
|
||||
if 'basewhitelist' in a_data and a_data['basewhitelist'] != b_data['basewhitelist']:
|
||||
print "basewhitelist changed from %s to %s" % (a_data['basewhitelist'], b_data['basewhitelist'])
|
||||
print "changed items: %s" % a_data['basewhitelist'].symmetric_difference(b_data['basewhitelist'])
|
||||
if a_data['basewhitelist'] and b_data['basewhitelist']:
|
||||
print "changed items: %s" % a_data['basewhitelist'].symmetric_difference(b_data['basewhitelist'])
|
||||
|
||||
if 'taskwhitelist' in a_data and a_data['taskwhitelist'] != b_data['taskwhitelist']:
|
||||
print "taskwhitelist changed from %s to %s" % (a_data['taskwhitelist'], b_data['taskwhitelist'])
|
||||
print "changed items: %s" % a_data['taskwhitelist'].symmetric_difference(b_data['taskwhitelist'])
|
||||
if a_data['taskwhitelist'] and b_data['taskwhitelist']:
|
||||
print "changed items: %s" % a_data['taskwhitelist'].symmetric_difference(b_data['taskwhitelist'])
|
||||
|
||||
if a_data['taskdeps'] != b_data['taskdeps']:
|
||||
print "Task dependencies changed from:\n%s\nto:\n%s" % (sorted(a_data['taskdeps']), sorted(b_data['taskdeps']))
|
||||
@@ -266,7 +279,8 @@ def compare_sigfiles(a, b):
|
||||
if changed:
|
||||
for dep in changed:
|
||||
print "List of dependencies for variable %s changed from %s to %s" % (dep, a_data['gendeps'][dep], b_data['gendeps'][dep])
|
||||
print "changed items: %s" % a_data['gendeps'][dep].symmetric_difference(b_data['gendeps'][dep])
|
||||
if a_data['gendeps'][dep] and b_data['gendeps'][dep]:
|
||||
print "changed items: %s" % a_data['gendeps'][dep].symmetric_difference(b_data['gendeps'][dep])
|
||||
if added:
|
||||
for dep in added:
|
||||
print "Dependency on variable %s was added" % (dep)
|
||||
@@ -286,16 +300,27 @@ def compare_sigfiles(a, b):
|
||||
changed, added, removed = dict_diff(a, b)
|
||||
if added:
|
||||
for dep in added:
|
||||
print "Dependency on task %s was added" % (dep)
|
||||
bdep_found = False
|
||||
if removed:
|
||||
for bdep in removed:
|
||||
if a[dep] == b[bdep]:
|
||||
#print "Dependency on task %s was replaced by %s with same hash" % (dep, bdep)
|
||||
bdep_found = True
|
||||
if not bdep_found:
|
||||
print "Dependency on task %s was added with hash %s" % (dep, a[dep])
|
||||
if removed:
|
||||
for dep in removed:
|
||||
print "Dependency on task %s was removed" % (dep)
|
||||
adep_found = False
|
||||
if added:
|
||||
for adep in added:
|
||||
if a[adep] == b[dep]:
|
||||
#print "Dependency on task %s was replaced by %s with same hash" % (adep, dep)
|
||||
adep_found = True
|
||||
if not adep_found:
|
||||
print "Dependency on task %s was removed with hash %s" % (dep, b[dep])
|
||||
if changed:
|
||||
for dep in changed:
|
||||
print "Hash for dependent task %s changed from %s to %s" % (dep, a[dep], b[dep])
|
||||
elif 'runtaskdeps' in a_data and 'runtaskdeps' in b_data and sorted(a_data['runtaskdeps']) != sorted(b_data['runtaskdeps']):
|
||||
print "Tasks this task depends on changed from %s to %s" % (sorted(a_data['runtaskdeps']), sorted(b_data['runtaskdeps']))
|
||||
print "changed items: %s" % a_data['runtaskdeps'].symmetric_difference(b_data['runtaskdeps'])
|
||||
|
||||
def dump_sigfile(a):
|
||||
p1 = pickle.Unpickler(file(a, "rb"))
|
||||
|
||||
110
bitbake/lib/bb/ui/crumbs/builddetailspage.py
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
from bb.ui.crumbs.hobwidget import hic
|
||||
from bb.ui.crumbs.runningbuild import RunningBuildTreeView
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
|
||||
#
|
||||
# BuildDetailsPage
|
||||
#
|
||||
|
||||
class BuildDetailsPage (HobPage):
|
||||
|
||||
def __init__(self, builder):
|
||||
super(BuildDetailsPage, self).__init__(builder, "Building ...")
|
||||
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
def create_visual_elements(self):
|
||||
# create visual elements
|
||||
self.vbox = gtk.VBox(False, 15)
|
||||
|
||||
self.progress_box = gtk.HBox(False, 5)
|
||||
self.progress_bar = HobProgressBar()
|
||||
self.progress_box.pack_start(self.progress_bar, expand=True, fill=True)
|
||||
self.stop_button = gtk.LinkButton("Stop the build process", "Stop")
|
||||
self.stop_button.connect("clicked", self.stop_button_clicked_cb)
|
||||
self.progress_box.pack_end(self.stop_button, expand=False, fill=False)
|
||||
|
||||
self.build_tv = RunningBuildTreeView(readonly=True)
|
||||
self.build_tv.set_model(self.builder.handler.build.model)
|
||||
self.scrolled_view = gtk.ScrolledWindow ()
|
||||
self.scrolled_view.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.scrolled_view.add(self.build_tv)
|
||||
|
||||
self.button_box = gtk.HBox(False, 5)
|
||||
self.back_button = gtk.LinkButton("Go back to Image Configuration screen", "<< Back to image configuration")
|
||||
self.back_button.connect("clicked", self.back_button_clicked_cb)
|
||||
self.button_box.pack_start(self.back_button, expand=False, fill=False)
|
||||
|
||||
def _remove_all_widget(self):
|
||||
children = self.vbox.get_children() or []
|
||||
for child in children:
|
||||
self.vbox.remove(child)
|
||||
children = self.box_group_area.get_children() or []
|
||||
for child in children:
|
||||
self.box_group_area.remove(child)
|
||||
children = self.get_children() or []
|
||||
for child in children:
|
||||
self.remove(child)
|
||||
|
||||
def show_page(self, step):
|
||||
self._remove_all_widget()
|
||||
if step == self.builder.PACKAGE_GENERATING or step == self.builder.FAST_IMAGE_GENERATING:
|
||||
self.title = "Building packages ..."
|
||||
else:
|
||||
self.title = "Building image ..."
|
||||
self.build_details_top = self.add_onto_top_bar(None)
|
||||
self.pack_start(self.build_details_top, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
|
||||
|
||||
self.progress_bar.reset()
|
||||
self.vbox.pack_start(self.progress_box, expand=False, fill=False)
|
||||
|
||||
self.vbox.pack_start(self.scrolled_view, expand=True, fill=True)
|
||||
|
||||
self.box_group_area.pack_end(self.button_box, expand=False, fill=False)
|
||||
self.show_all()
|
||||
self.back_button.hide()
|
||||
|
||||
def update_progress_bar(self, title, fraction, status=True):
|
||||
self.progress_bar.update(fraction)
|
||||
self.progress_bar.set_title(title)
|
||||
self.progress_bar.set_rcstyle(status)
|
||||
|
||||
def back_button_clicked_cb(self, button):
|
||||
self.builder.show_configuration()
|
||||
|
||||
def show_back_button(self):
|
||||
self.back_button.show()
|
||||
|
||||
def stop_button_clicked_cb(self, button):
|
||||
self.builder.stop_build()
|
||||
|
||||
def hide_stop_button(self):
|
||||
self.stop_button.hide()
|
||||
873
bitbake/lib/bb/ui/crumbs/builder.py
Executable file
@@ -0,0 +1,873 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011-2012 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import copy
|
||||
import os
|
||||
import subprocess
|
||||
import shlex
|
||||
from bb.ui.crumbs.template import TemplateMgr
|
||||
from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
|
||||
from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
|
||||
from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
|
||||
from bb.ui.crumbs.builddetailspage import BuildDetailsPage
|
||||
from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
|
||||
from bb.ui.crumbs.hobwidget import hwc
|
||||
from bb.ui.crumbs.hig import CrumbsDialog, BinbDialog, \
|
||||
AdvancedSettingDialog, LayerSelectionDialog, \
|
||||
DeployImageDialog, ImageSelectionDialog
|
||||
|
||||
class Configuration:
|
||||
'''Represents the data structure of configuration.'''
|
||||
|
||||
def __init__(self, params):
|
||||
# Settings
|
||||
self.curr_mach = ""
|
||||
self.curr_distro = params["distro"]
|
||||
self.dldir = params["dldir"]
|
||||
self.sstatedir = params["sstatedir"]
|
||||
self.sstatemirror = params["sstatemirror"]
|
||||
self.pmake = params["pmake"]
|
||||
self.bbthread = params["bbthread"]
|
||||
self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
|
||||
self.image_rootfs_size = params["image_rootfs_size"]
|
||||
self.image_extra_size = params["image_extra_size"]
|
||||
self.image_overhead_factor = params['image_overhead_factor']
|
||||
self.incompat_license = params["incompat_license"]
|
||||
self.curr_sdk_machine = params["sdk_machine"]
|
||||
self.extra_setting = {}
|
||||
self.toolchain_build = False
|
||||
self.image_fstypes = params["image_fstypes"].split()
|
||||
# bblayers.conf
|
||||
self.layers = params["layer"].split()
|
||||
# image/recipes/packages
|
||||
self.selected_image = None
|
||||
self.selected_recipes = []
|
||||
self.selected_packages = []
|
||||
|
||||
def load(self, template):
|
||||
self.curr_mach = template.getVar("MACHINE")
|
||||
self.curr_package_format = " ".join(template.getVar("PACKAGE_CLASSES").split("package_")).strip()
|
||||
self.curr_distro = template.getVar("DISTRO")
|
||||
self.dldir = template.getVar("DL_DIR")
|
||||
self.sstatedir = template.getVar("SSTATE_DIR")
|
||||
self.sstatemirror = template.getVar("SSTATE_MIRROR")
|
||||
self.pmake = int(template.getVar("PARALLEL_MAKE").split()[1])
|
||||
self.bbthread = int(template.getVar("BB_NUMBER_THREAD"))
|
||||
self.image_rootfs_size = int(template.getVar("IMAGE_ROOTFS_SIZE"))
|
||||
self.image_extra_size = int(template.getVar("IMAGE_EXTRA_SPACE"))
|
||||
# image_overhead_factor is read-only.
|
||||
self.incompat_license = template.getVar("INCOMPATIBLE_LICENSE")
|
||||
self.curr_sdk_machine = template.getVar("SDKMACHINE")
|
||||
self.extra_setting = eval(template.getVar("EXTRA_SETTING"))
|
||||
self.toolchain_build = eval(template.getVar("TOOLCHAIN_BUILD"))
|
||||
self.image_fstypes = template.getVar("IMAGE_FSTYPES").split()
|
||||
# bblayers.conf
|
||||
self.layers = template.getVar("BBLAYERS").split()
|
||||
# image/recipes/packages
|
||||
self.selected_image = template.getVar("__SELECTED_IMAGE__")
|
||||
self.selected_recipes = template.getVar("DEPENDS").split()
|
||||
self.selected_packages = template.getVar("IMAGE_INSTALL").split()
|
||||
|
||||
def save(self, template, filename):
|
||||
# bblayers.conf
|
||||
template.setVar("BBLAYERS", " ".join(self.layers))
|
||||
# local.conf
|
||||
template.setVar("MACHINE", self.curr_mach)
|
||||
template.setVar("DISTRO", self.curr_distro)
|
||||
template.setVar("DL_DIR", self.dldir)
|
||||
template.setVar("SSTATE_DIR", self.sstatedir)
|
||||
template.setVar("SSTATE_MIRROR", self.sstatemirror)
|
||||
template.setVar("PARALLEL_MAKE", "-j %s" % self.pmake)
|
||||
template.setVar("BB_NUMBER_THREAD", self.bbthread)
|
||||
template.setVar("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]))
|
||||
template.setVar("IMAGE_ROOTFS_SIZE", self.image_rootfs_size)
|
||||
template.setVar("IMAGE_EXTRA_SPACE", self.image_extra_size)
|
||||
template.setVar("INCOMPATIBLE_LICENSE", self.incompat_license)
|
||||
template.setVar("SDKMACHINE", self.curr_sdk_machine)
|
||||
template.setVar("EXTRA_SETTING", self.extra_setting)
|
||||
template.setVar("TOOLCHAIN_BUILD", self.toolchain_build)
|
||||
template.setVar("IMAGE_FSTYPES", " ".join(self.image_fstypes).lstrip(" "))
|
||||
# image/recipes/packages
|
||||
self.selected_image = filename
|
||||
template.setVar("__SELECTED_IMAGE__", self.selected_image)
|
||||
template.setVar("DEPENDS", self.selected_recipes)
|
||||
template.setVar("IMAGE_INSTALL", self.selected_packages)
|
||||
|
||||
class Parameters:
|
||||
'''Represents other variables like available machines, etc.'''
|
||||
|
||||
def __init__(self, params):
|
||||
# Variables
|
||||
self.all_machines = []
|
||||
self.all_package_formats = []
|
||||
self.all_distros = []
|
||||
self.all_sdk_machines = []
|
||||
self.max_threads = params["max_threads"]
|
||||
self.all_layers = []
|
||||
self.core_base = params["core_base"]
|
||||
self.image_names = []
|
||||
self.image_addr = params["image_addr"]
|
||||
self.image_types = params["image_types"].split()
|
||||
|
||||
class Builder(gtk.Window):
|
||||
|
||||
(MACHINE_SELECTION,
|
||||
LAYER_CHANGED,
|
||||
RCPPKGINFO_POPULATING,
|
||||
RCPPKGINFO_POPULATED,
|
||||
RECIPE_SELECTION,
|
||||
PACKAGE_GENERATING,
|
||||
PACKAGE_GENERATED,
|
||||
PACKAGE_SELECTION,
|
||||
FAST_IMAGE_GENERATING,
|
||||
IMAGE_GENERATING,
|
||||
IMAGE_GENERATED,
|
||||
MY_IMAGE_OPENED,
|
||||
BACK,
|
||||
END_NOOP) = range(14)
|
||||
|
||||
(IMAGE_CONFIGURATION,
|
||||
RECIPE_DETAILS,
|
||||
BUILD_DETAILS,
|
||||
PACKAGE_DETAILS,
|
||||
IMAGE_DETAILS,
|
||||
END_TAB) = range(6)
|
||||
|
||||
__step2page__ = {
|
||||
MACHINE_SELECTION : IMAGE_CONFIGURATION,
|
||||
LAYER_CHANGED : IMAGE_CONFIGURATION,
|
||||
RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
|
||||
RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
|
||||
RECIPE_SELECTION : RECIPE_DETAILS,
|
||||
PACKAGE_GENERATING : BUILD_DETAILS,
|
||||
PACKAGE_GENERATED : PACKAGE_DETAILS,
|
||||
PACKAGE_SELECTION : PACKAGE_DETAILS,
|
||||
FAST_IMAGE_GENERATING : BUILD_DETAILS,
|
||||
IMAGE_GENERATING : BUILD_DETAILS,
|
||||
IMAGE_GENERATED : IMAGE_DETAILS,
|
||||
MY_IMAGE_OPENED : IMAGE_DETAILS,
|
||||
END_NOOP : None,
|
||||
}
|
||||
|
||||
def __init__(self, hobHandler, recipe_model, package_model):
|
||||
super(Builder, self).__init__()
|
||||
|
||||
# handler
|
||||
self.handler = hobHandler
|
||||
|
||||
self.template = None
|
||||
|
||||
# settings
|
||||
params = self.handler.get_parameters()
|
||||
self.configuration = Configuration(params)
|
||||
self.parameters = Parameters(params)
|
||||
|
||||
# build step
|
||||
self.current_step = None
|
||||
self.previous_step = None
|
||||
|
||||
self.stopping = False
|
||||
self.build_succeeded = True
|
||||
|
||||
# recipe model and package model
|
||||
self.recipe_model = recipe_model
|
||||
self.package_model = package_model
|
||||
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
# connect the signals to functions
|
||||
#self.connect("configure-event", self.resize_window_cb)
|
||||
self.connect("delete-event", self.destroy_window_cb)
|
||||
self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
|
||||
self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
|
||||
self.recipe_model.connect ("recipelist-populated", self.recipelist_populated_cb)
|
||||
self.package_model.connect("packagelist-populated", self.packagelist_populated_cb)
|
||||
self.handler.connect("config-updated", self.handler_config_updated_cb)
|
||||
self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
|
||||
self.handler.connect("layers-updated", self.handler_layers_updated_cb)
|
||||
self.handler.connect("parsing-started", self.handler_parsing_started_cb)
|
||||
self.handler.connect("parsing", self.handler_parsing_cb)
|
||||
self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
|
||||
self.handler.build.connect("build-started", self.handler_build_started_cb)
|
||||
self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
|
||||
self.handler.build.connect("build-failed", self.handler_build_failed_cb)
|
||||
self.handler.build.connect("task-started", self.handler_task_started_cb)
|
||||
self.handler.connect("generating-data", self.handler_generating_data_cb)
|
||||
self.handler.connect("data-generated", self.handler_data_generated_cb)
|
||||
self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
|
||||
self.handler.connect("command-failed", self.handler_command_failed_cb)
|
||||
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.set_title("HOB -- Image Creator")
|
||||
self.set_icon_name("applications-development")
|
||||
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
|
||||
self.set_resizable(True)
|
||||
window_width = self.get_screen().get_width()
|
||||
window_height = self.get_screen().get_height()
|
||||
if window_width >= hwc.MAIN_WIN_WIDTH:
|
||||
window_width = hwc.MAIN_WIN_WIDTH
|
||||
window_height = hwc.MAIN_WIN_HEIGHT
|
||||
else:
|
||||
lbl = "<b>Screen dimension mismatched</b>\nfor better usability and visual effects,"
|
||||
lbl = lbl + " the screen dimension should be 1024x768 or above."
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
self.set_size_request(window_width, window_height)
|
||||
|
||||
self.vbox = gtk.VBox(False, 0)
|
||||
self.vbox.set_border_width(0)
|
||||
self.add(self.vbox)
|
||||
|
||||
# create pages
|
||||
self.image_configuration_page = ImageConfigurationPage(self)
|
||||
self.recipe_details_page = RecipeSelectionPage(self)
|
||||
self.build_details_page = BuildDetailsPage(self)
|
||||
self.package_details_page = PackageSelectionPage(self)
|
||||
self.image_details_page = ImageDetailsPage(self)
|
||||
|
||||
self.nb = gtk.Notebook()
|
||||
self.nb.set_show_tabs(False)
|
||||
self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
|
||||
self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
|
||||
self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
|
||||
self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
|
||||
self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
|
||||
self.vbox.pack_start(self.nb, expand=True, fill=True)
|
||||
|
||||
self.show_all()
|
||||
self.nb.set_current_page(0)
|
||||
|
||||
def get_split_model(self):
|
||||
return self.handler.split_model
|
||||
|
||||
def load_template(self, path):
|
||||
self.template = TemplateMgr()
|
||||
self.template.load(path)
|
||||
self.configuration.load(self.template)
|
||||
|
||||
if self.get_split_model():
|
||||
if not set(self.configuration.layers) <= set(self.parameters.all_layers):
|
||||
return False
|
||||
else:
|
||||
for layer in self.configuration.layers:
|
||||
if not os.path.exists(layer+'/conf/layer.conf'):
|
||||
return False
|
||||
|
||||
self.switch_page(self.LAYER_CHANGED)
|
||||
|
||||
self.template.destroy()
|
||||
self.template = None
|
||||
|
||||
def save_template(self, path):
|
||||
if path.rfind("/") == -1:
|
||||
filename = "default"
|
||||
path = "."
|
||||
else:
|
||||
filename = path[path.rfind("/") + 1:len(path)]
|
||||
path = path[0:path.rfind("/")]
|
||||
|
||||
self.template = TemplateMgr()
|
||||
self.template.open(filename, path)
|
||||
self.configuration.save(self.template, filename)
|
||||
|
||||
self.template.save()
|
||||
self.template.destroy()
|
||||
self.template = None
|
||||
|
||||
def switch_page(self, next_step):
|
||||
# Main Workflow (Business Logic)
|
||||
self.nb.set_current_page(self.__step2page__[next_step])
|
||||
|
||||
if next_step == self.MACHINE_SELECTION: # init step
|
||||
self.image_configuration_page.show_machine()
|
||||
|
||||
elif next_step == self.LAYER_CHANGED:
|
||||
# after layers is changd by users
|
||||
self.image_configuration_page.show_machine()
|
||||
self.handler.refresh_layers(self.configuration.layers)
|
||||
|
||||
elif next_step == self.RCPPKGINFO_POPULATING:
|
||||
# MACHINE CHANGED action or SETTINGS CHANGED
|
||||
# show the progress bar
|
||||
self.image_configuration_page.show_info_populating()
|
||||
self.generate_recipes()
|
||||
|
||||
elif next_step == self.RCPPKGINFO_POPULATED:
|
||||
self.image_configuration_page.show_info_populated()
|
||||
|
||||
elif next_step == self.RECIPE_SELECTION:
|
||||
pass
|
||||
|
||||
elif next_step == self.PACKAGE_SELECTION:
|
||||
pass
|
||||
|
||||
elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
|
||||
# both PACKAGE_GENEATING and FAST_IMAGE_GENERATING share the same page
|
||||
self.build_details_page.show_page(next_step)
|
||||
self.generate_packages()
|
||||
|
||||
elif next_step == self.PACKAGE_GENERATED:
|
||||
pass
|
||||
|
||||
elif next_step == self.IMAGE_GENERATING:
|
||||
# after packages are generated, selected_packages need to
|
||||
# be updated in package_model per selected_image in recipe_model
|
||||
self.build_details_page.show_page(next_step)
|
||||
self.generate_image()
|
||||
|
||||
elif next_step == self.IMAGE_GENERATED:
|
||||
self.image_details_page.show_page(next_step)
|
||||
|
||||
elif next_step == self.MY_IMAGE_OPENED:
|
||||
self.image_details_page.show_page(next_step)
|
||||
|
||||
self.previous_step = self.current_step
|
||||
self.current_step = next_step
|
||||
|
||||
def set_user_config(self):
|
||||
self.handler.init_cooker()
|
||||
# set bb layers
|
||||
self.handler.set_bblayers(self.configuration.layers)
|
||||
# set local configuration
|
||||
self.handler.set_machine(self.configuration.curr_mach)
|
||||
self.handler.set_package_format(self.configuration.curr_package_format)
|
||||
self.handler.set_distro(self.configuration.curr_distro)
|
||||
self.handler.set_dl_dir(self.configuration.dldir)
|
||||
self.handler.set_sstate_dir(self.configuration.sstatedir)
|
||||
self.handler.set_sstate_mirror(self.configuration.sstatemirror)
|
||||
self.handler.set_pmake(self.configuration.pmake)
|
||||
self.handler.set_bbthreads(self.configuration.bbthread)
|
||||
self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
|
||||
self.handler.set_extra_size(self.configuration.image_extra_size)
|
||||
self.handler.set_incompatible_license(self.configuration.incompat_license)
|
||||
self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
|
||||
self.handler.set_image_fstypes(self.configuration.image_fstypes)
|
||||
self.handler.set_extra_config(self.configuration.extra_setting)
|
||||
self.handler.set_extra_inherit("packageinfo")
|
||||
|
||||
def reset_recipe_model(self):
|
||||
self.recipe_model.reset()
|
||||
|
||||
def reset_package_model(self):
|
||||
self.package_model.reset()
|
||||
|
||||
def update_recipe_model(self, selected_image, selected_recipes):
|
||||
self.recipe_model.set_selected_image(selected_image)
|
||||
self.recipe_model.set_selected_recipes(selected_recipes)
|
||||
|
||||
def update_package_model(self, selected_packages):
|
||||
left = self.package_model.set_selected_packages(selected_packages)
|
||||
self.configuration.selected_packages += left
|
||||
|
||||
def generate_packages(self):
|
||||
# Build packages
|
||||
_, all_recipes = self.recipe_model.get_selected_recipes()
|
||||
self.set_user_config()
|
||||
self.handler.reset_build()
|
||||
self.handler.generate_packages(all_recipes)
|
||||
|
||||
def generate_recipes(self):
|
||||
# Parse recipes
|
||||
self.set_user_config()
|
||||
self.handler.generate_recipes()
|
||||
|
||||
def generate_image(self):
|
||||
# Build image
|
||||
self.set_user_config()
|
||||
all_packages = self.package_model.get_selected_packages()
|
||||
self.handler.reset_build()
|
||||
self.handler.generate_image(all_packages, self.configuration.toolchain_build)
|
||||
|
||||
|
||||
# Callback Functions
|
||||
def handler_config_updated_cb(self, handler, which, values):
|
||||
if which == "distro":
|
||||
self.parameters.all_distros = values
|
||||
elif which == "machine":
|
||||
self.parameters.all_machines = values
|
||||
self.image_configuration_page.update_machine_combo()
|
||||
elif which == "machine-sdk":
|
||||
self.parameters.all_sdk_machines = values
|
||||
|
||||
def handler_package_formats_updated_cb(self, handler, formats):
|
||||
self.parameters.all_package_formats = formats
|
||||
|
||||
def handler_layers_updated_cb(self, handler, layers):
|
||||
self.parameters.all_layers = layers
|
||||
|
||||
def handler_command_succeeded_cb(self, handler, initcmd):
|
||||
if initcmd == self.handler.LAYERS_REFRESH:
|
||||
self.image_configuration_page.switch_machine_combo()
|
||||
elif initcmd in [self.handler.GENERATE_RECIPES,
|
||||
self.handler.GENERATE_PACKAGES,
|
||||
self.handler.GENERATE_IMAGE]:
|
||||
self.handler.request_package_info_async()
|
||||
elif initcmd == self.handler.POPULATE_PACKAGEINFO:
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
self.switch_page(self.IMAGE_GENERATING)
|
||||
elif self.current_step == self.RCPPKGINFO_POPULATING:
|
||||
self.switch_page(self.RCPPKGINFO_POPULATED)
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
self.switch_page(self.PACKAGE_GENERATED)
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
self.switch_page(self.IMAGE_GENERATED)
|
||||
|
||||
def handler_command_failed_cb(self, handler, msg):
|
||||
lbl = "<b>Error</b>\n"
|
||||
lbl = lbl + "%s\n\n" % msg
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
self.handler.clear_busy()
|
||||
self.configuration.curr_mach = None
|
||||
self.image_configuration_page.switch_machine_combo()
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
|
||||
def window_sensitive(self, sensitive):
|
||||
self.set_sensitive(sensitive)
|
||||
if sensitive:
|
||||
self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
|
||||
else:
|
||||
self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
||||
|
||||
|
||||
def handler_generating_data_cb(self, handler):
|
||||
self.window_sensitive(False)
|
||||
|
||||
def handler_data_generated_cb(self, handler):
|
||||
self.window_sensitive(True)
|
||||
|
||||
def recipelist_populated_cb(self, recipe_model):
|
||||
selected_image = self.configuration.selected_image
|
||||
selected_recipes = self.configuration.selected_recipes[:]
|
||||
selected_packages = self.configuration.selected_packages[:]
|
||||
|
||||
self.recipe_model.image_list_append(selected_image,
|
||||
" ".join(selected_recipes),
|
||||
" ".join(selected_packages))
|
||||
|
||||
self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
|
||||
|
||||
self.update_recipe_model(selected_image, selected_recipes)
|
||||
|
||||
def packagelist_populated_cb(self, package_model):
|
||||
selected_packages = self.configuration.selected_packages[:]
|
||||
self.update_package_model(selected_packages)
|
||||
|
||||
def recipelist_changed_cb(self, recipe_model):
|
||||
self.recipe_details_page.refresh_selection()
|
||||
|
||||
def packagelist_changed_cb(self, package_model):
|
||||
self.package_details_page.refresh_selection()
|
||||
|
||||
def handler_parsing_started_cb(self, handler, message):
|
||||
if self.current_step != self.RCPPKGINFO_POPULATING:
|
||||
return
|
||||
|
||||
fraction = 0
|
||||
if message["eventname"] == "TreeDataPreparationStarted":
|
||||
fraction = 0.6 + fraction
|
||||
self.image_configuration_page.update_progress_bar(message["title"], fraction)
|
||||
|
||||
def handler_parsing_cb(self, handler, message):
|
||||
if self.current_step != self.RCPPKGINFO_POPULATING:
|
||||
return
|
||||
|
||||
fraction = message["current"] * 1.0/message["total"]
|
||||
if message["eventname"] == "TreeDataPreparationProgress":
|
||||
fraction = 0.6 + 0.4 * fraction
|
||||
else:
|
||||
fraction = 0.6 * fraction
|
||||
self.image_configuration_page.update_progress_bar(message["title"], fraction)
|
||||
|
||||
def handler_parsing_completed_cb(self, handler, message):
|
||||
if self.current_step != self.RCPPKGINFO_POPULATING:
|
||||
return
|
||||
|
||||
if message["eventname"] == "TreeDataPreparationCompleted":
|
||||
fraction = 1.0
|
||||
else:
|
||||
fraction = 0.6
|
||||
self.image_configuration_page.update_progress_bar(message["title"], fraction)
|
||||
|
||||
def handler_build_started_cb(self, running_build):
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
fraction = 0
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
if self.previous_step == self.FAST_IMAGE_GENERATING:
|
||||
fraction = 0.9
|
||||
else:
|
||||
fraction = 0
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
fraction = 0
|
||||
self.build_details_page.update_progress_bar("Build Started: ", fraction)
|
||||
|
||||
def handler_build_succeeded_cb(self, running_build):
|
||||
self.build_succeeded = True
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
fraction = 0.9
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
fraction = 1.0
|
||||
self.parameters.image_names = []
|
||||
linkname = 'hob-image-' + self.configuration.curr_mach
|
||||
for image_type in self.parameters.image_types:
|
||||
linkpath = self.parameters.image_addr + '/' + linkname + '.' + image_type
|
||||
if os.path.exists(linkpath):
|
||||
self.parameters.image_names.append(os.readlink(linkpath))
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
fraction = 1.0
|
||||
self.build_details_page.update_progress_bar("Build Completed: ", fraction)
|
||||
|
||||
def handler_build_failed_cb(self, running_build):
|
||||
self.build_succeeded = False
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
fraction = 0.9
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
fraction = 1.0
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
fraction = 1.0
|
||||
self.build_details_page.update_progress_bar("Build Failed: ", fraction, False)
|
||||
self.build_details_page.show_back_button()
|
||||
self.build_details_page.hide_stop_button()
|
||||
self.handler.build_failed_async()
|
||||
self.stopping = False
|
||||
|
||||
def handler_task_started_cb(self, running_build, message):
|
||||
fraction = message["current"] * 1.0/message["total"]
|
||||
title = "Build packages"
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
if message["eventname"] == "sceneQueueTaskStarted":
|
||||
fraction = 0.27 * fraction
|
||||
elif message["eventname"] == "runQueueTaskStarted":
|
||||
fraction = 0.27 + 0.63 * fraction
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
title = "Build image"
|
||||
if self.previous_step == self.FAST_IMAGE_GENERATING:
|
||||
if message["eventname"] == "sceneQueueTaskStarted":
|
||||
fraction = 0.27 + 0.63 + 0.03 * fraction
|
||||
elif message["eventname"] == "runQueueTaskStarted":
|
||||
fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
|
||||
else:
|
||||
if message["eventname"] == "sceneQueueTaskStarted":
|
||||
fraction = 0.2 * fraction
|
||||
elif message["eventname"] == "runQueueTaskStarted":
|
||||
fraction = 0.2 + 0.8 * fraction
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
if message["eventname"] == "sceneQueueTaskStarted":
|
||||
fraction = 0.2 * fraction
|
||||
elif message["eventname"] == "runQueueTaskStarted":
|
||||
fraction = 0.2 + 0.8 * fraction
|
||||
self.build_details_page.update_progress_bar(title + ": ", fraction)
|
||||
|
||||
def destroy_window_cb(self, widget, event):
|
||||
lbl = "<b>Do you really want to exit the Hob image creator?</b>"
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_YES, gtk.RESPONSE_YES)
|
||||
dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
|
||||
dialog.set_default_response(gtk.RESPONSE_NO)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
gtk.main_quit()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def build_packages(self):
|
||||
_, all_recipes = self.recipe_model.get_selected_recipes()
|
||||
if not all_recipes:
|
||||
lbl = "<b>No selections made</b>\nYou have not made any selections"
|
||||
lbl = lbl + " so there isn't anything to bake at this time."
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
self.switch_page(self.PACKAGE_GENERATING)
|
||||
|
||||
def build_image(self):
|
||||
selected_packages = self.package_model.get_selected_packages()
|
||||
if not selected_packages:
|
||||
lbl = "<b>No selections made</b>\nYou have not made any selections"
|
||||
lbl = lbl + " so there isn't anything to bake at this time."
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
self.switch_page(self.IMAGE_GENERATING)
|
||||
|
||||
def just_bake(self):
|
||||
selected_image = self.recipe_model.get_selected_image()
|
||||
selected_packages = self.package_model.get_selected_packages() or []
|
||||
|
||||
# If no base image and no selected packages don't build anything
|
||||
if not (selected_packages or selected_image != self.recipe_model.__dummy_image__):
|
||||
lbl = "<b>No selections made</b>\nYou have not made any selections"
|
||||
lbl = lbl + " so there isn't anything to bake at this time."
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
self.switch_page(self.FAST_IMAGE_GENERATING)
|
||||
|
||||
def show_binb_dialog(self, binb):
|
||||
binb_dialog = BinbDialog("Brought in by:", binb, self)
|
||||
binb_dialog.run()
|
||||
binb_dialog.destroy()
|
||||
|
||||
def show_layer_selection_dialog(self):
|
||||
dialog = LayerSelectionDialog(title = "Layer Selection",
|
||||
layers = copy.deepcopy(self.configuration.layers),
|
||||
all_layers = self.parameters.all_layers,
|
||||
split_model = self.get_split_model(),
|
||||
parent = self,
|
||||
flags = gtk.DIALOG_MODAL
|
||||
| gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.DIALOG_NO_SEPARATOR,
|
||||
buttons = (gtk.STOCK_OK, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.configuration.layers = dialog.layers
|
||||
# DO refresh layers
|
||||
if dialog.layers_changed:
|
||||
self.switch_page(self.LAYER_CHANGED)
|
||||
dialog.destroy()
|
||||
|
||||
def show_load_template_dialog(self):
|
||||
dialog = gtk.FileChooserDialog("Load Template Files", self,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
(gtk.STOCK_OPEN, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
filter = gtk.FileFilter()
|
||||
filter.set_name("HOB Files")
|
||||
filter.add_pattern("*.hob")
|
||||
dialog.add_filter(filter)
|
||||
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
path = dialog.get_filename()
|
||||
self.load_template(path)
|
||||
dialog.destroy()
|
||||
|
||||
def show_save_template_dialog(self):
|
||||
dialog = gtk.FileChooserDialog("Save Template Files", self,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
(gtk.STOCK_SAVE, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
dialog.set_current_name("hob")
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
path = dialog.get_filename()
|
||||
self.save_template(path)
|
||||
dialog.destroy()
|
||||
|
||||
def show_load_my_images_dialog(self):
|
||||
dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
|
||||
"Open My Images", self,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
(gtk.STOCK_OPEN, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
if not dialog.image_names:
|
||||
lbl = "<b>No selections made</b>\nYou have not made any selections"
|
||||
crumbs_dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
crumbs_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
crumbs_dialog.run()
|
||||
crumbs_dialog.destroy()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
self.parameters.image_addr = dialog.image_folder
|
||||
self.parameters.image_names = dialog.image_names[:]
|
||||
self.switch_page(self.MY_IMAGE_OPENED)
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def show_adv_settings_dialog(self):
|
||||
dialog = AdvancedSettingDialog(title = "Settings",
|
||||
configuration = copy.deepcopy(self.configuration),
|
||||
all_image_types = self.parameters.image_types,
|
||||
all_package_formats = self.parameters.all_package_formats,
|
||||
all_distros = self.parameters.all_distros,
|
||||
all_sdk_machines = self.parameters.all_sdk_machines,
|
||||
max_threads = self.parameters.max_threads,
|
||||
split_model = self.get_split_model(),
|
||||
parent = self,
|
||||
flags = gtk.DIALOG_MODAL
|
||||
| gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.DIALOG_NO_SEPARATOR,
|
||||
buttons = ("Save", gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.configuration = dialog.configuration
|
||||
# DO reparse recipes
|
||||
if dialog.settings_changed:
|
||||
if self.configuration.curr_mach == "":
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
else:
|
||||
self.switch_page(self.RCPPKGINFO_POPULATING)
|
||||
dialog.destroy()
|
||||
|
||||
def deploy_image(self, image_name):
|
||||
if not image_name:
|
||||
lbl = "<b>Please select an image to deploy.</b>"
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
image_path = os.path.join(self.parameters.image_addr, image_name)
|
||||
dialog = DeployImageDialog(title = "Usb Image Maker",
|
||||
image_path = image_path,
|
||||
parent = self,
|
||||
flags = gtk.DIALOG_MODAL
|
||||
| gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.DIALOG_NO_SEPARATOR,
|
||||
buttons = ("Close", gtk.RESPONSE_NO,
|
||||
"Make usb image", gtk.RESPONSE_YES))
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def runqemu_image(self, image_name):
|
||||
if not image_name:
|
||||
lbl = "<b>Please select an image to launch in QEMU.</b>"
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
dialog = gtk.FileChooserDialog("Load Kernel Files", self,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
(gtk.STOCK_OPEN, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
filter = gtk.FileFilter()
|
||||
filter.set_name("Kernel Files")
|
||||
filter.add_pattern("*.bin")
|
||||
dialog.add_filter(filter)
|
||||
|
||||
dialog.set_current_folder(self.parameters.image_addr)
|
||||
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
kernel_path = dialog.get_filename()
|
||||
image_path = os.path.join(self.parameters.image_addr, image_name)
|
||||
dialog.destroy()
|
||||
|
||||
if response == gtk.RESPONSE_YES:
|
||||
source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
|
||||
tmp_path = os.path.join(os.getcwd(), "tmp")
|
||||
if os.path.exists(image_path) and os.path.exists(kernel_path) \
|
||||
and os.path.exists(source_env_path) and os.path.exists(tmp_path):
|
||||
cmdline = "/usr/bin/xterm -e "
|
||||
cmdline += "\" export OE_TMPDIR=" + tmp_path + "; "
|
||||
cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
|
||||
cmdline += "runqemu " + kernel_path + " " + image_path + "; bash\""
|
||||
subprocess.Popen(shlex.split(cmdline))
|
||||
else:
|
||||
lbl = "<b>Path error</b>\nOne of your paths is wrong,"
|
||||
lbl = lbl + " please make sure the following paths exist:\n"
|
||||
lbl = lbl + "image path:" + image_path + "\n"
|
||||
lbl = lbl + "kernel path:" + kernel_path + "\n"
|
||||
lbl = lbl + "source environment path:" + source_env_path + "\n"
|
||||
lbl = lbl + "tmp path: " + tmp_path + "."
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def show_packages(self, ask=True):
|
||||
_, selected_recipes = self.recipe_model.get_selected_recipes()
|
||||
if selected_recipes and ask:
|
||||
lbl = "<b>Package list may be incomplete!</b>\nDo you want to build selected recipes"
|
||||
lbl = lbl + " to get a full list (Yes) or just view the existing packages (No)?"
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
dialog.add_button(gtk.STOCK_YES, gtk.RESPONSE_YES)
|
||||
dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
|
||||
dialog.set_default_response(gtk.RESPONSE_YES)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.switch_page(self.PACKAGE_GENERATING)
|
||||
else:
|
||||
self.switch_page(self.PACKAGE_SELECTION)
|
||||
else:
|
||||
self.switch_page(self.PACKAGE_SELECTION)
|
||||
|
||||
def show_recipes(self):
|
||||
self.switch_page(self.RECIPE_SELECTION)
|
||||
|
||||
def initiate_new_build(self):
|
||||
self.configuration.curr_mach = ""
|
||||
self.image_configuration_page.switch_machine_combo()
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
|
||||
def show_configuration(self):
|
||||
self.switch_page(self.RCPPKGINFO_POPULATED)
|
||||
|
||||
def stop_build(self):
|
||||
if self.stopping:
|
||||
lbl = "<b>Force Stop build?</b>\nYou've already selected Stop once,"
|
||||
lbl = lbl + " would you like to 'Force Stop' the build?\n\n"
|
||||
lbl = lbl + "This will stop the build as quickly as possible but may"
|
||||
lbl = lbl + " well leave your build directory in an unusable state"
|
||||
lbl = lbl + " that requires manual steps to fix.\n"
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
|
||||
dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
||||
dialog.add_button("Force Stop", gtk.RESPONSE_YES)
|
||||
else:
|
||||
lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
|
||||
lbl = lbl + " build?\n\n'Force Stop' will stop the build as quickly as"
|
||||
lbl = lbl + " possible but may well leave your build directory in an"
|
||||
lbl = lbl + " unusable state that requires manual steps to fix.\n\n"
|
||||
lbl = lbl + "'Stop' will stop the build as soon as all in"
|
||||
lbl = lbl + " progress build tasks are finished. However if a"
|
||||
lbl = lbl + " lengthy compilation phase is in progress this may take"
|
||||
lbl = lbl + " some time."
|
||||
dialog = CrumbsDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
|
||||
dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
||||
dialog.add_button("Stop", gtk.RESPONSE_OK)
|
||||
dialog.add_button("Force Stop", gtk.RESPONSE_YES)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response != gtk.RESPONSE_CANCEL:
|
||||
self.stopping = True
|
||||
if response == gtk.RESPONSE_OK:
|
||||
self.handler.cancel_build()
|
||||
elif response == gtk.RESPONSE_YES:
|
||||
self.handler.cancel_build(True)
|
||||
@@ -1,346 +0,0 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gobject
|
||||
import copy
|
||||
import re, os
|
||||
from bb import data
|
||||
|
||||
class Configurator(gobject.GObject):
|
||||
|
||||
"""
|
||||
A GObject to handle writing modified configuration values back
|
||||
to conf files.
|
||||
"""
|
||||
__gsignals__ = {
|
||||
"layers-loaded" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"layers-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
())
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self.bblayers = None
|
||||
self.enabled_layers = {}
|
||||
self.loaded_layers = {}
|
||||
self.config = {}
|
||||
self.orig_config = {}
|
||||
self.preconf = None
|
||||
self.postconf = None
|
||||
|
||||
# NOTE: cribbed from the cooker...
|
||||
def _parse(self, f, data, include=False):
|
||||
try:
|
||||
return bb.parse.handle(f, data, include)
|
||||
except (IOError, bb.parse.ParseError) as exc:
|
||||
parselog.critical("Unable to parse %s: %s" % (f, exc))
|
||||
sys.exit(1)
|
||||
|
||||
def _loadConf(self, path):
|
||||
def getString(var):
|
||||
return data.getVar(var, True) or ""
|
||||
|
||||
if self.orig_config:
|
||||
del self.orig_config
|
||||
self.orig_config = {}
|
||||
|
||||
data = bb.data.init()
|
||||
data = self._parse(path, data)
|
||||
|
||||
# We only need to care about certain variables
|
||||
mach = getString('MACHINE')
|
||||
if mach and mach != self.config.get('MACHINE', ''):
|
||||
self.config['MACHINE'] = mach
|
||||
sdkmach = getString('SDKMACHINE')
|
||||
if sdkmach and sdkmach != self.config.get('SDKMACHINE', ''):
|
||||
self.config['SDKMACHINE'] = sdkmach
|
||||
distro = getString('DISTRO')
|
||||
if not distro:
|
||||
distro = "defaultsetup"
|
||||
if distro and distro != self.config.get('DISTRO', ''):
|
||||
self.config['DISTRO'] = distro
|
||||
bbnum = getString('BB_NUMBER_THREADS')
|
||||
if bbnum and bbnum != self.config.get('BB_NUMBER_THREADS', ''):
|
||||
self.config['BB_NUMBER_THREADS'] = bbnum
|
||||
pmake = getString('PARALLEL_MAKE')
|
||||
if pmake and pmake != self.config.get('PARALLEL_MAKE', ''):
|
||||
self.config['PARALLEL_MAKE'] = pmake
|
||||
pclass = getString('PACKAGE_CLASSES')
|
||||
if pclass and pclass != self.config.get('PACKAGE_CLASSES', ''):
|
||||
self.config['PACKAGE_CLASSES'] = pclass
|
||||
fstypes = getString('IMAGE_FSTYPES')
|
||||
if fstypes and fstypes != self.config.get('IMAGE_FSTYPES', ''):
|
||||
self.config['IMAGE_FSTYPES'] = fstypes
|
||||
|
||||
# Values which aren't always set in the conf must be explicitly
|
||||
# loaded as empty values for save to work
|
||||
incompat = getString('INCOMPATIBLE_LICENSE')
|
||||
if incompat and incompat != self.config.get('INCOMPATIBLE_LICENSE', ''):
|
||||
self.config['INCOMPATIBLE_LICENSE'] = incompat
|
||||
else:
|
||||
self.config['INCOMPATIBLE_LICENSE'] = ""
|
||||
|
||||
# Non-standard, namespaces, variables for GUI preferences
|
||||
toolchain = getString('HOB_BUILD_TOOLCHAIN')
|
||||
if toolchain and toolchain != self.config.get('HOB_BUILD_TOOLCHAIN', ''):
|
||||
self.config['HOB_BUILD_TOOLCHAIN'] = toolchain
|
||||
header = getString('HOB_BUILD_TOOLCHAIN_HEADERS')
|
||||
if header and header != self.config.get('HOB_BUILD_TOOLCHAIN_HEADERS', ''):
|
||||
self.config['HOB_BUILD_TOOLCHAIN_HEADERS'] = header
|
||||
|
||||
self.orig_config = copy.deepcopy(self.config)
|
||||
|
||||
def setConfVar(self, var, val):
|
||||
self.config[var] = val
|
||||
|
||||
def getConfVar(self, var):
|
||||
if var in self.config:
|
||||
return self.config[var]
|
||||
else:
|
||||
return ""
|
||||
|
||||
def _loadLayerConf(self, path):
|
||||
self.bblayers = path
|
||||
self.enabled_layers = {}
|
||||
self.loaded_layers = {}
|
||||
data = bb.data.init()
|
||||
data = self._parse(self.bblayers, data)
|
||||
layers = (data.getVar('BBLAYERS', True) or "").split()
|
||||
for layer in layers:
|
||||
# TODO: we may be better off calling the layer by its
|
||||
# BBFILE_COLLECTIONS value?
|
||||
name = self._getLayerName(layer)
|
||||
self.loaded_layers[name] = layer
|
||||
|
||||
self.enabled_layers = copy.deepcopy(self.loaded_layers)
|
||||
self.emit("layers-loaded")
|
||||
|
||||
def _addConfigFile(self, path):
|
||||
conffiles = ["local.conf", "hob-pre.conf", "hob-post.conf"]
|
||||
pref, sep, filename = path.rpartition("/")
|
||||
|
||||
if filename == "hob-pre.conf":
|
||||
self.preconf = path
|
||||
|
||||
if filename == "hob-post.conf":
|
||||
self.postconf = path
|
||||
|
||||
if filename in conffiles:
|
||||
self._loadConf(path)
|
||||
elif filename == "bblayers.conf":
|
||||
self._loadLayerConf(path)
|
||||
|
||||
def _splitLayer(self, path):
|
||||
# we only care about the path up to /conf/layer.conf
|
||||
layerpath, conf, end = path.rpartition("/conf/")
|
||||
return layerpath
|
||||
|
||||
def _getLayerName(self, path):
|
||||
# Should this be the collection name?
|
||||
layerpath, sep, name = path.rpartition("/")
|
||||
return name
|
||||
|
||||
def disableLayer(self, layer):
|
||||
if layer in self.enabled_layers:
|
||||
del self.enabled_layers[layer]
|
||||
|
||||
def addLayerConf(self, confpath):
|
||||
layerpath = self._splitLayer(confpath)
|
||||
name = self._getLayerName(layerpath)
|
||||
|
||||
if not layerpath or not name:
|
||||
return None, None
|
||||
elif name not in self.enabled_layers:
|
||||
self.addLayer(name, layerpath)
|
||||
return name, layerpath
|
||||
else:
|
||||
return name, None
|
||||
|
||||
def addLayer(self, name, path):
|
||||
self.enabled_layers[name] = path
|
||||
|
||||
def _isLayerConfDirty(self):
|
||||
# if a different number of layers enabled to what was
|
||||
# loaded, definitely different
|
||||
if len(self.enabled_layers) != len(self.loaded_layers):
|
||||
return True
|
||||
|
||||
for layer in self.loaded_layers:
|
||||
# if layer loaded but no longer present, definitely dirty
|
||||
if layer not in self.enabled_layers:
|
||||
return True
|
||||
|
||||
for layer in self.enabled_layers:
|
||||
# if this layer wasn't present at load, definitely dirty
|
||||
if layer not in self.loaded_layers:
|
||||
return True
|
||||
# if this layers path has changed, definitely dirty
|
||||
if self.enabled_layers[layer] != self.loaded_layers[layer]:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _constructLayerEntry(self):
|
||||
"""
|
||||
Returns a string representing the new layer selection
|
||||
"""
|
||||
layers = self.enabled_layers.copy()
|
||||
# Construct BBLAYERS entry
|
||||
layer_entry = "BBLAYERS = \" \\\n"
|
||||
if 'meta' in layers:
|
||||
layer_entry = layer_entry + " %s \\\n" % layers['meta']
|
||||
del layers['meta']
|
||||
for layer in layers:
|
||||
layer_entry = layer_entry + " %s \\\n" % layers[layer]
|
||||
layer_entry = layer_entry + " \""
|
||||
|
||||
return "".join(layer_entry)
|
||||
|
||||
def writeConfFile(self, conffile, contents):
|
||||
"""
|
||||
Make a backup copy of conffile and write a new file in its stead with
|
||||
the lines in the contents list.
|
||||
"""
|
||||
# Create a backup of the conf file
|
||||
bkup = "%s~" % conffile
|
||||
os.rename(conffile, bkup)
|
||||
|
||||
# Write the contents list object to the conf file
|
||||
with open(conffile, "w") as new:
|
||||
new.write("".join(contents))
|
||||
|
||||
def updateConf(self, orig_lines, changed_values):
|
||||
new_config_lines = []
|
||||
for var in changed_values:
|
||||
# Convenience function for re.subn(). If the pattern matches
|
||||
# return a string which contains an assignment using the same
|
||||
# assignment operator as the old assignment.
|
||||
def replace_val(matchobj):
|
||||
var = matchobj.group(1) # config variable
|
||||
op = matchobj.group(2) # assignment operator
|
||||
val = changed_values[var] # new config value
|
||||
return "%s %s \"%s\"" % (var, op, val)
|
||||
|
||||
pattern = '^\s*(%s)\s*([+=?.]+)(.*)' % re.escape(var)
|
||||
p = re.compile(pattern)
|
||||
cnt = 0
|
||||
replaced = False
|
||||
|
||||
# Iterate over the local.conf lines and if they are a match
|
||||
# for the pattern comment out the line and append a new line
|
||||
# with the new VAR op "value" entry
|
||||
for line in orig_lines:
|
||||
new_line, replacements = p.subn(replace_val, line)
|
||||
if replacements:
|
||||
orig_lines[cnt] = "#%s" % line
|
||||
new_config_lines.append(new_line)
|
||||
replaced = True
|
||||
cnt = cnt + 1
|
||||
|
||||
if not replaced:
|
||||
new_config_lines.append("%s = \"%s\"\n" % (var, changed_values[var]))
|
||||
|
||||
# Add the modified variables
|
||||
orig_lines.extend(new_config_lines)
|
||||
return orig_lines
|
||||
|
||||
def writeConf(self):
|
||||
pre_vars = ["MACHINE", "SDKMACHINE", "DISTRO",
|
||||
"INCOMPATIBLE_LICENSE"]
|
||||
post_vars = ["BB_NUMBER_THREADS", "PARALLEL_MAKE", "PACKAGE_CLASSES",
|
||||
"IMAGE_FSTYPES", "HOB_BUILD_TOOLCHAIN",
|
||||
"HOB_BUILD_TOOLCHAIN_HEADERS"]
|
||||
pre_values = {}
|
||||
post_values = {}
|
||||
changed_values = {}
|
||||
pre_lines = None
|
||||
post_lines = None
|
||||
|
||||
for var in self.config:
|
||||
val = self.config[var]
|
||||
if self.orig_config.get(var, None) != val:
|
||||
changed_values[var] = val
|
||||
|
||||
if not len(changed_values):
|
||||
return
|
||||
|
||||
for var in changed_values:
|
||||
if var in pre_vars:
|
||||
pre_values[var] = changed_values[var]
|
||||
elif var in post_vars:
|
||||
post_values[var] = changed_values[var]
|
||||
|
||||
with open(self.preconf, 'r') as pre:
|
||||
pre_lines = pre.readlines()
|
||||
pre_lines = self.updateConf(pre_lines, pre_values)
|
||||
if len(pre_lines):
|
||||
self.writeConfFile(self.preconf, pre_lines)
|
||||
|
||||
with open(self.postconf, 'r') as post:
|
||||
post_lines = post.readlines()
|
||||
post_lines = self.updateConf(post_lines, post_values)
|
||||
if len(post_lines):
|
||||
self.writeConfFile(self.postconf, post_lines)
|
||||
|
||||
del self.orig_config
|
||||
self.orig_config = copy.deepcopy(self.config)
|
||||
|
||||
def insertTempBBPath(self, bbpath, bbfiles):
|
||||
# read the original conf into a list
|
||||
with open(self.postconf, 'r') as config:
|
||||
config_lines = config.readlines()
|
||||
|
||||
if bbpath:
|
||||
config_lines.append("BBPATH := \"${BBPATH}:%s\"\n" % bbpath)
|
||||
if bbfiles:
|
||||
config_lines.append("BBFILES := \"${BBFILES} %s\"\n" % bbfiles)
|
||||
|
||||
self.writeConfFile(self.postconf, config_lines)
|
||||
|
||||
def writeLayerConf(self):
|
||||
# If we've not added/removed new layers don't write
|
||||
if not self._isLayerConfDirty():
|
||||
return
|
||||
|
||||
# This pattern should find the existing BBLAYERS
|
||||
pattern = 'BBLAYERS\s=\s\".*\"'
|
||||
|
||||
replacement = self._constructLayerEntry()
|
||||
|
||||
with open(self.bblayers, "r") as f:
|
||||
contents = f.read()
|
||||
p = re.compile(pattern, re.DOTALL)
|
||||
new = p.sub(replacement, contents)
|
||||
|
||||
self.writeConfFile(self.bblayers, new)
|
||||
|
||||
# set loaded_layers for dirtiness tracking
|
||||
self.loaded_layers = copy.deepcopy(self.enabled_layers)
|
||||
|
||||
self.emit("layers-changed")
|
||||
|
||||
def configFound(self, handler, path):
|
||||
self._addConfigFile(path)
|
||||
|
||||
def loadConfig(self, path):
|
||||
self._addConfigFile(path)
|
||||
@@ -1,9 +1,11 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
# Copyright (C) 2011-2012 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
@@ -18,21 +20,33 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
import gobject
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import shlex
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import HobWidget
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
|
||||
"""
|
||||
The following are convenience classes for implementing GNOME HIG compliant
|
||||
BitBake GUI's
|
||||
In summary: spacing = 12px, border-width = 6px
|
||||
"""
|
||||
|
||||
#
|
||||
# CrumbsDialog
|
||||
#
|
||||
class CrumbsDialog(gtk.Dialog):
|
||||
"""
|
||||
A GNOME HIG compliant dialog widget.
|
||||
Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons
|
||||
"""
|
||||
def __init__(self, parent=None, label="", icon=gtk.STOCK_INFO):
|
||||
gtk.Dialog.__init__(self, "", parent, gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
super(CrumbsDialog, self).__init__("", parent, gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
|
||||
#self.set_property("has-separator", False) # note: deprecated in 2.22
|
||||
|
||||
@@ -59,3 +73,572 @@ class CrumbsDialog(gtk.Dialog):
|
||||
self.label.set_property("yalign", 0.00)
|
||||
self.label.show()
|
||||
first_row.add(self.label)
|
||||
|
||||
#
|
||||
# Brought-in-by Dialog
|
||||
#
|
||||
class BinbDialog(gtk.Dialog):
|
||||
"""
|
||||
A dialog widget to show "brought in by" info when a recipe/package is clicked.
|
||||
"""
|
||||
|
||||
def __init__(self, title, content, parent=None):
|
||||
super(BinbDialog, self).__init__(title, parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, None)
|
||||
|
||||
self.set_position(gtk.WIN_POS_MOUSE)
|
||||
self.set_resizable(False)
|
||||
self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.DARK))
|
||||
|
||||
hbox = gtk.HBox(False, 0)
|
||||
self.vbox.pack_start(hbox, expand=False, fill=False, padding=10)
|
||||
|
||||
label = gtk.Label(content)
|
||||
label.set_alignment(0, 0)
|
||||
label.set_line_wrap(True)
|
||||
label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.WHITE))
|
||||
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=10)
|
||||
self.vbox.show_all()
|
||||
|
||||
#
|
||||
# AdvancedSettings Dialog
|
||||
#
|
||||
class AdvancedSettingDialog (gtk.Dialog):
|
||||
|
||||
def __init__(self, title, configuration, all_image_types,
|
||||
all_package_formats, all_distros, all_sdk_machines,
|
||||
max_threads, split_model, parent, flags, buttons):
|
||||
super(AdvancedSettingDialog, self).__init__(title, parent, flags, buttons)
|
||||
|
||||
# class members from other objects
|
||||
# bitbake settings from Builder.Configuration
|
||||
self.configuration = configuration
|
||||
self.image_types = all_image_types
|
||||
self.all_package_formats = all_package_formats
|
||||
self.all_distros = all_distros
|
||||
self.all_sdk_machines = all_sdk_machines
|
||||
self.max_threads = max_threads
|
||||
self.split_model = split_model
|
||||
|
||||
# class members for internal use
|
||||
self.pkgfmt_store = None
|
||||
self.distro_combo = None
|
||||
self.dldir_text = None
|
||||
self.sstatedir_text = None
|
||||
self.sstatemirror_text = None
|
||||
self.bb_spinner = None
|
||||
self.pmake_spinner = None
|
||||
self.rootfs_size_spinner = None
|
||||
self.extra_size_spinner = None
|
||||
self.gplv3_checkbox = None
|
||||
self.toolchain_checkbox = None
|
||||
self.setting_store = None
|
||||
self.image_types_checkbuttons = {}
|
||||
|
||||
self.variables = {}
|
||||
self.variables["PACKAGE_FORMAT"] = self.configuration.curr_package_format
|
||||
self.variables["INCOMPATIBLE_LICENSE"] = self.configuration.incompat_license
|
||||
self.variables["IMAGE_FSTYPES"] = self.configuration.image_fstypes
|
||||
self.md5 = hashlib.md5(str(sorted(self.variables.items()))).hexdigest()
|
||||
self.settings_changed = False
|
||||
|
||||
# create visual elements on the dialog
|
||||
self.create_visual_elements()
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.set_size_request(500, 500)
|
||||
|
||||
self.nb = gtk.Notebook()
|
||||
self.nb.set_show_tabs(True)
|
||||
self.nb.append_page(self.create_image_types_page(), gtk.Label("Image types"))
|
||||
self.nb.append_page(self.create_output_page(), gtk.Label("Output"))
|
||||
self.nb.append_page(self.create_build_environment_page(), gtk.Label("Build environment"))
|
||||
self.nb.append_page(self.create_others_page(), gtk.Label("Others"))
|
||||
self.nb.set_current_page(0)
|
||||
self.vbox.pack_start(self.nb, expand=True, fill=True)
|
||||
self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def create_image_types_page(self):
|
||||
advanced_vbox = gtk.VBox(False, 15)
|
||||
advanced_vbox.set_border_width(20)
|
||||
|
||||
rows = (len(self.image_types)+1)/2
|
||||
table = gtk.Table(rows + 1, 10, True)
|
||||
advanced_vbox.pack_start(table, expand=False, fill=False)
|
||||
|
||||
tooltip = "Select image file system types that will be used."
|
||||
image = gtk.Image()
|
||||
image.show()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Select image types:</span>")
|
||||
table.attach(label, 0, 9, 0, 1)
|
||||
table.attach(image, 9, 10, 0, 1)
|
||||
|
||||
i = 1
|
||||
j = 1
|
||||
for image_type in self.image_types:
|
||||
self.image_types_checkbuttons[image_type] = gtk.CheckButton(image_type)
|
||||
self.image_types_checkbuttons[image_type].set_tooltip_text("Build an %s image" % image_type)
|
||||
table.attach(self.image_types_checkbuttons[image_type], j, j + 4, i, i + 1)
|
||||
if image_type in self.configuration.image_fstypes:
|
||||
self.image_types_checkbuttons[image_type].set_active(True)
|
||||
i += 1
|
||||
if i > rows:
|
||||
i = 1
|
||||
j = j + 4
|
||||
|
||||
return advanced_vbox
|
||||
|
||||
def create_output_page(self):
|
||||
advanced_vbox = gtk.VBox(False, 15)
|
||||
advanced_vbox.set_border_width(20)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Packaging Format:</span>")
|
||||
tooltip = "Select package formats that will be used. "
|
||||
tooltip += "The first format will be used for final image"
|
||||
pkgfmt_widget, self.pkgfmt_store = HobWidget.gen_pkgfmt_widget(self.configuration.curr_package_format, self.all_package_formats, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(pkgfmt_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Image Rootfs Size: (MB)</span>")
|
||||
tooltip = "Sets the size of your target image.\nThis is the basic size of your target image, unless your selected package size exceeds this value, or you set value to \"Image Extra Size\"."
|
||||
rootfs_size_widget, self.rootfs_size_spinner = HobWidget.gen_spinner_widget(int(self.configuration.image_rootfs_size*1.0/1024), 0, 1024, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(rootfs_size_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Image Extra Size: (MB)</span>")
|
||||
tooltip = "Sets the extra free space of your target image.\nDefaultly, system will reserve 30% of your image size as your free space. If your image contains zypper, it will bring in 50MB more space. The maximum free space is 1024MB."
|
||||
extra_size_widget, self.extra_size_spinner = HobWidget.gen_spinner_widget(int(self.configuration.image_extra_size*1.0/1024), 0, 1024, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(extra_size_widget, expand=False, fill=False)
|
||||
|
||||
self.gplv3_checkbox = gtk.CheckButton("Exclude GPLv3 packages")
|
||||
self.gplv3_checkbox.set_tooltip_text("Check this box to prevent GPLv3 packages from being included in your image")
|
||||
if "GPLv3" in self.configuration.incompat_license.split():
|
||||
self.gplv3_checkbox.set_active(True)
|
||||
else:
|
||||
self.gplv3_checkbox.set_active(False)
|
||||
advanced_vbox.pack_start(self.gplv3_checkbox, expand=False, fill=False)
|
||||
|
||||
sub_hbox = gtk.HBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_hbox, expand=False, fill=False)
|
||||
self.toolchain_checkbox = gtk.CheckButton("Build Toolchain")
|
||||
self.toolchain_checkbox.set_tooltip_text("Check this box to build the related toolchain with your image")
|
||||
self.toolchain_checkbox.set_active(self.configuration.toolchain_build)
|
||||
sub_hbox.pack_start(self.toolchain_checkbox, expand=False, fill=False)
|
||||
|
||||
tooltip = "This is the Host platform you would like to run the toolchain"
|
||||
sdk_machine_widget, self.sdk_machine_combo = HobWidget.gen_combo_widget(self.configuration.curr_sdk_machine, self.all_sdk_machines, tooltip)
|
||||
sub_hbox.pack_start(sdk_machine_widget, expand=False, fill=False)
|
||||
|
||||
return advanced_vbox
|
||||
|
||||
def create_build_environment_page(self):
|
||||
advanced_vbox = gtk.VBox(False, 15)
|
||||
advanced_vbox.set_border_width(20)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Select Distro:</span>")
|
||||
tooltip = "This is the Yocto distribution you would like to use"
|
||||
distro_widget, self.distro_combo = HobWidget.gen_combo_widget(self.configuration.curr_distro, self.all_distros, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(distro_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">BB_NUMBER_THREADS:</span>")
|
||||
tooltip = "Sets the number of threads that bitbake tasks can run simultaneously"
|
||||
bbthread_widget, self.bb_spinner = HobWidget.gen_spinner_widget(self.configuration.bbthread, 1, self.max_threads, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(bbthread_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">PARALLEL_MAKE:</span>")
|
||||
tooltip = "Sets the make parallism, as known as 'make -j'"
|
||||
pmake_widget, self.pmake_spinner = HobWidget.gen_spinner_widget(self.configuration.pmake, 1, self.max_threads, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(pmake_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Set Download Directory:</span>")
|
||||
tooltip = "Select a folder that caches the upstream project source code"
|
||||
dldir_widget, self.dldir_text = HobWidget.gen_entry_widget(self.split_model, self.configuration.dldir, self, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(dldir_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Select SSTATE Directory:</span>")
|
||||
tooltip = "Select a folder that caches your prebuilt results"
|
||||
sstatedir_widget, self.sstatedir_text = HobWidget.gen_entry_widget(self.split_model, self.configuration.sstatedir, self, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(sstatedir_widget, expand=False, fill=False)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Select SSTATE Mirror:</span>")
|
||||
tooltip = "Select the prebuilt mirror that will fasten your build speed"
|
||||
sstatemirror_widget, self.sstatemirror_text = HobWidget.gen_entry_widget(self.split_model, self.configuration.sstatemirror, self, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(sstatemirror_widget, expand=False, fill=False)
|
||||
|
||||
return advanced_vbox
|
||||
|
||||
def create_others_page(self):
|
||||
advanced_vbox = gtk.VBox(False, 15)
|
||||
advanced_vbox.set_border_width(20)
|
||||
|
||||
sub_vbox = gtk.VBox(False, 5)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=True, fill=True)
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\">Add your own variables:</span>")
|
||||
tooltip = "This is the key/value pair for your extra settings"
|
||||
setting_widget, self.setting_store = HobWidget.gen_editable_settings(self.configuration.extra_setting, tooltip)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(setting_widget, expand=True, fill=True)
|
||||
|
||||
return advanced_vbox
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
self.variables = {}
|
||||
|
||||
self.configuration.curr_package_format = ""
|
||||
it = self.pkgfmt_store.get_iter_first()
|
||||
while it:
|
||||
value = self.pkgfmt_store.get_value(it, 2)
|
||||
if value:
|
||||
self.configuration.curr_package_format += (self.pkgfmt_store.get_value(it, 1) + " ")
|
||||
it = self.pkgfmt_store.iter_next(it)
|
||||
self.configuration.curr_package_format = self.configuration.curr_package_format.strip()
|
||||
self.variables["PACKAGE_FORMAT"] = self.configuration.curr_package_format
|
||||
|
||||
self.configuration.curr_distro = self.distro_combo.get_active_text()
|
||||
self.configuration.dldir = self.dldir_text.get_text()
|
||||
self.configuration.sstatedir = self.sstatedir_text.get_text()
|
||||
self.configuration.sstatemirror = self.sstatemirror_text.get_text()
|
||||
self.configuration.bbthread = self.bb_spinner.get_value_as_int()
|
||||
self.configuration.pmake = self.pmake_spinner.get_value_as_int()
|
||||
self.configuration.image_rootfs_size = self.rootfs_size_spinner.get_value_as_int() * 1024
|
||||
self.configuration.image_extra_size = self.extra_size_spinner.get_value_as_int() * 1024
|
||||
|
||||
self.configuration.image_fstypes = []
|
||||
for image_type in self.image_types:
|
||||
if self.image_types_checkbuttons[image_type].get_active():
|
||||
self.configuration.image_fstypes.append(image_type)
|
||||
self.variables["IMAGE_FSTYPES"] = self.configuration.image_fstypes
|
||||
|
||||
if self.gplv3_checkbox.get_active():
|
||||
if "GPLv3" not in self.configuration.incompat_license.split():
|
||||
self.configuration.incompat_license += " GPLv3"
|
||||
else:
|
||||
if "GPLv3" in self.configuration.incompat_license.split():
|
||||
self.configuration.incompat_license = self.configuration.incompat_license.split().remove("GPLv3")
|
||||
self.configuration.incompat_license = " ".join(self.configuration.incompat_license or [])
|
||||
self.configuration.incompat_license = self.configuration.incompat_license.strip()
|
||||
self.variables["INCOMPATIBLE_LICENSE"] = self.configuration.incompat_license
|
||||
|
||||
self.configuration.toolchain_build = self.toolchain_checkbox.get_active()
|
||||
|
||||
self.configuration.extra_setting = {}
|
||||
it = self.setting_store.get_iter_first()
|
||||
while it:
|
||||
key = self.setting_store.get_value(it, 0)
|
||||
value = self.setting_store.get_value(it, 1)
|
||||
self.configuration.extra_setting[key] = value
|
||||
self.variables[key] = value
|
||||
it = self.setting_store.iter_next(it)
|
||||
|
||||
md5 = hashlib.md5(str(sorted(self.variables.items()))).hexdigest()
|
||||
self.settings_changed = (self.md5 != md5)
|
||||
|
||||
#
|
||||
# DeployImageDialog
|
||||
#
|
||||
class DeployImageDialog (gtk.Dialog):
|
||||
|
||||
__dummy_usb__ = "--select a usb drive--"
|
||||
|
||||
def __init__(self, title, image_path, parent, flags, buttons):
|
||||
super(DeployImageDialog, self).__init__(title, parent, flags, buttons)
|
||||
|
||||
self.image_path = image_path
|
||||
|
||||
self.create_visual_elements()
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.set_border_width(20)
|
||||
self.set_default_size(500, 250)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
markup = "<span font_desc='12'>The image to be written into usb drive:</span>"
|
||||
label.set_markup(markup)
|
||||
self.vbox.pack_start(label, expand=False, fill=False, padding=2)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
tv = gtk.TextView()
|
||||
tv.set_editable(False)
|
||||
tv.set_wrap_mode(gtk.WRAP_WORD)
|
||||
tv.set_cursor_visible(False)
|
||||
buf = gtk.TextBuffer()
|
||||
buf.set_text(self.image_path)
|
||||
tv.set_buffer(buf)
|
||||
scroll.add(tv)
|
||||
self.vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
self.usb_desc = gtk.Label()
|
||||
self.usb_desc.set_alignment(0.0, 0.5)
|
||||
markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>"
|
||||
self.usb_desc.set_markup(markup)
|
||||
|
||||
self.usb_combo = gtk.combo_box_new_text()
|
||||
self.usb_combo.connect("changed", self.usb_combo_changed_cb)
|
||||
model = self.usb_combo.get_model()
|
||||
model.clear()
|
||||
self.usb_combo.append_text(self.__dummy_usb__)
|
||||
for usb in self.find_all_usb_devices():
|
||||
self.usb_combo.append_text("/dev/" + usb)
|
||||
self.usb_combo.set_active(0)
|
||||
self.vbox.pack_start(self.usb_combo, expand=True, fill=True)
|
||||
self.vbox.pack_start(self.usb_desc, expand=False, fill=False, padding=2)
|
||||
|
||||
self.progress_bar = HobProgressBar()
|
||||
self.vbox.pack_start(self.progress_bar, expand=False, fill=False)
|
||||
separator = gtk.HSeparator()
|
||||
self.vbox.pack_start(separator, expand=False, fill=True, padding=10)
|
||||
|
||||
self.vbox.show_all()
|
||||
self.progress_bar.hide()
|
||||
|
||||
def popen_read(self, cmd):
|
||||
return os.popen("%s 2>/dev/null" % cmd).read().strip()
|
||||
|
||||
def find_all_usb_devices(self):
|
||||
usb_devs = [ os.readlink(u)
|
||||
for u in self.popen_read('ls /dev/disk/by-id/usb*').split()
|
||||
if not re.search(r'part\d+', u) ]
|
||||
return [ '%s' % u[u.rfind('/')+1:] for u in usb_devs ]
|
||||
|
||||
def get_usb_info(self, dev):
|
||||
return "%s %s" % \
|
||||
(self.popen_read('cat /sys/class/block/%s/device/vendor' % dev),
|
||||
self.popen_read('cat /sys/class/block/%s/device/model' % dev))
|
||||
|
||||
def usb_combo_changed_cb(self, usb_combo):
|
||||
combo_item = self.usb_combo.get_active_text()
|
||||
if not combo_item or combo_item == self.__dummy_usb__:
|
||||
markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>"
|
||||
self.usb_desc.set_markup(markup)
|
||||
else:
|
||||
markup = "<span font_desc='12'>" + self.get_usb_info(combo_item.lstrip("/dev/")) + "</span>"
|
||||
self.usb_desc.set_markup(markup)
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
if response_id == gtk.RESPONSE_YES:
|
||||
combo_item = self.usb_combo.get_active_text()
|
||||
if combo_item and combo_item != self.__dummy_usb__:
|
||||
cmdline = "/usr/bin/xterm -e "
|
||||
cmdline += "\"sudo dd if=" + self.image_path + " of=" + combo_item + "; bash\""
|
||||
subprocess.Popen(args=shlex.split(cmdline))
|
||||
|
||||
def update_progress_bar(self, title, fraction, status=True):
|
||||
self.progress_bar.update(fraction)
|
||||
self.progress_bar.set_title(title)
|
||||
self.progress_bar.set_rcstyle(status)
|
||||
|
||||
def write_file(self, ifile, ofile):
|
||||
self.progress_bar.reset()
|
||||
self.progress_bar.show()
|
||||
|
||||
f_from = os.open(ifile, os.O_RDONLY)
|
||||
f_to = os.open(ofile, os.O_WRONLY)
|
||||
|
||||
total_size = os.stat(ifile).st_size
|
||||
written_size = 0
|
||||
|
||||
while True:
|
||||
buf = os.read(f_from, 1024*1024)
|
||||
if not buf:
|
||||
break
|
||||
os.write(f_to, buf)
|
||||
written_size += 1024*1024
|
||||
self.update_progress_bar("Writing to usb:", written_size * 1.0/total_size)
|
||||
|
||||
self.update_progress_bar("Writing completed:", 1.0)
|
||||
os.close(f_from)
|
||||
os.close(f_to)
|
||||
self.progress_bar.hide()
|
||||
#
|
||||
# LayerSelectionDialog
|
||||
#
|
||||
class LayerSelectionDialog (gtk.Dialog):
|
||||
|
||||
def __init__(self, title, layers, all_layers, split_model,
|
||||
parent, flags, buttons):
|
||||
super(LayerSelectionDialog, self).__init__(title, parent, flags, buttons)
|
||||
|
||||
# class members from other objects
|
||||
self.layers = layers
|
||||
self.all_layers = all_layers
|
||||
self.split_model = split_model
|
||||
self.layers_changed = False
|
||||
|
||||
# class members for internal use
|
||||
self.layer_store = None
|
||||
|
||||
# create visual elements on the dialog
|
||||
self.create_visual_elements()
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.set_border_width(20)
|
||||
self.set_default_size(400, 250)
|
||||
|
||||
hbox_top = gtk.HBox()
|
||||
self.set_border_width(12)
|
||||
self.vbox.pack_start(hbox_top, expand=False, fill=False)
|
||||
|
||||
if self.split_model:
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\" font_desc='12'>Select Layers:</span>\n(Available layers under '${COREBASE}/layers/' directory)")
|
||||
else:
|
||||
label = HobWidget.gen_label_widget("<span weight=\"bold\" font_desc='12'>Select Layers:</span>")
|
||||
hbox_top.pack_start(label, expand=False, fill=False)
|
||||
|
||||
tooltip = "Layer is a collection of bb files and conf files"
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
hbox_top.pack_end(image, expand=False, fill=False)
|
||||
|
||||
layer_widget, self.layer_store = HobWidget.gen_layer_widget(self.split_model, self.layers, self.all_layers, self, None)
|
||||
|
||||
self.vbox.pack_start(layer_widget, expand=True, fill=True)
|
||||
|
||||
separator = gtk.HSeparator()
|
||||
self.vbox.pack_start(separator, False, True, 5)
|
||||
separator.show()
|
||||
|
||||
hbox_button = gtk.HBox()
|
||||
self.vbox.pack_end(hbox_button, expand=False, fill=False)
|
||||
hbox_button.show()
|
||||
|
||||
label = HobWidget.gen_label_widget("<i>'meta' is Core layer for Yocto images</i>\n"
|
||||
"<span weight=\"bold\">Please do not remove it</span>")
|
||||
hbox_button.pack_start(label, expand=False, fill=False)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
model = self.layer_store
|
||||
it = model.get_iter_first()
|
||||
layers = []
|
||||
while it:
|
||||
if self.split_model:
|
||||
inc = model.get_value(it, 1)
|
||||
if inc:
|
||||
layers.append(model.get_value(it, 0))
|
||||
else:
|
||||
layers.append(model.get_value(it, 0))
|
||||
it = model.iter_next(it)
|
||||
|
||||
self.layers_changed = (self.layers != layers)
|
||||
self.layers = layers
|
||||
|
||||
class ImageSelectionDialog (gtk.Dialog):
|
||||
|
||||
def __init__(self, image_folder, image_types, title, parent, flags, buttons):
|
||||
super(ImageSelectionDialog, self).__init__(title, parent, flags, buttons)
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
self.image_folder = image_folder
|
||||
self.image_types = image_types
|
||||
self.image_names = []
|
||||
|
||||
# create visual elements on the dialog
|
||||
self.create_visual_elements()
|
||||
|
||||
self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
|
||||
self.fill_image_store()
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.set_border_width(20)
|
||||
self.set_default_size(600, 300)
|
||||
self.vbox.set_spacing(10)
|
||||
|
||||
hbox = gtk.HBox(False, 10)
|
||||
self.vbox.pack_start(hbox, expand=False, fill=False)
|
||||
|
||||
entry = gtk.Entry()
|
||||
entry.set_text(self.image_folder)
|
||||
table = gtk.Table(1, 10, True)
|
||||
table.set_size_request(560, -1)
|
||||
hbox.pack_start(table, expand=False, fill=False)
|
||||
table.attach(entry, 0, 9, 0, 1)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON)
|
||||
open_button = gtk.Button()
|
||||
open_button.set_image(image)
|
||||
open_button.connect("clicked", self.select_path_cb, self, entry)
|
||||
table.attach(open_button, 9, 10, 0, 1)
|
||||
|
||||
imgtv_widget, self.imgsel_tv = HobWidget.gen_imgtv_widget(400, 160)
|
||||
self.vbox.pack_start(imgtv_widget, expand=True, fill=True)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def select_path_cb(self, action, parent, entry):
|
||||
dialog = gtk.FileChooserDialog("", parent,
|
||||
gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
(gtk.STOCK_OK, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
path = dialog.get_filename()
|
||||
entry.set_text(path)
|
||||
self.image_folder = path
|
||||
self.fill_image_store()
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def fill_image_store(self):
|
||||
self.image_store.clear()
|
||||
imageset = set()
|
||||
for root, dirs, files in os.walk(self.image_folder):
|
||||
for f in files:
|
||||
for image_type in self.image_types:
|
||||
if f.endswith('.' + image_type):
|
||||
imageset.add(f.rsplit('.' + image_type)[0])
|
||||
|
||||
for image in imageset:
|
||||
self.image_store.set(self.image_store.append(), 0, image, 1, False)
|
||||
|
||||
self.imgsel_tv.set_model(self.image_store)
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
self.image_names = []
|
||||
if response_id == gtk.RESPONSE_YES:
|
||||
iter = self.image_store.get_iter_first()
|
||||
while iter:
|
||||
path = self.image_store.get_path(iter)
|
||||
if self.image_store[path][1]:
|
||||
for root, dirs, files in os.walk(self.image_folder):
|
||||
for f in files:
|
||||
if f.startswith(self.image_store[path][0] + '.'):
|
||||
self.image_names.append(f)
|
||||
break
|
||||
iter = self.image_store.iter_next(iter)
|
||||
|
||||
35
bitbake/lib/bb/ui/crumbs/hobcolor.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
class HobColors:
|
||||
WHITE = "#ffffff"
|
||||
PALE_GREEN = "#aaffaa"
|
||||
ORANGE = "#ff7c24"
|
||||
PALE_RED = "#ffaaaa"
|
||||
GRAY = "#aaaaaa"
|
||||
LIGHT_GRAY = "#dddddd"
|
||||
DARK = "#3c3b37"
|
||||
BLACK = "#000000"
|
||||
LIGHT_ORANGE = "#f7a787"
|
||||
|
||||
OK = WHITE
|
||||
RUNNING = PALE_GREEN
|
||||
WARNING = ORANGE
|
||||
ERROR = PALE_RED
|
||||
@@ -4,6 +4,7 @@
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
@@ -20,10 +21,7 @@
|
||||
|
||||
import gobject
|
||||
import logging
|
||||
import tempfile
|
||||
import datetime
|
||||
|
||||
progress_total = 0
|
||||
from bb.ui.crumbs.runningbuild import RunningBuild
|
||||
|
||||
class HobHandler(gobject.GObject):
|
||||
|
||||
@@ -31,147 +29,176 @@ class HobHandler(gobject.GObject):
|
||||
This object does BitBake event handling for the hob gui.
|
||||
"""
|
||||
__gsignals__ = {
|
||||
"machines-updated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"sdk-machines-updated": (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"distros-updated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"package-formats-found" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"config-found" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING,)),
|
||||
"generating-data" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"data-generated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"fatal-error" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,)),
|
||||
"command-failed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING,)),
|
||||
"reload-triggered" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,)),
|
||||
"layers-updated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"package-formats-updated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"config-updated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,)),
|
||||
"command-succeeded" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_INT,)),
|
||||
"command-failed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING,)),
|
||||
"generating-data" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"data-generated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"parsing-started" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"parsing" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
"parsing-completed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
}
|
||||
|
||||
(CFG_PATH_LOCAL, CFG_PATH_PRE, CFG_PATH_POST, CFG_PATH_LAYERS, CFG_FILES_DISTRO, CFG_FILES_MACH, CFG_FILES_SDK, FILES_MATCH_CLASS, GENERATE_TGTS, REPARSE_FILES, BUILD_IMAGE) = range(11)
|
||||
(CFG_AVAIL_LAYERS, CFG_PATH_LAYERS, CFG_FILES_DISTRO, CFG_FILES_MACH, CFG_FILES_SDKMACH, FILES_MATCH_CLASS, PARSE_CONFIG, PARSE_BBFILES, GENERATE_TGTS, GENERATE_PACKAGEINFO, BUILD_TARGET_RECIPES, BUILD_TARGET_IMAGE, CMD_END) = range(13)
|
||||
(LAYERS_REFRESH, GENERATE_RECIPES, GENERATE_PACKAGES, GENERATE_IMAGE, POPULATE_PACKAGEINFO) = range(5)
|
||||
|
||||
def __init__(self, taskmodel, server):
|
||||
gobject.GObject.__init__(self)
|
||||
def __init__(self, server, server_addr, client_addr, recipe_model, package_model):
|
||||
super(HobHandler, self).__init__()
|
||||
|
||||
self.current_command = None
|
||||
self.building = False
|
||||
self.build_toolchain = False
|
||||
self.build_toolchain_headers = False
|
||||
self.build = RunningBuild(sequential=True)
|
||||
|
||||
self.recipe_model = recipe_model
|
||||
self.package_model = package_model
|
||||
|
||||
self.commands_async = []
|
||||
self.generating = False
|
||||
self.build_queue = []
|
||||
self.current_phase = None
|
||||
self.bbpath_ok = False
|
||||
self.bbfiles_ok = False
|
||||
self.build_type = "image"
|
||||
self.image_dir = os.path.join(tempfile.gettempdir(), 'hob-images')
|
||||
self.building = False
|
||||
self.recipe_queue = []
|
||||
self.package_queue = []
|
||||
|
||||
self.model = taskmodel
|
||||
self.server = server
|
||||
self.error_msg = ""
|
||||
self.initcmd = None
|
||||
|
||||
deploy_dir = self.server.runCommand(["getVariable", "DEPLOY_DIR"])
|
||||
self.image_out_dir = os.path.join(deploy_dir, "images")
|
||||
self.image_output_types = self.server.runCommand(["getVariable", "IMAGE_FSTYPES"]).split(" ")
|
||||
self.bbpath = self.server.runCommand(["getVariable", "BBPATH"])
|
||||
self.bbfiles = self.server.runCommand(["getVariable", "BBFILES"])
|
||||
self.split_model = False
|
||||
if server_addr and client_addr:
|
||||
self.split_model = (server_addr != client_addr)
|
||||
self.reset_server() # reset server if server was found just now
|
||||
self.server_addr = server_addr
|
||||
|
||||
def run_next_command(self):
|
||||
if self.current_command and not self.generating:
|
||||
def kick(self):
|
||||
import xmlrpclib
|
||||
try:
|
||||
# kick the while thing off
|
||||
if self.split_model:
|
||||
self.commands_async.append(self.CFG_AVAIL_LAYERS)
|
||||
else:
|
||||
self.commands_async.append(self.CFG_PATH_LAYERS)
|
||||
self.commands_async.append(self.CFG_FILES_DISTRO)
|
||||
self.commands_async.append(self.CFG_FILES_MACH)
|
||||
self.commands_async.append(self.CFG_FILES_SDKMACH)
|
||||
self.commands_async.append(self.FILES_MATCH_CLASS)
|
||||
self.run_next_command()
|
||||
return True
|
||||
except xmlrpclib.Fault as x:
|
||||
print("XMLRPC Fault getting commandline:\n %s" % x)
|
||||
return False
|
||||
|
||||
def set_busy(self):
|
||||
if not self.generating:
|
||||
self.emit("generating-data")
|
||||
self.generating = True
|
||||
|
||||
if self.current_command == self.CFG_PATH_LOCAL:
|
||||
self.current_command = self.CFG_PATH_PRE
|
||||
self.server.runCommand(["findConfigFilePath", "hob-pre.conf"])
|
||||
elif self.current_command == self.CFG_PATH_PRE:
|
||||
self.current_command = self.CFG_PATH_POST
|
||||
self.server.runCommand(["findConfigFilePath", "hob-post.conf"])
|
||||
elif self.current_command == self.CFG_PATH_POST:
|
||||
self.current_command = self.CFG_PATH_LAYERS
|
||||
def clear_busy(self):
|
||||
if self.generating:
|
||||
self.emit("data-generated")
|
||||
self.generating = False
|
||||
|
||||
def run_next_command(self, initcmd=None):
|
||||
if initcmd != None:
|
||||
self.initcmd = initcmd
|
||||
|
||||
if self.commands_async:
|
||||
self.set_busy()
|
||||
next_command = self.commands_async.pop(0)
|
||||
else:
|
||||
self.clear_busy()
|
||||
if self.initcmd != None:
|
||||
self.emit("command-succeeded", self.initcmd)
|
||||
return
|
||||
|
||||
if next_command == self.CFG_AVAIL_LAYERS:
|
||||
self.server.runCommand(["findCoreBaseFiles", "layers", "conf/layer.conf"])
|
||||
elif next_command == self.CFG_PATH_LAYERS:
|
||||
self.server.runCommand(["findConfigFilePath", "bblayers.conf"])
|
||||
elif self.current_command == self.CFG_PATH_LAYERS:
|
||||
self.current_command = self.CFG_FILES_DISTRO
|
||||
elif next_command == self.CFG_FILES_DISTRO:
|
||||
self.server.runCommand(["findConfigFiles", "DISTRO"])
|
||||
elif self.current_command == self.CFG_FILES_DISTRO:
|
||||
self.current_command = self.CFG_FILES_MACH
|
||||
elif next_command == self.CFG_FILES_MACH:
|
||||
self.server.runCommand(["findConfigFiles", "MACHINE"])
|
||||
elif self.current_command == self.CFG_FILES_MACH:
|
||||
self.current_command = self.CFG_FILES_SDK
|
||||
elif next_command == self.CFG_FILES_SDKMACH:
|
||||
self.server.runCommand(["findConfigFiles", "MACHINE-SDK"])
|
||||
elif self.current_command == self.CFG_FILES_SDK:
|
||||
self.current_command = self.FILES_MATCH_CLASS
|
||||
elif next_command == self.FILES_MATCH_CLASS:
|
||||
self.server.runCommand(["findFilesMatchingInDir", "rootfs_", "classes"])
|
||||
elif self.current_command == self.FILES_MATCH_CLASS:
|
||||
self.current_command = self.GENERATE_TGTS
|
||||
self.server.runCommand(["generateTargetsTree", "classes/image.bbclass"])
|
||||
elif self.current_command == self.GENERATE_TGTS:
|
||||
if self.generating:
|
||||
self.emit("data-generated")
|
||||
self.generating = False
|
||||
self.current_command = None
|
||||
elif self.current_command == self.REPARSE_FILES:
|
||||
if self.build_queue:
|
||||
self.current_command = self.BUILD_IMAGE
|
||||
else:
|
||||
self.current_command = self.CFG_PATH_LAYERS
|
||||
self.server.runCommand(["resetCooker"])
|
||||
self.server.runCommand(["reparseFiles"])
|
||||
elif self.current_command == self.BUILD_IMAGE:
|
||||
if self.generating:
|
||||
self.emit("data-generated")
|
||||
self.generating = False
|
||||
elif next_command == self.PARSE_CONFIG:
|
||||
self.server.runCommand(["parseConfigurationFiles", "", ""])
|
||||
elif next_command == self.PARSE_BBFILES:
|
||||
self.server.runCommand(["parseFiles"])
|
||||
elif next_command == self.GENERATE_TGTS:
|
||||
self.server.runCommand(["generateTargetsTree", "classes/image.bbclass", [], True])
|
||||
elif next_command == self.GENERATE_PACKAGEINFO:
|
||||
self.server.runCommand(["triggerEvent", "bb.event.RequestPackageInfo()"])
|
||||
elif next_command == self.BUILD_TARGET_RECIPES:
|
||||
self.clear_busy()
|
||||
self.building = True
|
||||
self.server.runCommand(["buildTargets", self.build_queue, "build"])
|
||||
self.build_queue = []
|
||||
self.current_command = None
|
||||
self.server.runCommand(["buildTargets", self.recipe_queue, "build"])
|
||||
self.recipe_queue = []
|
||||
elif next_command == self.BUILD_TARGET_IMAGE:
|
||||
self.clear_busy()
|
||||
self.building = True
|
||||
targets = ["hob-image"]
|
||||
self.server.runCommand(["setVariable", "LINGUAS_INSTALL", ""])
|
||||
self.server.runCommand(["setVariable", "PACKAGE_INSTALL", " ".join(self.package_queue)])
|
||||
if self.toolchain_build:
|
||||
pkgs = self.package_queue + [i+'-dev' for i in self.package_queue] + [i+'-dbg' for i in self.package_queue]
|
||||
self.server.runCommand(["setVariable", "TOOLCHAIN_TARGET_TASK", " ".join(pkgs)])
|
||||
targets.append("hob-toolchain")
|
||||
self.server.runCommand(["buildTargets", targets, "build"])
|
||||
|
||||
def handle_event(self, event, running_build, pbar):
|
||||
def handle_event(self, event):
|
||||
if not event:
|
||||
return
|
||||
return
|
||||
|
||||
# If we're running a build, use the RunningBuild event handler
|
||||
if self.building:
|
||||
self.current_phase = "building"
|
||||
running_build.handle_event(event)
|
||||
self.build.handle_event(event)
|
||||
|
||||
if isinstance(event, bb.event.PackageInfo):
|
||||
self.package_model.populate(event._pkginfolist)
|
||||
self.run_next_command()
|
||||
|
||||
elif(isinstance(event, logging.LogRecord)):
|
||||
if event.levelno >= logging.ERROR:
|
||||
self.error_msg += event.msg + '\n'
|
||||
|
||||
elif isinstance(event, bb.event.TargetsTreeGenerated):
|
||||
self.current_phase = "data generation"
|
||||
if event._model:
|
||||
self.model.populate(event._model)
|
||||
self.recipe_model.populate(event._model)
|
||||
elif isinstance(event, bb.event.CoreBaseFilesFound):
|
||||
self.current_phase = "configuration lookup"
|
||||
paths = event._paths
|
||||
self.emit('layers-updated', paths)
|
||||
elif isinstance(event, bb.event.ConfigFilesFound):
|
||||
self.current_phase = "configuration lookup"
|
||||
var = event._variable
|
||||
if var == "distro":
|
||||
distros = event._values
|
||||
distros.sort()
|
||||
self.emit("distros-updated", distros)
|
||||
elif var == "machine":
|
||||
machines = event._values
|
||||
machines.sort()
|
||||
self.emit("machines-updated", machines)
|
||||
elif var == "machine-sdk":
|
||||
sdk_machines = event._values
|
||||
sdk_machines.sort()
|
||||
self.emit("sdk-machines-updated", sdk_machines)
|
||||
values = event._values
|
||||
values.sort()
|
||||
self.emit("config-updated", var, values)
|
||||
elif isinstance(event, bb.event.ConfigFilePathFound):
|
||||
self.current_phase = "configuration lookup"
|
||||
path = event._path
|
||||
self.emit("config-found", path)
|
||||
elif isinstance(event, bb.event.FilesMatchingFound):
|
||||
self.current_phase = "configuration lookup"
|
||||
# FIXME: hard coding, should at least be a variable shared between
|
||||
@@ -183,48 +210,84 @@ class HobHandler(gobject.GObject):
|
||||
fs, sep, format = classname.rpartition("_")
|
||||
formats.append(format)
|
||||
formats.sort()
|
||||
self.emit("package-formats-found", formats)
|
||||
self.emit("package-formats-updated", formats)
|
||||
elif isinstance(event, bb.command.CommandCompleted):
|
||||
self.current_phase = None
|
||||
self.run_next_command()
|
||||
|
||||
elif isinstance(event, bb.event.NoProvider):
|
||||
if event._runtime:
|
||||
r = "R"
|
||||
else:
|
||||
r = ""
|
||||
if event._dependees:
|
||||
self.error_msg += " Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)" % (r, event._item, ", ".join(event._dependees), r)
|
||||
else:
|
||||
self.error_msg += " Nothing %sPROVIDES '%s'" % (r, event._item)
|
||||
if event._reasons:
|
||||
for reason in event._reasons:
|
||||
self.error_msg += " %s" % reason
|
||||
|
||||
self.commands_async = []
|
||||
self.emit("command-failed", self.error_msg)
|
||||
self.error_msg = ""
|
||||
|
||||
elif isinstance(event, bb.command.CommandFailed):
|
||||
self.emit("command-failed", event.error)
|
||||
elif isinstance(event, bb.event.CacheLoadStarted):
|
||||
self.current_phase = "cache loading"
|
||||
bb.ui.crumbs.hobeventhandler.progress_total = event.total
|
||||
pbar.set_text("Loading cache: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total))
|
||||
elif isinstance(event, bb.event.CacheLoadProgress):
|
||||
self.current_phase = "cache loading"
|
||||
pbar.set_text("Loading cache: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total))
|
||||
elif isinstance(event, bb.event.CacheLoadCompleted):
|
||||
self.current_phase = None
|
||||
pbar.set_text("Loading...")
|
||||
elif isinstance(event, bb.event.ParseStarted):
|
||||
self.current_phase = "recipe parsing"
|
||||
if event.total == 0:
|
||||
return
|
||||
bb.ui.crumbs.hobeventhandler.progress_total = event.total
|
||||
pbar.set_text("Processing recipes: %s/%s" % (0, bb.ui.crumbs.hobeventhandler.progress_total))
|
||||
elif isinstance(event, bb.event.ParseProgress):
|
||||
self.current_phase = "recipe parsing"
|
||||
pbar.set_text("Processing recipes: %s/%s" % (event.current, bb.ui.crumbs.hobeventhandler.progress_total))
|
||||
elif isinstance(event, bb.event.ParseCompleted):
|
||||
self.current_phase = None
|
||||
pbar.set_fraction(1.0)
|
||||
pbar.set_text("Loading...")
|
||||
elif isinstance(event, logging.LogRecord):
|
||||
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
|
||||
if event.levelno >= format.CRITICAL:
|
||||
self.emit("fatal-error", event.getMessage(), self.current_phase)
|
||||
self.commands_async = []
|
||||
if self.error_msg:
|
||||
self.emit("command-failed", self.error_msg)
|
||||
self.error_msg = ""
|
||||
elif isinstance(event, (bb.event.ParseStarted,
|
||||
bb.event.CacheLoadStarted,
|
||||
bb.event.TreeDataPreparationStarted,
|
||||
)):
|
||||
message = {}
|
||||
message["eventname"] = bb.event.getName(event)
|
||||
message["current"] = 0
|
||||
message["total"] = None
|
||||
message["title"] = "Parsing recipes: "
|
||||
self.emit("parsing-started", message)
|
||||
elif isinstance(event, (bb.event.ParseProgress,
|
||||
bb.event.CacheLoadProgress,
|
||||
bb.event.TreeDataPreparationProgress)):
|
||||
message = {}
|
||||
message["eventname"] = bb.event.getName(event)
|
||||
message["current"] = event.current
|
||||
message["total"] = event.total
|
||||
message["title"] = "Parsing recipes: "
|
||||
self.emit("parsing", message)
|
||||
elif isinstance(event, (bb.event.ParseCompleted,
|
||||
bb.event.CacheLoadCompleted,
|
||||
bb.event.TreeDataPreparationCompleted)):
|
||||
message = {}
|
||||
message["eventname"] = bb.event.getName(event)
|
||||
message["current"] = event.total
|
||||
message["total"] = event.total
|
||||
message["title"] = "Parsing recipes: "
|
||||
self.emit("parsing-completed", message)
|
||||
|
||||
return
|
||||
|
||||
def event_handle_idle_func (self, eventHandler, running_build, pbar):
|
||||
# Consume as many messages as we can in the time available to us
|
||||
event = eventHandler.getEvent()
|
||||
while event:
|
||||
self.handle_event(event, running_build, pbar)
|
||||
event = eventHandler.getEvent()
|
||||
return True
|
||||
def init_cooker(self):
|
||||
self.server.runCommand(["initCooker"])
|
||||
|
||||
def refresh_layers(self, bblayers):
|
||||
self.server.runCommand(["initCooker"])
|
||||
self.server.runCommand(["setVariable", "BBLAYERS", " ".join(bblayers)])
|
||||
self.commands_async.append(self.PARSE_CONFIG)
|
||||
self.commands_async.append(self.CFG_FILES_DISTRO)
|
||||
self.commands_async.append(self.CFG_FILES_MACH)
|
||||
self.commands_async.append(self.CFG_FILES_SDKMACH)
|
||||
self.commands_async.append(self.FILES_MATCH_CLASS)
|
||||
self.run_next_command(self.LAYERS_REFRESH)
|
||||
|
||||
def set_extra_inherit(self, bbclass):
|
||||
inherits = self.server.runCommand(["getVariable", "INHERIT"]) or ""
|
||||
inherits = inherits + " " + bbclass
|
||||
self.server.runCommand(["setVariable", "INHERIT", inherits])
|
||||
|
||||
def set_bblayers(self, bblayers):
|
||||
self.server.runCommand(["setVariable", "BBLAYERS", " ".join(bblayers)])
|
||||
|
||||
def set_machine(self, machine):
|
||||
self.server.runCommand(["setVariable", "MACHINE", machine])
|
||||
@@ -232,62 +295,78 @@ class HobHandler(gobject.GObject):
|
||||
def set_sdk_machine(self, sdk_machine):
|
||||
self.server.runCommand(["setVariable", "SDKMACHINE", sdk_machine])
|
||||
|
||||
def set_image_fstypes(self, image_fstypes):
|
||||
self.server.runCommand(["setVariable", "IMAGE_FSTYPES", " ".join(image_fstypes).lstrip(" ")])
|
||||
|
||||
def set_distro(self, distro):
|
||||
self.server.runCommand(["setVariable", "DISTRO", distro])
|
||||
|
||||
def set_package_format(self, format):
|
||||
self.server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_%s" % format])
|
||||
|
||||
def reload_data(self, config=None):
|
||||
img = self.model.selected_image
|
||||
selected_packages, _ = self.model.get_selected_packages()
|
||||
self.emit("reload-triggered", img, " ".join(selected_packages))
|
||||
self.current_command = self.REPARSE_FILES
|
||||
self.run_next_command()
|
||||
package_classes = ""
|
||||
for pkgfmt in format.split():
|
||||
package_classes += ("package_%s" % pkgfmt + " ")
|
||||
self.server.runCommand(["setVariable", "PACKAGE_CLASSES", package_classes])
|
||||
|
||||
def set_bbthreads(self, threads):
|
||||
self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", threads])
|
||||
|
||||
def set_pmake(self, threads):
|
||||
pmake = "-j %s" % threads
|
||||
self.server.runCommand(["setVariable", "BB_NUMBER_THREADS", pmake])
|
||||
self.server.runCommand(["setVariable", "PARALLEL_MAKE", pmake])
|
||||
|
||||
def build_targets(self, tgts, configurator, build_type="image"):
|
||||
self.build_type = build_type
|
||||
def set_dl_dir(self, directory):
|
||||
self.server.runCommand(["setVariable", "DL_DIR", directory])
|
||||
|
||||
def set_sstate_dir(self, directory):
|
||||
self.server.runCommand(["setVariable", "SSTATE_DIR", directory])
|
||||
|
||||
def set_sstate_mirror(self, url):
|
||||
self.server.runCommand(["setVariable", "SSTATE_MIRROR", url])
|
||||
|
||||
def set_extra_size(self, image_extra_size):
|
||||
self.server.runCommand(["setVariable", "IMAGE_ROOTFS_EXTRA_SPACE", str(image_extra_size)])
|
||||
|
||||
def set_rootfs_size(self, image_rootfs_size):
|
||||
self.server.runCommand(["setVariable", "IMAGE_ROOTFS_SIZE", str(image_rootfs_size)])
|
||||
|
||||
def set_incompatible_license(self, incompat_license):
|
||||
self.server.runCommand(["setVariable", "INCOMPATIBLE_LICENSE", incompat_license])
|
||||
|
||||
def set_extra_config(self, extra_setting):
|
||||
for key in extra_setting.keys():
|
||||
value = extra_setting[key]
|
||||
self.server.runCommand(["setVariable", key, value])
|
||||
|
||||
def request_package_info_async(self):
|
||||
self.commands_async.append(self.GENERATE_PACKAGEINFO)
|
||||
self.run_next_command(self.POPULATE_PACKAGEINFO)
|
||||
|
||||
def generate_recipes(self):
|
||||
self.commands_async.append(self.PARSE_CONFIG)
|
||||
self.commands_async.append(self.GENERATE_TGTS)
|
||||
self.run_next_command(self.GENERATE_RECIPES)
|
||||
|
||||
def generate_packages(self, tgts):
|
||||
targets = []
|
||||
nbbp = None
|
||||
nbbf = None
|
||||
targets.extend(tgts)
|
||||
if self.build_toolchain and self.build_toolchain_headers:
|
||||
targets.append("meta-toolchain-sdk")
|
||||
elif self.build_toolchain:
|
||||
targets.append("meta-toolchain")
|
||||
self.build_queue = targets
|
||||
self.recipe_queue = targets
|
||||
self.commands_async.append(self.PARSE_CONFIG)
|
||||
self.commands_async.append(self.PARSE_BBFILES)
|
||||
self.commands_async.append(self.BUILD_TARGET_RECIPES)
|
||||
self.run_next_command(self.GENERATE_PACKAGES)
|
||||
|
||||
if not self.bbpath_ok:
|
||||
if self.image_dir in self.bbpath.split(":"):
|
||||
self.bbpath_ok = True
|
||||
else:
|
||||
nbbp = self.image_dir
|
||||
def generate_image(self, tgts, toolchain_build=False):
|
||||
self.package_queue = tgts
|
||||
self.toolchain_build = toolchain_build
|
||||
self.commands_async.append(self.PARSE_CONFIG)
|
||||
self.commands_async.append(self.PARSE_BBFILES)
|
||||
self.commands_async.append(self.BUILD_TARGET_IMAGE)
|
||||
self.run_next_command(self.GENERATE_IMAGE)
|
||||
|
||||
if not self.bbfiles_ok:
|
||||
import re
|
||||
pattern = "%s/\*.bb" % self.image_dir
|
||||
|
||||
for files in self.bbfiles.split(" "):
|
||||
if re.match(pattern, files):
|
||||
self.bbfiles_ok = True
|
||||
|
||||
if not self.bbfiles_ok:
|
||||
nbbf = "%s/*.bb" % self.image_dir
|
||||
|
||||
if nbbp or nbbf:
|
||||
configurator.insertTempBBPath(nbbp, nbbf)
|
||||
self.bbpath_ok = True
|
||||
self.bbfiles_ok = True
|
||||
|
||||
self.current_command = self.REPARSE_FILES
|
||||
self.run_next_command()
|
||||
def build_failed_async(self):
|
||||
self.initcmd = None
|
||||
self.commands_async = []
|
||||
self.building = False
|
||||
|
||||
def cancel_build(self, force=False):
|
||||
if force:
|
||||
@@ -298,46 +377,83 @@ class HobHandler(gobject.GObject):
|
||||
# leave the workdir in a usable state
|
||||
self.server.runCommand(["stateShutdown"])
|
||||
|
||||
def set_incompatible_license(self, incompatible):
|
||||
self.server.runCommand(["setVariable", "INCOMPATIBLE_LICENSE", incompatible])
|
||||
def reset_server(self):
|
||||
self.server.runCommand(["resetCooker"])
|
||||
|
||||
def toggle_toolchain(self, enabled):
|
||||
if self.build_toolchain != enabled:
|
||||
self.build_toolchain = enabled
|
||||
def reset_build(self):
|
||||
self.build.reset()
|
||||
|
||||
def toggle_toolchain_headers(self, enabled):
|
||||
if self.build_toolchain_headers != enabled:
|
||||
self.build_toolchain_headers = enabled
|
||||
def get_parameters(self):
|
||||
# retrieve the parameters from bitbake
|
||||
params = {}
|
||||
params["core_base"] = self.server.runCommand(["getVariable", "COREBASE"]) or ""
|
||||
hob_layer = params["core_base"] + "/meta-hob"
|
||||
params["layer"] = (self.server.runCommand(["getVariable", "BBLAYERS"]) or "") + " " + hob_layer
|
||||
params["dldir"] = self.server.runCommand(["getVariable", "DL_DIR"]) or ""
|
||||
params["machine"] = self.server.runCommand(["getVariable", "MACHINE"]) or ""
|
||||
params["distro"] = self.server.runCommand(["getVariable", "DISTRO"]) or "defaultsetup"
|
||||
params["pclass"] = self.server.runCommand(["getVariable", "PACKAGE_CLASSES"]) or ""
|
||||
params["sstatedir"] = self.server.runCommand(["getVariable", "SSTATE_DIR"]) or ""
|
||||
params["sstatemirror"] = self.server.runCommand(["getVariable", "SSTATE_MIRROR"]) or ""
|
||||
|
||||
def set_fstypes(self, fstypes):
|
||||
self.server.runCommand(["setVariable", "IMAGE_FSTYPES", fstypes])
|
||||
num_threads = self.server.runCommand(["getCpuCount"])
|
||||
if not num_threads:
|
||||
num_threads = 1
|
||||
max_threads = 65536
|
||||
else:
|
||||
num_threads = int(num_threads)
|
||||
max_threads = 16 * num_threads
|
||||
params["max_threads"] = max_threads
|
||||
|
||||
def add_image_output_type(self, output_type):
|
||||
if output_type not in self.image_output_types:
|
||||
self.image_output_types.append(output_type)
|
||||
fstypes = " ".join(self.image_output_types).lstrip(" ")
|
||||
self.set_fstypes(fstypes)
|
||||
return self.image_output_types
|
||||
bbthread = self.server.runCommand(["getVariable", "BB_NUMBER_THREADS"])
|
||||
if not bbthread:
|
||||
bbthread = num_threads
|
||||
else:
|
||||
bbthread = int(bbthread)
|
||||
params["bbthread"] = bbthread
|
||||
|
||||
def remove_image_output_type(self, output_type):
|
||||
if output_type in self.image_output_types:
|
||||
ind = self.image_output_types.index(output_type)
|
||||
self.image_output_types.pop(ind)
|
||||
fstypes = " ".join(self.image_output_types).lstrip(" ")
|
||||
self.set_fstypes(fstypes)
|
||||
return self.image_output_types
|
||||
pmake = self.server.runCommand(["getVariable", "PARALLEL_MAKE"])
|
||||
if not pmake:
|
||||
pmake = num_threads
|
||||
elif isinstance(pmake, int):
|
||||
pass
|
||||
else:
|
||||
pmake = int(pmake.lstrip("-j "))
|
||||
params["pmake"] = pmake
|
||||
|
||||
def get_image_deploy_dir(self):
|
||||
return self.image_out_dir
|
||||
image_addr = self.server.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"]) or ""
|
||||
if self.server_addr:
|
||||
image_addr = "http://" + self.server_addr + ":" + image_addr
|
||||
params["image_addr"] = image_addr
|
||||
|
||||
def make_temp_dir(self):
|
||||
bb.utils.mkdirhier(self.image_dir)
|
||||
image_extra_size = self.server.runCommand(["getVariable", "IMAGE_ROOTFS_EXTRA_SPACE"])
|
||||
if not image_extra_size:
|
||||
image_extra_size = 0
|
||||
else:
|
||||
image_extra_size = int(image_extra_size)
|
||||
params["image_extra_size"] = image_extra_size
|
||||
|
||||
def remove_temp_dir(self):
|
||||
bb.utils.remove(self.image_dir, True)
|
||||
image_rootfs_size = self.server.runCommand(["getVariable", "IMAGE_ROOTFS_SIZE"])
|
||||
if not image_rootfs_size:
|
||||
image_rootfs_size = 0
|
||||
else:
|
||||
image_rootfs_size = int(image_rootfs_size)
|
||||
params["image_rootfs_size"] = image_rootfs_size
|
||||
|
||||
def get_temp_recipe_path(self, name):
|
||||
timestamp = datetime.date.today().isoformat()
|
||||
image_file = "hob-%s-variant-%s.bb" % (name, timestamp)
|
||||
recipepath = os.path.join(self.image_dir, image_file)
|
||||
return recipepath
|
||||
image_overhead_factor = self.server.runCommand(["getVariable", "IMAGE_OVERHEAD_FACTOR"])
|
||||
if not image_overhead_factor:
|
||||
image_overhead_factor = 1
|
||||
else:
|
||||
image_overhead_factor = float(image_overhead_factor)
|
||||
params['image_overhead_factor'] = image_overhead_factor
|
||||
|
||||
params["incompat_license"] = self.server.runCommand(["getVariable", "INCOMPATIBLE_LICENSE"]) or ""
|
||||
params["sdk_machine"] = self.server.runCommand(["getVariable", "SDKMACHINE"]) or self.server.runCommand(["getVariable", "SDK_ARCH"]) or ""
|
||||
|
||||
#params["image_types"] = self.server.runCommand(["getVariable", "IMAGE_TYPES"]) or ""
|
||||
params["image_fstypes"] = self.server.runCommand(["getVariable", "IMAGE_FSTYPES"]) or ""
|
||||
"""
|
||||
A workaround
|
||||
"""
|
||||
params["image_types"] = "jffs2 sum.jffs2 cramfs ext2 ext2.gz ext2.bz2 ext3 ext3.gz ext2.lzma btrfs live squashfs squashfs-lzma ubi tar tar.gz tar.bz2 tar.xz cpio cpio.gz cpio.xz cpio.lzma"
|
||||
return params
|
||||
|
||||
765
bitbake/lib/bb/ui/crumbs/hoblistmodel.py
Normal file
@@ -0,0 +1,765 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
|
||||
#
|
||||
# PackageListModel
|
||||
#
|
||||
class PackageListModel(gtk.TreeStore):
|
||||
"""
|
||||
This class defines an gtk.TreeStore subclass which will convert the output
|
||||
of the bb.event.TargetsTreeGenerated event into a gtk.TreeStore whilst also
|
||||
providing convenience functions to access gtk.TreeModel subclasses which
|
||||
provide filtered views of the data.
|
||||
"""
|
||||
(COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_BINB, COL_INC) = range(11)
|
||||
|
||||
__gsignals__ = {
|
||||
"packagelist-populated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"package-selection-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.contents = None
|
||||
self.images = None
|
||||
self.pkgs_size = 0
|
||||
self.pn_path = {}
|
||||
self.pkg_path = {}
|
||||
|
||||
gtk.TreeStore.__init__ (self,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_BOOLEAN)
|
||||
|
||||
|
||||
"""
|
||||
Find the model path for the item_name
|
||||
Returns the path in the model or None
|
||||
"""
|
||||
def find_path_for_item(self, item_name):
|
||||
if item_name not in self.pkg_path.keys():
|
||||
return None
|
||||
else:
|
||||
return self.pkg_path[item_name]
|
||||
|
||||
def find_item_for_path(self, item_path):
|
||||
return self[item_path][self.COL_NAME]
|
||||
|
||||
"""
|
||||
Helper function to determine whether an item is an item specified by filter
|
||||
"""
|
||||
def tree_model_filter(self, model, it, filter):
|
||||
for key in filter.keys():
|
||||
if model.get_value(it, key) not in filter[key]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModelSort
|
||||
containing only the items specified by filter
|
||||
"""
|
||||
def tree_model(self, filter):
|
||||
model = self.filter_new()
|
||||
model.set_visible_func(self.tree_model_filter, filter)
|
||||
|
||||
sort = gtk.TreeModelSort(model)
|
||||
sort.set_sort_column_id(PackageListModel.COL_NAME, gtk.SORT_ASCENDING)
|
||||
sort.set_default_sort_func(None)
|
||||
return sort
|
||||
|
||||
def convert_vpath_to_path(self, view_model, view_path):
|
||||
# view_model is the model sorted
|
||||
# get the path of the model filtered
|
||||
filtered_model_path = view_model.convert_path_to_child_path(view_path)
|
||||
# get the model filtered
|
||||
filtered_model = view_model.get_model()
|
||||
# get the path of the original model
|
||||
path = filtered_model.convert_path_to_child_path(filtered_model_path)
|
||||
return path
|
||||
|
||||
def convert_path_to_vpath(self, view_model, path):
|
||||
name = self.find_item_for_path(path)
|
||||
it = view_model.get_iter_first()
|
||||
while it:
|
||||
child_it = view_model.iter_children(it)
|
||||
while child_it:
|
||||
view_name = view_model.get_value(child_it, self.COL_NAME)
|
||||
if view_name == name:
|
||||
view_path = view_model.get_path(child_it)
|
||||
return view_path
|
||||
child_it = view_model.iter_next(child_it)
|
||||
it = view_model.iter_next(it)
|
||||
return None
|
||||
|
||||
"""
|
||||
The populate() function takes as input the data from a
|
||||
bb.event.PackageInfo event and populates the package list.
|
||||
Once the population is done it emits gsignal packagelist-populated
|
||||
to notify any listeners that the model is ready
|
||||
"""
|
||||
def populate(self, pkginfolist):
|
||||
self.clear()
|
||||
self.pkgs_size = 0
|
||||
self.pn_path = {}
|
||||
self.pkg_path = {}
|
||||
|
||||
for pkginfo in pkginfolist:
|
||||
pn = pkginfo['PN']
|
||||
pv = pkginfo['PV']
|
||||
pr = pkginfo['PR']
|
||||
if pn in self.pn_path.keys():
|
||||
pniter = self.get_iter(self.pn_path[pn])
|
||||
else:
|
||||
pniter = self.append(None)
|
||||
self.set(pniter, self.COL_NAME, pn + '-' + pv + '-' + pr,
|
||||
self.COL_INC, False)
|
||||
self.pn_path[pn] = self.get_path(pniter)
|
||||
|
||||
pkg = pkginfo['PKG']
|
||||
pkgv = pkginfo['PKGV']
|
||||
pkgr = pkginfo['PKGR']
|
||||
pkgsize = pkginfo['PKGSIZE_%s' % pkg] if 'PKGSIZE_%s' % pkg in pkginfo.keys() else "0"
|
||||
pkg_rename = pkginfo['PKG_%s' % pkg] if 'PKG_%s' % pkg in pkginfo.keys() else ""
|
||||
section = pkginfo['SECTION_%s' % pkg] if 'SECTION_%s' % pkg in pkginfo.keys() else ""
|
||||
summary = pkginfo['SUMMARY_%s' % pkg] if 'SUMMARY_%s' % pkg in pkginfo.keys() else ""
|
||||
rdep = pkginfo['RDEPENDS_%s' % pkg] if 'RDEPENDS_%s' % pkg in pkginfo.keys() else ""
|
||||
rrec = pkginfo['RRECOMMENDS_%s' % pkg] if 'RRECOMMENDS_%s' % pkg in pkginfo.keys() else ""
|
||||
rprov = pkginfo['RPROVIDES_%s' % pkg] if 'RPROVIDES_%s' % pkg in pkginfo.keys() else ""
|
||||
|
||||
if 'ALLOW_EMPTY_%s' % pkg in pkginfo.keys():
|
||||
allow_empty = pkginfo['ALLOW_EMPTY_%s' % pkg]
|
||||
elif 'ALLOW_EMPTY' in pkginfo.keys():
|
||||
allow_empty = pkginfo['ALLOW_EMPTY']
|
||||
else:
|
||||
allow_empty = ""
|
||||
|
||||
if pkgsize == "0" and not allow_empty:
|
||||
continue
|
||||
|
||||
if len(pkgsize) > 3:
|
||||
size = '%.1f' % (int(pkgsize)*1.0/1024) + ' MB'
|
||||
else:
|
||||
size = pkgsize + ' KB'
|
||||
|
||||
it = self.append(pniter)
|
||||
self.pkg_path[pkg] = self.get_path(it)
|
||||
self.set(it, self.COL_NAME, pkg, self.COL_VER, pkgv,
|
||||
self.COL_REV, pkgr, self.COL_RNM, pkg_rename,
|
||||
self.COL_SEC, section, self.COL_SUM, summary,
|
||||
self.COL_RDEP, rdep + ' ' + rrec,
|
||||
self.COL_RPROV, rprov, self.COL_SIZE, size,
|
||||
self.COL_BINB, "", self.COL_INC, False)
|
||||
|
||||
self.emit("packagelist-populated")
|
||||
|
||||
"""
|
||||
Check whether the item at item_path is included or not
|
||||
"""
|
||||
def path_included(self, item_path):
|
||||
return self[item_path][self.COL_INC]
|
||||
|
||||
"""
|
||||
Update the model, send out the notification.
|
||||
"""
|
||||
def selection_change_notification(self):
|
||||
self.emit("package-selection-changed")
|
||||
|
||||
"""
|
||||
Mark a certain package as selected.
|
||||
All its dependencies are marked as selected.
|
||||
The recipe provides the package is marked as selected.
|
||||
If user explicitly selects a recipe, all its providing packages are selected
|
||||
"""
|
||||
def include_item(self, item_path, binb=""):
|
||||
if self.path_included(item_path):
|
||||
return
|
||||
|
||||
item_name = self[item_path][self.COL_NAME]
|
||||
item_rdep = self[item_path][self.COL_RDEP]
|
||||
|
||||
self[item_path][self.COL_INC] = True
|
||||
|
||||
self.selection_change_notification()
|
||||
|
||||
it = self.get_iter(item_path)
|
||||
|
||||
# If user explicitly selects a recipe, all its providing packages are selected.
|
||||
if not self[item_path][self.COL_VER] and binb == "User Selected":
|
||||
child_it = self.iter_children(it)
|
||||
while child_it:
|
||||
child_path = self.get_path(child_it)
|
||||
child_included = self.path_included(child_path)
|
||||
if not child_included:
|
||||
self.include_item(child_path, binb="User Selected")
|
||||
child_it = self.iter_next(child_it)
|
||||
return
|
||||
|
||||
# The recipe provides the package is also marked as selected
|
||||
parent_it = self.iter_parent(it)
|
||||
if parent_it:
|
||||
parent_path = self.get_path(parent_it)
|
||||
self[parent_path][self.COL_INC] = True
|
||||
|
||||
item_bin = self[item_path][self.COL_BINB].split(', ')
|
||||
if binb and not binb in item_bin:
|
||||
item_bin.append(binb)
|
||||
self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
|
||||
|
||||
if item_rdep:
|
||||
# Ensure all of the items deps are included and, where appropriate,
|
||||
# add this item to their COL_BINB
|
||||
for dep in item_rdep.split(" "):
|
||||
if dep.startswith('('):
|
||||
continue
|
||||
# If the contents model doesn't already contain dep, add it
|
||||
dep_path = self.find_path_for_item(dep)
|
||||
if not dep_path:
|
||||
continue
|
||||
dep_included = self.path_included(dep_path)
|
||||
|
||||
if dep_included and not dep in item_bin:
|
||||
# don't set the COL_BINB to this item if the target is an
|
||||
# item in our own COL_BINB
|
||||
dep_bin = self[dep_path][self.COL_BINB].split(', ')
|
||||
if not item_name in dep_bin:
|
||||
dep_bin.append(item_name)
|
||||
self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
elif not dep_included:
|
||||
self.include_item(dep_path, binb=item_name)
|
||||
|
||||
"""
|
||||
Mark a certain package as de-selected.
|
||||
All other packages that depends on this package are marked as de-selected.
|
||||
If none of the packages provided by the recipe, the recipe should be marked as de-selected.
|
||||
If user explicitly de-select a recipe, all its providing packages are de-selected.
|
||||
"""
|
||||
def exclude_item(self, item_path):
|
||||
if not self.path_included(item_path):
|
||||
return
|
||||
|
||||
self[item_path][self.COL_INC] = False
|
||||
|
||||
self.selection_change_notification()
|
||||
|
||||
item_name = self[item_path][self.COL_NAME]
|
||||
item_rdep = self[item_path][self.COL_RDEP]
|
||||
it = self.get_iter(item_path)
|
||||
|
||||
# If user explicitly de-select a recipe, all its providing packages are de-selected.
|
||||
if not self[item_path][self.COL_VER]:
|
||||
child_it = self.iter_children(it)
|
||||
while child_it:
|
||||
child_path = self.get_path(child_it)
|
||||
child_included = self[child_path][self.COL_INC]
|
||||
if child_included:
|
||||
self.exclude_item(child_path)
|
||||
child_it = self.iter_next(child_it)
|
||||
return
|
||||
|
||||
# If none of the packages provided by the recipe, the recipe should be marked as de-selected.
|
||||
parent_it = self.iter_parent(it)
|
||||
peer_iter = self.iter_children(parent_it)
|
||||
enabled = 0
|
||||
while peer_iter:
|
||||
peer_path = self.get_path(peer_iter)
|
||||
if self[peer_path][self.COL_INC]:
|
||||
enabled = 1
|
||||
break
|
||||
peer_iter = self.iter_next(peer_iter)
|
||||
if not enabled:
|
||||
parent_path = self.get_path(parent_it)
|
||||
self[parent_path][self.COL_INC] = False
|
||||
|
||||
# All packages that depends on this package are de-selected.
|
||||
if item_rdep:
|
||||
for dep in item_rdep.split(" "):
|
||||
if dep.startswith('('):
|
||||
continue
|
||||
dep_path = self.find_path_for_item(dep)
|
||||
if not dep_path:
|
||||
continue
|
||||
dep_bin = self[dep_path][self.COL_BINB].split(', ')
|
||||
if item_name in dep_bin:
|
||||
dep_bin.remove(item_name)
|
||||
self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
|
||||
item_bin = self[item_path][self.COL_BINB].split(', ')
|
||||
if item_bin:
|
||||
for binb in item_bin:
|
||||
binb_path = self.find_path_for_item(binb)
|
||||
if not binb_path:
|
||||
continue
|
||||
self.exclude_item(binb_path)
|
||||
|
||||
"""
|
||||
Package model may be incomplete, therefore when calling the
|
||||
set_selected_packages(), some packages will not be set included.
|
||||
Return the un-set packages list.
|
||||
"""
|
||||
def set_selected_packages(self, packagelist):
|
||||
left = []
|
||||
for pn in packagelist:
|
||||
if pn in self.pkg_path.keys():
|
||||
path = self.pkg_path[pn]
|
||||
self.include_item(item_path=path,
|
||||
binb="User Selected")
|
||||
else:
|
||||
left.append(pn)
|
||||
|
||||
return left
|
||||
|
||||
def get_selected_packages(self):
|
||||
packagelist = []
|
||||
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
child_it = self.iter_children(it)
|
||||
while child_it:
|
||||
if self.get_value(child_it, self.COL_INC):
|
||||
name = self.get_value(child_it, self.COL_NAME)
|
||||
packagelist.append(name)
|
||||
child_it = self.iter_next(child_it)
|
||||
it = self.iter_next(it)
|
||||
|
||||
return packagelist
|
||||
|
||||
"""
|
||||
Return the selected package size, unit is KB.
|
||||
"""
|
||||
def get_packages_size(self):
|
||||
packages_size = 0
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
child_it = self.iter_children(it)
|
||||
while child_it:
|
||||
if self.get_value(child_it, self.COL_INC):
|
||||
str_size = self.get_value(child_it, self.COL_SIZE)
|
||||
if not str_size:
|
||||
continue
|
||||
|
||||
unit = str_size.split()
|
||||
if unit[1] == 'MB':
|
||||
size = float(unit[0])*1024
|
||||
else:
|
||||
size = float(unit[0])
|
||||
packages_size += size
|
||||
|
||||
child_it = self.iter_next(child_it)
|
||||
it = self.iter_next(it)
|
||||
return "%f" % packages_size
|
||||
|
||||
"""
|
||||
Empty self.contents by setting the include of each entry to None
|
||||
"""
|
||||
def reset(self):
|
||||
self.pkgs_size = 0
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
self.set(it, self.COL_INC, False)
|
||||
child_it = self.iter_children(it)
|
||||
while child_it:
|
||||
self.set(child_it,
|
||||
self.COL_INC, False,
|
||||
self.COL_BINB, "")
|
||||
child_it = self.iter_next(child_it)
|
||||
it = self.iter_next(it)
|
||||
|
||||
self.selection_change_notification()
|
||||
|
||||
#
|
||||
# RecipeListModel
|
||||
#
|
||||
class RecipeListModel(gtk.ListStore):
|
||||
"""
|
||||
This class defines an gtk.ListStore subclass which will convert the output
|
||||
of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
|
||||
providing convenience functions to access gtk.TreeModel subclasses which
|
||||
provide filtered views of the data.
|
||||
"""
|
||||
(COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_INSTALL, COL_PN) = range(11)
|
||||
|
||||
__dummy_image__ = "--select a base image--"
|
||||
|
||||
__gsignals__ = {
|
||||
"recipelist-populated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"recipe-selection-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
}
|
||||
|
||||
"""
|
||||
"""
|
||||
def __init__(self):
|
||||
gtk.ListStore.__init__ (self,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_BOOLEAN,
|
||||
gobject.TYPE_BOOLEAN,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING)
|
||||
|
||||
"""
|
||||
Find the model path for the item_name
|
||||
Returns the path in the model or None
|
||||
"""
|
||||
def find_path_for_item(self, item_name):
|
||||
if self.non_target_name(item_name) or item_name not in self.pn_path.keys():
|
||||
return None
|
||||
else:
|
||||
return self.pn_path[item_name]
|
||||
|
||||
def find_item_for_path(self, item_path):
|
||||
return self[item_path][self.COL_NAME]
|
||||
|
||||
"""
|
||||
Helper method to determine whether name is a target pn
|
||||
"""
|
||||
def non_target_name(self, name):
|
||||
if name and ('-native' in name):
|
||||
return True
|
||||
return False
|
||||
|
||||
"""
|
||||
Helper function to determine whether an item is an item specified by filter
|
||||
"""
|
||||
def tree_model_filter(self, model, it, filter):
|
||||
name = model.get_value(it, self.COL_NAME)
|
||||
if self.non_target_name(name):
|
||||
return False
|
||||
|
||||
for key in filter.keys():
|
||||
if model.get_value(it, key) not in filter[key]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def sort_func(self, model, iter1, iter2):
|
||||
val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
|
||||
val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
|
||||
return val1 > val2
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModelSort
|
||||
containing only the items which are items specified by filter
|
||||
"""
|
||||
def tree_model(self, filter):
|
||||
model = self.filter_new()
|
||||
model.set_visible_func(self.tree_model_filter, filter)
|
||||
|
||||
sort = gtk.TreeModelSort(model)
|
||||
sort.set_default_sort_func(self.sort_func)
|
||||
return sort
|
||||
|
||||
def convert_vpath_to_path(self, view_model, view_path):
|
||||
filtered_model_path = view_model.convert_path_to_child_path(view_path)
|
||||
filtered_model = view_model.get_model()
|
||||
|
||||
# get the path of the original model
|
||||
path = filtered_model.convert_path_to_child_path(filtered_model_path)
|
||||
return path
|
||||
|
||||
def convert_path_to_vpath(self, view_model, path):
|
||||
it = view_model.get_iter_first()
|
||||
while it:
|
||||
name = self.find_item_for_path(path)
|
||||
view_name = view_model.get_value(it, RecipeListModel.COL_NAME)
|
||||
if view_name == name:
|
||||
view_path = view_model.get_path(it)
|
||||
return view_path
|
||||
it = view_model.iter_next(it)
|
||||
return None
|
||||
|
||||
def map_runtime(self, event_model, runtime, rdep_type, name):
|
||||
if rdep_type not in ['pkg', 'pn'] or runtime not in ['rdepends', 'rrecs']:
|
||||
return
|
||||
package_depends = event_model["%s-%s" % (runtime, rdep_type)].get(name, [])
|
||||
pn_depends = []
|
||||
for package_depend in package_depends:
|
||||
if 'task-' not in package_depend and package_depend in event_model["packages"].keys():
|
||||
pn_depends.append(event_model["packages"][package_depend]["pn"])
|
||||
else:
|
||||
pn_depends.append(package_depend)
|
||||
return list(set(pn_depends))
|
||||
|
||||
def subpkg_populate(self, event_model, pkg, desc, lic, group, atype, pn):
|
||||
pn_depends = self.map_runtime(event_model, "rdepends", "pkg", pkg)
|
||||
pn_depends += self.map_runtime(event_model, "rrecs", "pkg", pkg)
|
||||
self.set(self.append(), self.COL_NAME, pkg, self.COL_DESC, desc,
|
||||
self.COL_LIC, lic, self.COL_GROUP, group,
|
||||
self.COL_DEPS, " ".join(pn_depends), self.COL_BINB, "",
|
||||
self.COL_TYPE, atype, self.COL_INC, False,
|
||||
self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, pn)
|
||||
|
||||
"""
|
||||
The populate() function takes as input the data from a
|
||||
bb.event.TargetsTreeGenerated event and populates the RecipeList.
|
||||
Once the population is done it emits gsignal recipelist-populated
|
||||
to notify any listeners that the model is ready
|
||||
"""
|
||||
def populate(self, event_model):
|
||||
# First clear the model, in case repopulating
|
||||
self.clear()
|
||||
|
||||
# dummy image for prompt
|
||||
self.set(self.append(), self.COL_NAME, self.__dummy_image__,
|
||||
self.COL_DESC, "",
|
||||
self.COL_LIC, "", self.COL_GROUP, "",
|
||||
self.COL_DEPS, "", self.COL_BINB, "",
|
||||
self.COL_TYPE, "image", self.COL_INC, False,
|
||||
self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, self.__dummy_image__)
|
||||
|
||||
for item in event_model["pn"]:
|
||||
name = item
|
||||
desc = event_model["pn"][item]["description"]
|
||||
lic = event_model["pn"][item]["license"]
|
||||
group = event_model["pn"][item]["section"]
|
||||
install = []
|
||||
|
||||
if ('task-' in name):
|
||||
if ('lib32-' in name or 'lib64-' in name):
|
||||
atype = 'mltask'
|
||||
else:
|
||||
atype = 'task'
|
||||
for pkg in event_model["pn"][name]["packages"]:
|
||||
self.subpkg_populate(event_model, pkg, desc, lic, group, atype, name)
|
||||
continue
|
||||
|
||||
elif ('-image-' in name):
|
||||
atype = 'image'
|
||||
depends = event_model["depends"].get(item, [])
|
||||
rdepends = self.map_runtime(event_model, 'rdepends', 'pn', name)
|
||||
depends = depends + rdepends
|
||||
install = event_model["rdepends-pn"].get(item, [])
|
||||
|
||||
elif ('meta-' in name):
|
||||
atype = 'toolchain'
|
||||
|
||||
elif (name == 'dummy-image' or name == 'dummy-toolchain'):
|
||||
atype = 'dummy'
|
||||
|
||||
else:
|
||||
if ('lib32-' in name or 'lib64-' in name):
|
||||
atype = 'mlrecipe'
|
||||
else:
|
||||
atype = 'recipe'
|
||||
depends = event_model["depends"].get(item, [])
|
||||
depends += self.map_runtime(event_model, 'rdepends', 'pn', item)
|
||||
for pkg in event_model["pn"][name]["packages"]:
|
||||
depends += self.map_runtime(event_model, 'rdepends', 'pkg', item)
|
||||
depends += self.map_runtime(event_model, 'rrecs', 'pkg', item)
|
||||
|
||||
self.set(self.append(), self.COL_NAME, item, self.COL_DESC, desc,
|
||||
self.COL_LIC, lic, self.COL_GROUP, group,
|
||||
self.COL_DEPS, " ".join(depends), self.COL_BINB, "",
|
||||
self.COL_TYPE, atype, self.COL_INC, False,
|
||||
self.COL_IMG, False, self.COL_INSTALL, " ".join(install), self.COL_PN, item)
|
||||
|
||||
self.pn_path = {}
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
pn = self.get_value(it, self.COL_NAME)
|
||||
path = self.get_path(it)
|
||||
self.pn_path[pn] = path
|
||||
it = self.iter_next(it)
|
||||
|
||||
self.emit("recipelist-populated")
|
||||
|
||||
"""
|
||||
Update the model, send out the notification.
|
||||
"""
|
||||
def selection_change_notification(self):
|
||||
self.emit("recipe-selection-changed")
|
||||
|
||||
def path_included(self, item_path):
|
||||
return self[item_path][self.COL_INC]
|
||||
|
||||
"""
|
||||
Append a certain image into the combobox
|
||||
"""
|
||||
def image_list_append(self, name, deps, install):
|
||||
# check whether a certain image is there
|
||||
if not name or self.find_path_for_item(name):
|
||||
return
|
||||
it = self.append()
|
||||
self.set(it, self.COL_NAME, name, self.COL_DESC, "",
|
||||
self.COL_LIC, "", self.COL_GROUP, "",
|
||||
self.COL_DEPS, deps, self.COL_BINB, "",
|
||||
self.COL_TYPE, "image", self.COL_INC, False,
|
||||
self.COL_IMG, False, self.COL_INSTALL, install,
|
||||
self.COL_PN, name)
|
||||
self.pn_path[name] = self.get_path(it)
|
||||
|
||||
"""
|
||||
Add this item, and any of its dependencies, to the image contents
|
||||
"""
|
||||
def include_item(self, item_path, binb="", image_contents=False):
|
||||
if self.path_included(item_path):
|
||||
return
|
||||
|
||||
item_name = self[item_path][self.COL_NAME]
|
||||
item_deps = self[item_path][self.COL_DEPS]
|
||||
|
||||
self[item_path][self.COL_INC] = True
|
||||
self.selection_change_notification()
|
||||
|
||||
item_bin = self[item_path][self.COL_BINB].split(', ')
|
||||
if binb and not binb in item_bin:
|
||||
item_bin.append(binb)
|
||||
self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
|
||||
|
||||
# We want to do some magic with things which are brought in by the
|
||||
# base image so tag them as so
|
||||
if image_contents:
|
||||
self[item_path][self.COL_IMG] = True
|
||||
|
||||
if item_deps:
|
||||
# Ensure all of the items deps are included and, where appropriate,
|
||||
# add this item to their COL_BINB
|
||||
for dep in item_deps.split(" "):
|
||||
# If the contents model doesn't already contain dep, add it
|
||||
dep_path = self.find_path_for_item(dep)
|
||||
if not dep_path:
|
||||
continue
|
||||
dep_included = self.path_included(dep_path)
|
||||
|
||||
if dep_included and not dep in item_bin:
|
||||
# don't set the COL_BINB to this item if the target is an
|
||||
# item in our own COL_BINB
|
||||
dep_bin = self[dep_path][self.COL_BINB].split(', ')
|
||||
if not item_name in dep_bin:
|
||||
dep_bin.append(item_name)
|
||||
self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
elif not dep_included:
|
||||
self.include_item(dep_path, binb=item_name, image_contents=image_contents)
|
||||
|
||||
def exclude_item(self, item_path):
|
||||
if not self.path_included(item_path):
|
||||
return
|
||||
|
||||
self[item_path][self.COL_INC] = False
|
||||
|
||||
self.selection_change_notification()
|
||||
|
||||
item_name = self[item_path][self.COL_NAME]
|
||||
item_deps = self[item_path][self.COL_DEPS]
|
||||
if item_deps:
|
||||
for dep in item_deps.split(" "):
|
||||
dep_path = self.find_path_for_item(dep)
|
||||
if not dep_path:
|
||||
continue
|
||||
dep_bin = self[dep_path][self.COL_BINB].split(', ')
|
||||
if item_name in dep_bin:
|
||||
dep_bin.remove(item_name)
|
||||
self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
|
||||
item_bin = self[item_path][self.COL_BINB].split(', ')
|
||||
if item_bin:
|
||||
for binb in item_bin:
|
||||
binb_path = self.find_path_for_item(binb)
|
||||
if not binb_path:
|
||||
continue
|
||||
self.exclude_item(binb_path)
|
||||
|
||||
def reset(self):
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
self.set(it,
|
||||
self.COL_INC, False,
|
||||
self.COL_BINB, "",
|
||||
self.COL_IMG, False)
|
||||
it = self.iter_next(it)
|
||||
|
||||
self.selection_change_notification()
|
||||
|
||||
"""
|
||||
Returns two lists. One of user selected recipes and the other containing
|
||||
all selected recipes
|
||||
"""
|
||||
def get_selected_recipes(self):
|
||||
allrecipes = []
|
||||
userrecipes = []
|
||||
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
if self.get_value(it, self.COL_INC):
|
||||
name = self.get_value(it, self.COL_PN)
|
||||
type = self.get_value(it, self.COL_TYPE)
|
||||
if type != "image":
|
||||
allrecipes.append(name)
|
||||
sel = "User Selected" in self.get_value(it, self.COL_BINB)
|
||||
if sel:
|
||||
userrecipes.append(name)
|
||||
it = self.iter_next(it)
|
||||
|
||||
return list(set(userrecipes)), list(set(allrecipes))
|
||||
|
||||
def set_selected_recipes(self, recipelist):
|
||||
for pn in recipelist:
|
||||
if pn in self.pn_path.keys():
|
||||
path = self.pn_path[pn]
|
||||
self.include_item(item_path=path,
|
||||
binb="User Selected")
|
||||
|
||||
def get_selected_image(self):
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
if self.get_value(it, self.COL_INC):
|
||||
name = self.get_value(it, self.COL_PN)
|
||||
type = self.get_value(it, self.COL_TYPE)
|
||||
if type == "image":
|
||||
sel = "User Selected" in self.get_value(it, self.COL_BINB)
|
||||
if sel:
|
||||
return name
|
||||
it = self.iter_next(it)
|
||||
return None
|
||||
|
||||
def set_selected_image(self, img):
|
||||
if img == None:
|
||||
return
|
||||
path = self.find_path_for_item(img)
|
||||
self.include_item(item_path=path,
|
||||
binb="User Selected",
|
||||
image_contents=True)
|
||||
87
bitbake/lib/bb/ui/crumbs/hobpages.py
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import hwc
|
||||
|
||||
#
|
||||
# HobPage: the super class for all Hob-related pages
|
||||
#
|
||||
class HobPage (gtk.VBox):
|
||||
|
||||
def __init__(self, builder, title = None):
|
||||
super(HobPage, self).__init__(False, 0)
|
||||
self.builder = builder
|
||||
self.builder_width, self.builder_height = self.builder.size_request()
|
||||
|
||||
if title == None:
|
||||
self.title = "HOB -- Image Creator"
|
||||
else:
|
||||
self.title = title
|
||||
|
||||
self.box_group_area = gtk.VBox(False, 15)
|
||||
self.box_group_area.set_size_request(self.builder_width - 73 - 73, self.builder_height - 88 - 15 - 15)
|
||||
self.group_align = gtk.Alignment(xalign = 0, yalign=0.5, xscale=1, yscale=1)
|
||||
self.group_align.set_padding(15, 15, 73, 73)
|
||||
self.group_align.add(self.box_group_area)
|
||||
self.box_group_area.set_homogeneous(False)
|
||||
|
||||
|
||||
def add_onto_top_bar(self, widget = None, padding = 0):
|
||||
# the top button occupies 1/7 of the page height
|
||||
# setup an event box
|
||||
eventbox = gtk.EventBox()
|
||||
style = eventbox.get_style().copy()
|
||||
style.bg[gtk.STATE_NORMAL] = eventbox.get_colormap().alloc_color(HobColors.LIGHT_GRAY, False, False)
|
||||
eventbox.set_style(style)
|
||||
eventbox.set_size_request(-1, 88)
|
||||
|
||||
hbox = gtk.HBox()
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_markup("<span font_desc=\'14\'>%s</span>" % self.title)
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=20)
|
||||
|
||||
if widget != None:
|
||||
# add the widget in the event box
|
||||
hbox.pack_end(widget, expand=False, fill=False, padding=padding)
|
||||
eventbox.add(hbox)
|
||||
|
||||
return eventbox
|
||||
|
||||
def span_tag(self, px="12px", weight="normal", forground="#1c1c1c"):
|
||||
span_tag = "weight=\'%s\' foreground=\'%s\' font_desc=\'%s\'" % (weight, forground, px)
|
||||
return span_tag
|
||||
|
||||
def append_toolbar_button(self, toolbar, buttonname, icon_disp, icon_hovor, tip, cb):
|
||||
# Create a button and append it on the toolbar according to button name
|
||||
icon = gtk.Image()
|
||||
icon_display = icon_disp
|
||||
icon_hover = icon_hovor
|
||||
pix_buffer = gtk.gdk.pixbuf_new_from_file(icon_display)
|
||||
icon.set_from_pixbuf(pix_buffer)
|
||||
tip_text = tip
|
||||
button = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, None,
|
||||
buttonname, tip_text, "Private text", icon,
|
||||
cb, None)
|
||||
return toolbar, button
|
||||
@@ -1,335 +0,0 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import glib
|
||||
from bb.ui.crumbs.configurator import Configurator
|
||||
|
||||
class HobPrefs(gtk.Dialog):
|
||||
"""
|
||||
"""
|
||||
def empty_combo_text(self, combo_text):
|
||||
model = combo_text.get_model()
|
||||
if model:
|
||||
model.clear()
|
||||
|
||||
def output_type_toggled_cb(self, check, handler):
|
||||
ot = check.get_label()
|
||||
enabled = check.get_active()
|
||||
if enabled:
|
||||
self.selected_image_types = handler.add_image_output_type(ot)
|
||||
else:
|
||||
self.selected_image_types = handler.remove_image_output_type(ot)
|
||||
|
||||
self.configurator.setConfVar('IMAGE_FSTYPES', "%s" % " ".join(self.selected_image_types).lstrip(" "))
|
||||
self.reload_required = True
|
||||
|
||||
def sdk_machine_combo_changed_cb(self, combo, handler):
|
||||
sdk_mach = combo.get_active_text()
|
||||
if sdk_mach != self.curr_sdk_mach:
|
||||
self.curr_sdk_mach = sdk_mach
|
||||
self.configurator.setConfVar('SDKMACHINE', sdk_mach)
|
||||
handler.set_sdk_machine(sdk_mach)
|
||||
|
||||
def update_sdk_machines(self, handler, sdk_machines):
|
||||
active = 0
|
||||
# disconnect the signal handler before updating the combo model
|
||||
if self.sdk_machine_handler_id:
|
||||
self.sdk_machine_combo.disconnect(self.sdk_machine_handler_id)
|
||||
self.sdk_machine_handler_id = None
|
||||
|
||||
self.empty_combo_text(self.sdk_machine_combo)
|
||||
for sdk_machine in sdk_machines:
|
||||
self.sdk_machine_combo.append_text(sdk_machine)
|
||||
if sdk_machine == self.curr_sdk_mach:
|
||||
self.sdk_machine_combo.set_active(active)
|
||||
active = active + 1
|
||||
|
||||
self.sdk_machine_handler_id = self.sdk_machine_combo.connect("changed", self.sdk_machine_combo_changed_cb, handler)
|
||||
|
||||
def distro_combo_changed_cb(self, combo, handler):
|
||||
distro = combo.get_active_text()
|
||||
if distro != self.curr_distro:
|
||||
self.curr_distro = distro
|
||||
self.configurator.setConfVar('DISTRO', distro)
|
||||
handler.set_distro(distro)
|
||||
self.reload_required = True
|
||||
|
||||
def update_distros(self, handler, distros):
|
||||
active = 0
|
||||
# disconnect the signal handler before updating combo model
|
||||
if self.distro_handler_id:
|
||||
self.distro_combo.disconnect(self.distro_handler_id)
|
||||
self.distro_handler_id = None
|
||||
|
||||
self.empty_combo_text(self.distro_combo)
|
||||
for distro in distros:
|
||||
self.distro_combo.append_text(distro)
|
||||
if distro == self.curr_distro:
|
||||
self.distro_combo.set_active(active)
|
||||
active = active + 1
|
||||
|
||||
self.distro_handler_id = self.distro_combo.connect("changed", self.distro_combo_changed_cb, handler)
|
||||
|
||||
def package_format_combo_changed_cb(self, combo, handler):
|
||||
package_format = combo.get_active_text()
|
||||
if package_format != self.curr_package_format:
|
||||
self.curr_package_format = package_format
|
||||
self.configurator.setConfVar('PACKAGE_CLASSES', 'package_%s' % package_format)
|
||||
handler.set_package_format(package_format)
|
||||
self.reload_required = True
|
||||
|
||||
def update_package_formats(self, handler, formats):
|
||||
active = 0
|
||||
# disconnect the signal handler before updating the model
|
||||
if self.package_handler_id:
|
||||
self.package_combo.disconnect(self.package_handler_id)
|
||||
self.package_handler_id = None
|
||||
|
||||
self.empty_combo_text(self.package_combo)
|
||||
for format in formats:
|
||||
self.package_combo.append_text(format)
|
||||
if format == self.curr_package_format:
|
||||
self.package_combo.set_active(active)
|
||||
active = active + 1
|
||||
|
||||
self.package_handler_id = self.package_combo.connect("changed", self.package_format_combo_changed_cb, handler)
|
||||
|
||||
def include_gplv3_cb(self, toggle):
|
||||
excluded = toggle.get_active()
|
||||
orig_incompatible = self.configurator.getConfVar('INCOMPATIBLE_LICENSE')
|
||||
new_incompatible = ""
|
||||
if excluded:
|
||||
if not orig_incompatible:
|
||||
new_incompatible = "GPLv3"
|
||||
elif not orig_incompatible.find('GPLv3'):
|
||||
new_incompatible = "%s GPLv3" % orig_incompatible
|
||||
else:
|
||||
new_incompatible = orig_incompatible.replace('GPLv3', '')
|
||||
|
||||
if new_incompatible != orig_incompatible:
|
||||
self.handler.set_incompatible_license(new_incompatible)
|
||||
self.configurator.setConfVar('INCOMPATIBLE_LICENSE', new_incompatible)
|
||||
self.reload_required = True
|
||||
|
||||
def change_bb_threads_cb(self, spinner):
|
||||
val = spinner.get_value_as_int()
|
||||
self.handler.set_bbthreads(val)
|
||||
self.configurator.setConfVar('BB_NUMBER_THREADS', val)
|
||||
|
||||
def change_make_threads_cb(self, spinner):
|
||||
val = spinner.get_value_as_int()
|
||||
self.handler.set_pmake(val)
|
||||
self.configurator.setConfVar('PARALLEL_MAKE', "-j %s" % val)
|
||||
|
||||
def toggle_toolchain_cb(self, check):
|
||||
enabled = check.get_active()
|
||||
toolchain = '0'
|
||||
if enabled:
|
||||
toolchain = '1'
|
||||
self.handler.toggle_toolchain(enabled)
|
||||
self.configurator.setConfVar('HOB_BUILD_TOOLCHAIN', toolchain)
|
||||
|
||||
def toggle_headers_cb(self, check):
|
||||
enabled = check.get_active()
|
||||
headers = '0'
|
||||
if enabled:
|
||||
headers = '1'
|
||||
self.handler.toggle_toolchain_headers(enabled)
|
||||
self.configurator.setConfVar('HOB_BUILD_TOOLCHAIN_HEADERS', headers)
|
||||
|
||||
def set_parent_window(self, parent):
|
||||
self.set_transient_for(parent)
|
||||
|
||||
def write_changes(self):
|
||||
self.configurator.writeConf()
|
||||
|
||||
def prefs_response_cb(self, dialog, response):
|
||||
if self.reload_required:
|
||||
glib.idle_add(self.handler.reload_data)
|
||||
self.reload_required = False
|
||||
|
||||
def __init__(self, configurator, handler, curr_sdk_mach, curr_distro, pclass,
|
||||
pmake, bbthread, selected_image_types, all_image_types,
|
||||
gplv3disabled, build_toolchain, build_toolchain_headers):
|
||||
"""
|
||||
"""
|
||||
gtk.Dialog.__init__(self, "Preferences", None,
|
||||
gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
(gtk.STOCK_CLOSE, gtk.RESPONSE_OK))
|
||||
|
||||
self.set_border_width(6)
|
||||
self.vbox.set_property("spacing", 12)
|
||||
self.action_area.set_property("spacing", 12)
|
||||
self.action_area.set_property("border-width", 6)
|
||||
|
||||
self.handler = handler
|
||||
self.configurator = configurator
|
||||
|
||||
self.curr_sdk_mach = curr_sdk_mach
|
||||
self.curr_distro = curr_distro
|
||||
self.curr_package_format = pclass
|
||||
self.pmake = pmake
|
||||
self.bbthread = bbthread
|
||||
self.selected_image_types = selected_image_types.split(" ")
|
||||
self.gplv3disabled = gplv3disabled
|
||||
self.build_toolchain = build_toolchain
|
||||
self.build_toolchain_headers = build_toolchain_headers
|
||||
|
||||
self.reload_required = False
|
||||
self.distro_handler_id = None
|
||||
self.sdk_machine_handler_id = None
|
||||
self.package_handler_id = None
|
||||
|
||||
left = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
||||
right = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_markup("<b>Policy</b>")
|
||||
label.show()
|
||||
frame = gtk.Frame()
|
||||
frame.set_label_widget(label)
|
||||
frame.set_shadow_type(gtk.SHADOW_NONE)
|
||||
frame.show()
|
||||
self.vbox.pack_start(frame)
|
||||
pbox = gtk.VBox(False, 12)
|
||||
pbox.show()
|
||||
frame.add(pbox)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.show()
|
||||
pbox.pack_start(hbox, expand=False, fill=False, padding=6)
|
||||
# Distro selector
|
||||
label = gtk.Label("Distribution:")
|
||||
label.show()
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=6)
|
||||
self.distro_combo = gtk.combo_box_new_text()
|
||||
self.distro_combo.set_tooltip_text("Select the Yocto distribution you would like to use")
|
||||
self.distro_combo.show()
|
||||
hbox.pack_start(self.distro_combo, expand=False, fill=False, padding=6)
|
||||
# Exclude GPLv3
|
||||
check = gtk.CheckButton("Exclude GPLv3 packages")
|
||||
check.set_tooltip_text("Check this box to prevent GPLv3 packages from being included in your image")
|
||||
check.show()
|
||||
check.set_active(self.gplv3disabled)
|
||||
check.connect("toggled", self.include_gplv3_cb)
|
||||
hbox.pack_start(check, expand=False, fill=False, padding=6)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.show()
|
||||
pbox.pack_start(hbox, expand=False, fill=False, padding=6)
|
||||
# Package format selector
|
||||
label = gtk.Label("Package format:")
|
||||
label.show()
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=6)
|
||||
self.package_combo = gtk.combo_box_new_text()
|
||||
self.package_combo.set_tooltip_text("""The package format is that used in creation
|
||||
of the root filesystem and also dictates the package manager used in your image""")
|
||||
self.package_combo.show()
|
||||
hbox.pack_start(self.package_combo, expand=False, fill=False, padding=6)
|
||||
if all_image_types:
|
||||
# Image output type selector
|
||||
label = gtk.Label("Image output types:")
|
||||
label.show()
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=6)
|
||||
chk_cnt = 3
|
||||
for it in all_image_types.split(" "):
|
||||
chk_cnt = chk_cnt + 1
|
||||
if chk_cnt % 6 == 0:
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.show()
|
||||
pbox.pack_start(hbox, expand=False, fill=False, padding=6)
|
||||
chk = gtk.CheckButton(it)
|
||||
if it in self.selected_image_types:
|
||||
chk.set_active(True)
|
||||
chk.set_tooltip_text("Build an %s image" % it)
|
||||
chk.connect("toggled", self.output_type_toggled_cb, handler)
|
||||
chk.show()
|
||||
hbox.pack_start(chk, expand=False, fill=False, padding=3)
|
||||
# BitBake
|
||||
label = gtk.Label()
|
||||
label.set_markup("<b>BitBake</b>")
|
||||
label.show()
|
||||
frame = gtk.Frame()
|
||||
frame.set_label_widget(label)
|
||||
frame.set_shadow_type(gtk.SHADOW_NONE)
|
||||
frame.show()
|
||||
self.vbox.pack_start(frame)
|
||||
pbox = gtk.VBox(False, 12)
|
||||
pbox.show()
|
||||
frame.add(pbox)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.show()
|
||||
pbox.pack_start(hbox, expand=False, fill=False, padding=6)
|
||||
label = gtk.Label("BitBake threads:")
|
||||
label.show()
|
||||
# NOTE: may be a good idea in future to intelligently cap the maximum
|
||||
# values but we need more data to make an educated decision, for now
|
||||
# set a high maximum as a value for upper bounds is required by the
|
||||
# gtk.Adjustment
|
||||
spin_max = 30 # seems like a high enough arbitrary number
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=6)
|
||||
bbadj = gtk.Adjustment(value=self.bbthread, lower=1, upper=spin_max, step_incr=1)
|
||||
bbspinner = gtk.SpinButton(adjustment=bbadj, climb_rate=1, digits=0)
|
||||
bbspinner.show()
|
||||
bbspinner.connect("value-changed", self.change_bb_threads_cb)
|
||||
hbox.pack_start(bbspinner, expand=False, fill=False, padding=6)
|
||||
label = gtk.Label("Make threads:")
|
||||
label.show()
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=6)
|
||||
madj = gtk.Adjustment(value=self.pmake, lower=1, upper=spin_max, step_incr=1)
|
||||
makespinner = gtk.SpinButton(adjustment=madj, climb_rate=1, digits=0)
|
||||
makespinner.connect("value-changed", self.change_make_threads_cb)
|
||||
makespinner.show()
|
||||
hbox.pack_start(makespinner, expand=False, fill=False, padding=6)
|
||||
# Toolchain
|
||||
label = gtk.Label()
|
||||
label.set_markup("<b>External Toolchain</b>")
|
||||
label.show()
|
||||
frame = gtk.Frame()
|
||||
frame.set_label_widget(label)
|
||||
frame.set_shadow_type(gtk.SHADOW_NONE)
|
||||
frame.show()
|
||||
self.vbox.pack_start(frame)
|
||||
pbox = gtk.VBox(False, 12)
|
||||
pbox.show()
|
||||
frame.add(pbox)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.show()
|
||||
pbox.pack_start(hbox, expand=False, fill=False, padding=6)
|
||||
toolcheck = gtk.CheckButton("Build external development toolchain with image")
|
||||
toolcheck.show()
|
||||
toolcheck.set_active(self.build_toolchain)
|
||||
toolcheck.connect("toggled", self.toggle_toolchain_cb)
|
||||
hbox.pack_start(toolcheck, expand=False, fill=False, padding=6)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.show()
|
||||
pbox.pack_start(hbox, expand=False, fill=False, padding=6)
|
||||
label = gtk.Label("Toolchain host:")
|
||||
label.show()
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=6)
|
||||
self.sdk_machine_combo = gtk.combo_box_new_text()
|
||||
self.sdk_machine_combo.set_tooltip_text("Select the host architecture of the external machine")
|
||||
self.sdk_machine_combo.show()
|
||||
hbox.pack_start(self.sdk_machine_combo, expand=False, fill=False, padding=6)
|
||||
# headerscheck = gtk.CheckButton("Include development headers with toolchain")
|
||||
# headerscheck.show()
|
||||
# headerscheck.set_active(self.build_toolchain_headers)
|
||||
# headerscheck.connect("toggled", self.toggle_headers_cb)
|
||||
# hbox.pack_start(headerscheck, expand=False, fill=False, padding=6)
|
||||
self.connect("response", self.prefs_response_cb)
|
||||
805
bitbake/lib/bb/ui/crumbs/hobwidget.py
Normal file
@@ -0,0 +1,805 @@
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011-2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
import os
|
||||
import os.path
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
|
||||
class hwc:
|
||||
|
||||
MAIN_WIN_WIDTH = 1024
|
||||
MAIN_WIN_HEIGHT = 700
|
||||
|
||||
class hic:
|
||||
|
||||
HOB_ICON_BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ("ui/icons/"))
|
||||
|
||||
ICON_RCIPE_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('recipe/recipe_display.png'))
|
||||
ICON_RCIPE_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('recipe/recipe_hover.png'))
|
||||
ICON_PACKAGES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('packages/packages_display.png'))
|
||||
ICON_PACKAGES_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('packages/packages_hover.png'))
|
||||
ICON_LAYERS_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('layers/layers_display.png'))
|
||||
ICON_LAYERS_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('layers/layers_hover.png'))
|
||||
ICON_TEMPLATES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('templates/templates_display.png'))
|
||||
ICON_TEMPLATES_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('templates/templates_hover.png'))
|
||||
ICON_IMAGES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('images/images_display.png'))
|
||||
ICON_IMAGES_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('images/images_hover.png'))
|
||||
ICON_SETTINGS_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('settings/settings_display.png'))
|
||||
ICON_SETTINGS_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('settings/settings_hover.png'))
|
||||
ICON_INFO_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('info/info_display.png'))
|
||||
ICON_INFO_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('info/info_hover.png'))
|
||||
ICON_INDI_CONFIRM_FILE = os.path.join(HOB_ICON_BASE_DIR, ('indicators/confirmation.png'))
|
||||
ICON_INDI_ERROR_FILE = os.path.join(HOB_ICON_BASE_DIR, ('indicators/error.png'))
|
||||
|
||||
class HobWidget:
|
||||
@classmethod
|
||||
def resize_widget(cls, screen, widget, widget_width, widget_height):
|
||||
screen_width, screen_height = screen.get_size_request()
|
||||
ratio_height = screen_width * hwc.MAIN_WIN_HEIGHT/hwc.MAIN_WIN_WIDTH
|
||||
if ratio_height < screen_height:
|
||||
screen_height = ratio_height
|
||||
widget_width = widget_width * screen_width/hwc.MAIN_WIN_WIDTH
|
||||
widget_height = widget_height * screen_height/hwc.MAIN_WIN_HEIGHT
|
||||
widget.set_size_request(widget_width, widget_height)
|
||||
|
||||
@classmethod
|
||||
def _toggle_cb(cls, cell, path, model, column):
|
||||
it = model.get_iter(path)
|
||||
val = model.get_value(it, column)
|
||||
val = not val
|
||||
model.set(it, column, val)
|
||||
|
||||
@classmethod
|
||||
def _pkgfmt_up_clicked_cb(cls, button, tree_selection):
|
||||
(model, it) = tree_selection.get_selected()
|
||||
if not it:
|
||||
return
|
||||
path = model.get_path(it)
|
||||
if path[0] <= 0:
|
||||
return
|
||||
|
||||
pre_it = model.get_iter_first()
|
||||
if not pre_it:
|
||||
return
|
||||
else:
|
||||
while model.iter_next(pre_it) :
|
||||
if model.get_value(model.iter_next(pre_it), 1) != model.get_value(it, 1):
|
||||
pre_it = model.iter_next(pre_it)
|
||||
else:
|
||||
break
|
||||
|
||||
cur_index = model.get_value(it, 0)
|
||||
pre_index = cur_index
|
||||
if pre_it:
|
||||
model.set(pre_it, 0, pre_index)
|
||||
cur_index = cur_index - 1
|
||||
model.set(it, 0, cur_index)
|
||||
|
||||
@classmethod
|
||||
def _pkgfmt_down_clicked_cb(cls, button, tree_selection):
|
||||
(model, it) = tree_selection.get_selected()
|
||||
if not it:
|
||||
return
|
||||
next_it = model.iter_next(it)
|
||||
if not next_it:
|
||||
return
|
||||
cur_index = model.get_value(it, 0)
|
||||
next_index = cur_index
|
||||
model.set(next_it, 0, next_index)
|
||||
cur_index = cur_index + 1
|
||||
model.set(it, 0, cur_index)
|
||||
|
||||
@classmethod
|
||||
def _tree_selection_changed_cb(cls, tree_selection, button1, button2):
|
||||
(model, it) = tree_selection.get_selected()
|
||||
inc = model.get_value(it, 2)
|
||||
if inc:
|
||||
button1.set_sensitive(True)
|
||||
button2.set_sensitive(True)
|
||||
else:
|
||||
button1.set_sensitive(False)
|
||||
button2.set_sensitive(False)
|
||||
|
||||
@classmethod
|
||||
def _sort_func(cls, model, iter1, iter2, data):
|
||||
val1 = model.get_value(iter1, 0)
|
||||
val2 = model.get_value(iter2, 0)
|
||||
inc1 = model.get_value(iter1, 2)
|
||||
inc2 = model.get_value(iter2, 2)
|
||||
if inc1 != inc2:
|
||||
return inc2 - inc1
|
||||
else:
|
||||
return val1 - val2
|
||||
|
||||
@classmethod
|
||||
def gen_pkgfmt_widget(cls, curr_package_format, all_package_format, tooltip=""):
|
||||
pkgfmt_hbox = gtk.HBox(False, 15)
|
||||
|
||||
pkgfmt_store = gtk.ListStore(int, str, gobject.TYPE_BOOLEAN)
|
||||
for format in curr_package_format.split():
|
||||
pkgfmt_store.set(pkgfmt_store.append(), 1, format, 2, True)
|
||||
for format in all_package_format:
|
||||
if format not in curr_package_format:
|
||||
pkgfmt_store.set(pkgfmt_store.append(), 1, format, 2, False)
|
||||
pkgfmt_tree = gtk.TreeView(pkgfmt_store)
|
||||
pkgfmt_tree.set_headers_clickable(True)
|
||||
pkgfmt_tree.set_headers_visible(False)
|
||||
tree_selection = pkgfmt_tree.get_selection()
|
||||
tree_selection.set_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
col = gtk.TreeViewColumn('NO')
|
||||
col.set_sort_column_id(0)
|
||||
col.set_sort_order(gtk.SORT_ASCENDING)
|
||||
col.set_clickable(False)
|
||||
col1 = gtk.TreeViewColumn('TYPE')
|
||||
col1.set_min_width(130)
|
||||
col1.set_max_width(140)
|
||||
col2 = gtk.TreeViewColumn('INCLUDED')
|
||||
col2.set_min_width(60)
|
||||
col2.set_max_width(70)
|
||||
pkgfmt_tree.append_column(col1)
|
||||
pkgfmt_tree.append_column(col2)
|
||||
cell = gtk.CellRendererText()
|
||||
cell1 = gtk.CellRendererText()
|
||||
cell1.set_property('width-chars', 10)
|
||||
cell2 = gtk.CellRendererToggle()
|
||||
cell2.set_property('activatable', True)
|
||||
cell2.connect("toggled", cls._toggle_cb, pkgfmt_store, 2)
|
||||
col.pack_start(cell, True)
|
||||
col1.pack_start(cell1, True)
|
||||
col2.pack_end(cell2, True)
|
||||
col.set_attributes(cell, text=0)
|
||||
col1.set_attributes(cell1, text=1)
|
||||
col2.set_attributes(cell2, active=2)
|
||||
|
||||
pkgfmt_store.set_sort_func(0, cls._sort_func, None)
|
||||
pkgfmt_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
scroll.add(pkgfmt_tree)
|
||||
scroll.set_size_request(200,60)
|
||||
pkgfmt_hbox.pack_start(scroll, False, False, 0)
|
||||
|
||||
vbox = gtk.VBox(False, 5)
|
||||
pkgfmt_hbox.pack_start(vbox, False, False, 15)
|
||||
|
||||
up = gtk.Button()
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_MENU)
|
||||
up.set_image(image)
|
||||
up.set_size_request(50,30)
|
||||
up.connect("clicked", cls._pkgfmt_up_clicked_cb, tree_selection)
|
||||
vbox.pack_start(up, False, False, 5)
|
||||
|
||||
down = gtk.Button()
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_MENU)
|
||||
down.set_image(image)
|
||||
down.set_size_request(50,30)
|
||||
down.connect("clicked", cls._pkgfmt_down_clicked_cb, tree_selection)
|
||||
vbox.pack_start(down, False, False, 5)
|
||||
tree_selection.connect("changed", cls._tree_selection_changed_cb, up, down)
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
pkgfmt_hbox.pack_start(image, expand=False, fill=False)
|
||||
|
||||
pkgfmt_hbox.show_all()
|
||||
|
||||
return pkgfmt_hbox, pkgfmt_store
|
||||
|
||||
@classmethod
|
||||
def gen_combo_widget(cls, curr_item, all_item, tooltip=""):
|
||||
hbox = gtk.HBox(False, 10)
|
||||
combo = gtk.combo_box_new_text()
|
||||
hbox.pack_start(combo, expand=False, fill=False)
|
||||
|
||||
index = 0
|
||||
for item in all_item or []:
|
||||
combo.append_text(item)
|
||||
if item == curr_item:
|
||||
combo.set_active(index)
|
||||
index += 1
|
||||
|
||||
image = gtk.Image()
|
||||
image.show()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
|
||||
hbox.pack_start(image, expand=False, fill=False)
|
||||
|
||||
hbox.show_all()
|
||||
|
||||
return hbox, combo
|
||||
|
||||
@classmethod
|
||||
def gen_label_widget(cls, content):
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0, 0)
|
||||
label.set_markup(content)
|
||||
label.show()
|
||||
return label
|
||||
|
||||
@classmethod
|
||||
def _select_path_cb(cls, action, parent, entry):
|
||||
dialog = gtk.FileChooserDialog("", parent,
|
||||
gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
(gtk.STOCK_OK, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
path = dialog.get_filename()
|
||||
entry.set_text(path)
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
@classmethod
|
||||
def gen_entry_widget(cls, split_model, content, parent, tooltip=""):
|
||||
hbox = gtk.HBox(False, 10)
|
||||
entry = gtk.Entry()
|
||||
entry.set_text(content)
|
||||
|
||||
if split_model:
|
||||
hbox.pack_start(entry, expand=True, fill=True)
|
||||
else:
|
||||
table = gtk.Table(1, 10, True)
|
||||
hbox.pack_start(table, expand=True, fill=True)
|
||||
table.attach(entry, 0, 9, 0, 1)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON)
|
||||
open_button = gtk.Button()
|
||||
open_button.set_image(image)
|
||||
open_button.connect("clicked", cls._select_path_cb, parent, entry)
|
||||
table.attach(open_button, 9, 10, 0, 1)
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
hbox.pack_start(image, expand=False, fill=False)
|
||||
|
||||
hbox.show_all()
|
||||
|
||||
return hbox, entry
|
||||
|
||||
@classmethod
|
||||
def gen_spinner_widget(cls, content, lower, upper, tooltip=""):
|
||||
hbox = gtk.HBox(False, 10)
|
||||
adjust = gtk.Adjustment(value=content, lower=lower, upper=upper, step_incr=1)
|
||||
spinner = gtk.SpinButton(adjustment=adjust, climb_rate=1, digits=0)
|
||||
|
||||
spinner.set_value(content)
|
||||
hbox.pack_start(spinner, expand=False, fill=False)
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
hbox.pack_start(image, expand=False, fill=False)
|
||||
|
||||
hbox.show_all()
|
||||
|
||||
return hbox, spinner
|
||||
|
||||
@classmethod
|
||||
def conf_error(cls, parent, lbl):
|
||||
dialog = CrumbsDialog(parent, lbl)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
@classmethod
|
||||
def _add_layer_cb(cls, action, layer_store, parent):
|
||||
dialog = gtk.FileChooserDialog("Add new layer", parent,
|
||||
gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
(gtk.STOCK_OK, gtk.RESPONSE_YES,
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_NO))
|
||||
label = gtk.Label("Select the layer you wish to add")
|
||||
label.show()
|
||||
dialog.set_extra_widget(label)
|
||||
response = dialog.run()
|
||||
path = dialog.get_filename()
|
||||
dialog.destroy()
|
||||
|
||||
lbl = "<b>Error</b>\nUnable to load layer <i>%s</i> because " % path
|
||||
if response == gtk.RESPONSE_YES:
|
||||
import os
|
||||
import os.path
|
||||
layers = []
|
||||
it = layer_store.get_iter_first()
|
||||
while it:
|
||||
layers.append(layer_store.get_value(it, 0))
|
||||
it = layer_store.iter_next(it)
|
||||
|
||||
if not path:
|
||||
lbl += "it is an invalid path."
|
||||
elif not os.path.exists(path+"/conf/layer.conf"):
|
||||
lbl += "there is no layer.conf inside the directory."
|
||||
elif path in layers:
|
||||
lbl += "it is already in loaded layers."
|
||||
else:
|
||||
layer_store.append([path])
|
||||
return
|
||||
cls.conf_error(parent, lbl)
|
||||
|
||||
@classmethod
|
||||
def _del_layer_cb(cls, action, tree_selection, layer_store):
|
||||
model, iter = tree_selection.get_selected()
|
||||
if iter:
|
||||
layer_store.remove(iter)
|
||||
|
||||
@classmethod
|
||||
def _toggle_layer_cb(cls, cell, path, layer_store):
|
||||
name = layer_store[path][0]
|
||||
toggle = not layer_store[path][1]
|
||||
layer_store[path][1] = toggle
|
||||
|
||||
@classmethod
|
||||
def gen_layer_widget(cls, split_model, layers, layers_avail, window, tooltip=""):
|
||||
hbox = gtk.HBox(False, 10)
|
||||
|
||||
layer_tv = gtk.TreeView()
|
||||
layer_tv.set_rules_hint(True)
|
||||
layer_tv.set_headers_visible(False)
|
||||
tree_selection = layer_tv.get_selection()
|
||||
tree_selection.set_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
col0= gtk.TreeViewColumn('Path')
|
||||
cell0 = gtk.CellRendererText()
|
||||
cell0.set_padding(5,2)
|
||||
col0.pack_start(cell0, True)
|
||||
col0.set_attributes(cell0, text=0)
|
||||
layer_tv.append_column(col0)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
scroll.add(layer_tv)
|
||||
|
||||
table_layer = gtk.Table(2, 10, False)
|
||||
hbox.pack_start(table_layer, expand=True, fill=True)
|
||||
|
||||
if split_model:
|
||||
table_layer.attach(scroll, 0, 10, 0, 2)
|
||||
|
||||
layer_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
|
||||
for layer in layers:
|
||||
layer_store.set(layer_store.append(), 0, layer, 1, True)
|
||||
for layer in layers_avail:
|
||||
if layer not in layers:
|
||||
layer_store.set(layer_store.append(), 0, layer, 1, False)
|
||||
|
||||
col1 = gtk.TreeViewColumn('Included')
|
||||
layer_tv.append_column(col1)
|
||||
|
||||
cell1 = gtk.CellRendererToggle()
|
||||
cell1.connect("toggled", cls._toggle_layer_cb, layer_store)
|
||||
col1.pack_start(cell1, True)
|
||||
col1.set_attributes(cell1, active=1)
|
||||
|
||||
else:
|
||||
table_layer.attach(scroll, 0, 10, 0, 1)
|
||||
|
||||
layer_store = gtk.ListStore(gobject.TYPE_STRING)
|
||||
for layer in layers:
|
||||
layer_store.set(layer_store.append(), 0, layer)
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_ADD,gtk.ICON_SIZE_MENU)
|
||||
add_button = gtk.Button()
|
||||
add_button.set_image(image)
|
||||
add_button.connect("clicked", cls._add_layer_cb, layer_store, window)
|
||||
table_layer.attach(add_button, 0, 5, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 0)
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_REMOVE,gtk.ICON_SIZE_MENU)
|
||||
del_button = gtk.Button()
|
||||
del_button.set_image(image)
|
||||
del_button.connect("clicked", cls._del_layer_cb, tree_selection, layer_store)
|
||||
table_layer.attach(del_button, 5, 10, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 0)
|
||||
layer_tv.set_model(layer_store)
|
||||
|
||||
hbox.show_all()
|
||||
|
||||
return hbox, layer_store
|
||||
|
||||
@classmethod
|
||||
def _toggle_single_cb(cls, cell, select_path, treeview, toggle_column):
|
||||
model = treeview.get_model()
|
||||
if not model:
|
||||
return
|
||||
iter = model.get_iter_first()
|
||||
while iter:
|
||||
path = model.get_path(iter)
|
||||
model[path][toggle_column] = False
|
||||
iter = model.iter_next(iter)
|
||||
|
||||
model[select_path][toggle_column] = True
|
||||
|
||||
@classmethod
|
||||
def gen_imgtv_widget(cls, col0_width, col1_width):
|
||||
vbox = gtk.VBox(False, 10)
|
||||
|
||||
imgsel_tv = gtk.TreeView()
|
||||
imgsel_tv.set_rules_hint(True)
|
||||
imgsel_tv.set_headers_visible(False)
|
||||
tree_selection = imgsel_tv.get_selection()
|
||||
tree_selection.set_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
col0= gtk.TreeViewColumn('Image name')
|
||||
cell0 = gtk.CellRendererText()
|
||||
cell0.set_padding(5,2)
|
||||
col0.pack_start(cell0, True)
|
||||
col0.set_attributes(cell0, text=0)
|
||||
col0.set_max_width(col0_width)
|
||||
col0.set_min_width(col0_width)
|
||||
imgsel_tv.append_column(col0)
|
||||
|
||||
col1= gtk.TreeViewColumn('Select')
|
||||
cell1 = gtk.CellRendererToggle()
|
||||
cell1.set_padding(5,2)
|
||||
cell1.connect("toggled", cls._toggle_single_cb, imgsel_tv, 1)
|
||||
col1.pack_start(cell1, True)
|
||||
col1.set_attributes(cell1, active=1)
|
||||
col1.set_max_width(col1_width)
|
||||
col1.set_min_width(col1_width)
|
||||
imgsel_tv.append_column(col1)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
scroll.add(imgsel_tv)
|
||||
|
||||
vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
return vbox, imgsel_tv
|
||||
|
||||
@classmethod
|
||||
def gen_images_widget(cls, col0_width, col1_width, col2_width):
|
||||
vbox = gtk.VBox(False, 10)
|
||||
|
||||
imgsel_tv = gtk.TreeView()
|
||||
imgsel_tv.set_rules_hint(True)
|
||||
imgsel_tv.set_headers_visible(False)
|
||||
tree_selection = imgsel_tv.get_selection()
|
||||
tree_selection.set_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
col0= gtk.TreeViewColumn('Image name')
|
||||
cell0 = gtk.CellRendererText()
|
||||
cell0.set_padding(5,2)
|
||||
col0.pack_start(cell0, True)
|
||||
col0.set_attributes(cell0, text=0)
|
||||
col0.set_max_width(col0_width)
|
||||
col0.set_min_width(col0_width)
|
||||
imgsel_tv.append_column(col0)
|
||||
|
||||
col1= gtk.TreeViewColumn('Image size')
|
||||
cell1 = gtk.CellRendererText()
|
||||
cell1.set_padding(5,2)
|
||||
col1.pack_start(cell1, True)
|
||||
col1.set_attributes(cell1, text=1)
|
||||
col1.set_max_width(col1_width)
|
||||
col1.set_min_width(col1_width)
|
||||
imgsel_tv.append_column(col1)
|
||||
|
||||
col2= gtk.TreeViewColumn('Select')
|
||||
cell2 = gtk.CellRendererToggle()
|
||||
cell2.set_padding(5,2)
|
||||
cell2.connect("toggled", cls._toggle_single_cb, imgsel_tv, 2)
|
||||
col2.pack_start(cell2, True)
|
||||
col2.set_attributes(cell2, active=2)
|
||||
col2.set_max_width(col2_width)
|
||||
col2.set_min_width(col2_width)
|
||||
imgsel_tv.append_column(col2)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
scroll.add(imgsel_tv)
|
||||
|
||||
vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
return vbox, imgsel_tv
|
||||
|
||||
@classmethod
|
||||
def _on_add_item_clicked(cls, button, model):
|
||||
new_item = ["##KEY##", "##VALUE##"]
|
||||
|
||||
iter = model.append()
|
||||
model.set (iter,
|
||||
0, new_item[0],
|
||||
1, new_item[1],
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
def _on_remove_item_clicked(cls, button, treeview):
|
||||
|
||||
selection = treeview.get_selection()
|
||||
model, iter = selection.get_selected()
|
||||
|
||||
if iter:
|
||||
path = model.get_path(iter)[0]
|
||||
model.remove(iter)
|
||||
|
||||
@classmethod
|
||||
def _on_cell_edited(cls, cell, path_string, new_text, model):
|
||||
it = model.get_iter_from_string(path_string)
|
||||
column = cell.get_data("column")
|
||||
model.set(it, column, new_text)
|
||||
|
||||
|
||||
@classmethod
|
||||
def gen_editable_settings(cls, setting, tooltip=""):
|
||||
setting_hbox = gtk.HBox(False, 10)
|
||||
|
||||
vbox = gtk.VBox(False, 10)
|
||||
setting_hbox.pack_start(vbox, expand=True, fill=True)
|
||||
|
||||
setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
for key in setting.keys():
|
||||
setting_store.set(setting_store.append(), 0, key, 1, setting[key])
|
||||
|
||||
setting_tree = gtk.TreeView(setting_store)
|
||||
setting_tree.set_headers_visible(True)
|
||||
setting_tree.set_size_request(300, 100)
|
||||
|
||||
col = gtk.TreeViewColumn('Key')
|
||||
col.set_min_width(100)
|
||||
col.set_max_width(150)
|
||||
col.set_resizable(True)
|
||||
col1 = gtk.TreeViewColumn('Value')
|
||||
col1.set_min_width(100)
|
||||
col1.set_max_width(150)
|
||||
col1.set_resizable(True)
|
||||
setting_tree.append_column(col)
|
||||
setting_tree.append_column(col1)
|
||||
cell = gtk.CellRendererText()
|
||||
cell.set_property('width-chars', 10)
|
||||
cell.set_property('editable', True)
|
||||
cell.set_data("column", 0)
|
||||
cell.connect("edited", cls._on_cell_edited, setting_store)
|
||||
cell1 = gtk.CellRendererText()
|
||||
cell1.set_property('width-chars', 10)
|
||||
cell1.set_property('editable', True)
|
||||
cell1.set_data("column", 1)
|
||||
cell1.connect("edited", cls._on_cell_edited, setting_store)
|
||||
col.pack_start(cell, True)
|
||||
col1.pack_end(cell1, True)
|
||||
col.set_attributes(cell, text=0)
|
||||
col1.set_attributes(cell1, text=1)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
scroll.add(setting_tree)
|
||||
vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
# some buttons
|
||||
hbox = gtk.HBox(True, 4)
|
||||
vbox.pack_start(hbox, False, False)
|
||||
|
||||
button = gtk.Button(stock=gtk.STOCK_ADD)
|
||||
button.connect("clicked", cls._on_add_item_clicked, setting_store)
|
||||
hbox.pack_start(button)
|
||||
|
||||
button = gtk.Button(stock=gtk.STOCK_REMOVE)
|
||||
button.connect("clicked", cls._on_remove_item_clicked, setting_tree)
|
||||
hbox.pack_start(button)
|
||||
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
|
||||
image.set_tooltip_text(tooltip)
|
||||
setting_hbox.pack_start(image, expand=False, fill=False)
|
||||
|
||||
return setting_hbox, setting_store
|
||||
|
||||
class HobViewTable (gtk.VBox):
|
||||
"""
|
||||
A VBox to contain the table for different recipe views and package view
|
||||
"""
|
||||
def __init__(self, columns, reset_clicked_cb=None, toggled_cb=None):
|
||||
gtk.VBox.__init__(self, False, 6)
|
||||
self.table_tree = gtk.TreeView()
|
||||
self.table_tree.set_headers_visible(True)
|
||||
self.table_tree.set_headers_clickable(True)
|
||||
self.table_tree.set_enable_search(True)
|
||||
self.table_tree.set_search_column(0)
|
||||
self.table_tree.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
for i in range(len(columns)):
|
||||
col = gtk.TreeViewColumn(columns[i]['col_name'])
|
||||
col.set_clickable(True)
|
||||
col.set_resizable(True)
|
||||
col.set_sort_column_id(columns[i]['col_id'])
|
||||
col.set_min_width(columns[i]['col_min'])
|
||||
col.set_max_width(columns[i]['col_max'])
|
||||
self.table_tree.append_column(col)
|
||||
|
||||
if columns[i]['col_style'] == 'toggle':
|
||||
cell = gtk.CellRendererToggle()
|
||||
cell.set_property('activatable', True)
|
||||
cell.connect("toggled", toggled_cb, self.table_tree)
|
||||
col.pack_end(cell, True)
|
||||
col.set_attributes(cell, active=columns[i]['col_id'])
|
||||
elif columns[i]['col_style'] == 'text':
|
||||
cell = gtk.CellRendererText()
|
||||
col.pack_start(cell, True)
|
||||
col.set_attributes(cell, text=columns[i]['col_id'])
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
scroll.add(self.table_tree)
|
||||
self.pack_start(scroll, True, True, 0)
|
||||
|
||||
hbox = gtk.HBox(False, 5)
|
||||
button = gtk.Button("Reset")
|
||||
button.connect('clicked', reset_clicked_cb)
|
||||
hbox.pack_end(button, False, False, 0)
|
||||
|
||||
self.pack_start(hbox, False, False, 0)
|
||||
|
||||
class HobViewBar (gtk.EventBox):
|
||||
"""
|
||||
A EventBox with the specified gray background color is associated with a notebook.
|
||||
And the toolbar to simulate the tabs.
|
||||
"""
|
||||
|
||||
def __init__(self, notebook):
|
||||
if not notebook:
|
||||
return
|
||||
self.notebook = notebook
|
||||
|
||||
# setup an event box
|
||||
gtk.EventBox.__init__(self)
|
||||
self.set_border_width(2)
|
||||
style = self.get_style().copy()
|
||||
style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color (HobColors.GRAY, False, False)
|
||||
self.set_style(style)
|
||||
|
||||
hbox = gtk.HBox()
|
||||
self.add(hbox)
|
||||
|
||||
# setup a tool bar in the event box
|
||||
self.toolbar = gtk.Toolbar()
|
||||
self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
|
||||
self.toolbar.set_style(gtk.TOOLBAR_TEXT)
|
||||
self.toolbar.set_border_width(5)
|
||||
|
||||
self.toolbuttons = []
|
||||
for index in range(self.notebook.get_n_pages()):
|
||||
child = self.notebook.get_nth_page(index)
|
||||
label = self.notebook.get_tab_label_text(child)
|
||||
tip_text = 'switch to ' + label + ' page'
|
||||
toolbutton = self.toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, None,
|
||||
label, tip_text, "Private text", None,
|
||||
self.toolbutton_cb, index)
|
||||
toolbutton.set_size_request(200, 100)
|
||||
self.toolbuttons.append(toolbutton)
|
||||
|
||||
# set the default current page
|
||||
self.modify_toolbuttons_bg(0)
|
||||
self.notebook.set_current_page(0)
|
||||
|
||||
self.toolbar.append_space()
|
||||
|
||||
# add the tool bar into the event box
|
||||
hbox.pack_start(self.toolbar, expand=False, fill=False)
|
||||
|
||||
self.search = gtk.Entry()
|
||||
self.align = gtk.Alignment(xalign=0.5, yalign=0.5)
|
||||
self.align.add(self.search)
|
||||
hbox.pack_end(self.align, expand=False, fill=False)
|
||||
|
||||
self.label = gtk.Label(" Search: ")
|
||||
self.label.set_alignment(0.5, 0.5)
|
||||
hbox.pack_end(self.label, expand=False, fill=False)
|
||||
|
||||
def toolbutton_cb(self, widget, index):
|
||||
if index >= self.notebook.get_n_pages():
|
||||
return
|
||||
self.notebook.set_current_page(index)
|
||||
self.modify_toolbuttons_bg(index)
|
||||
|
||||
def modify_toolbuttons_bg(self, index):
|
||||
if index >= len(self.toolbuttons):
|
||||
return
|
||||
for i in range(0, len(self.toolbuttons)):
|
||||
toolbutton = self.toolbuttons[i]
|
||||
if i == index:
|
||||
self.modify_toolbutton_bg(toolbutton, True)
|
||||
else:
|
||||
self.modify_toolbutton_bg(toolbutton)
|
||||
|
||||
def modify_toolbutton_bg(self, toolbutton, active=False):
|
||||
if active:
|
||||
toolbutton.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.WHITE))
|
||||
toolbutton.modify_bg(gtk.STATE_ACTIVE, gtk.gdk.Color(HobColors.WHITE))
|
||||
toolbutton.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.WHITE))
|
||||
toolbutton.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.WHITE))
|
||||
else:
|
||||
toolbutton.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.GRAY))
|
||||
toolbutton.modify_bg(gtk.STATE_ACTIVE, gtk.gdk.Color(HobColors.GRAY))
|
||||
toolbutton.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.GRAY))
|
||||
toolbutton.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.GRAY))
|
||||
|
||||
class HobXpmLabelButtonBox(gtk.EventBox):
|
||||
""" label: name of buttonbox
|
||||
description: the simple description
|
||||
"""
|
||||
|
||||
def __init__(self, display_file="", hover_file="", label="", description=""):
|
||||
gtk.EventBox.__init__(self)
|
||||
self._base_state_flags = gtk.STATE_NORMAL
|
||||
self.set_events(gtk.gdk.MOTION_NOTIFY | gtk.gdk.BUTTON_PRESS | gtk.gdk.EXPOSE)
|
||||
|
||||
self.connect("expose-event", self.cb)
|
||||
self.connect("enter-notify-event", self.pointer_enter_cb)
|
||||
self.connect("leave-notify-event", self.pointer_leave_cb)
|
||||
|
||||
self.icon_hover = gtk.Image()
|
||||
self.icon_hover.set_name("icon_image")
|
||||
if type(hover_file) == str:
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(hover_file)
|
||||
self.icon_hover.set_from_pixbuf(pixbuf)
|
||||
|
||||
self.icon_display = gtk.Image()
|
||||
self.icon_display.set_name("icon_image")
|
||||
if type(display_file) == str:
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(display_file)
|
||||
self.icon_display.set_from_pixbuf(pixbuf)
|
||||
|
||||
self.tb = gtk.Table(2, 10, True)
|
||||
self.tb.set_row_spacing(1, False)
|
||||
self.tb.set_col_spacing(1, False)
|
||||
self.add(self.tb)
|
||||
self.tb.attach(self.icon_display, 0, 2, 0, 2, 0, 0)
|
||||
self.tb.attach(self.icon_hover, 0, 2, 0, 2, 0, 0)
|
||||
|
||||
lbl = gtk.Label()
|
||||
lbl.set_alignment(0.0, 0.5)
|
||||
lbl.set_markup("<span foreground=\'#1C1C1C\' font_desc=\'18px\'>%s</span>" % label)
|
||||
self.tb.attach(lbl, 2, 10, 0, 1)
|
||||
|
||||
lbl = gtk.Label()
|
||||
lbl.set_alignment(0.0, 0.5)
|
||||
lbl.set_markup("<span foreground=\'#1C1C1C\' font_desc=\'14px\'>%s</span>" % description)
|
||||
self.tb.attach(lbl, 2, 10, 1, 2)
|
||||
|
||||
def pointer_enter_cb(self, *args):
|
||||
#if not self.is_focus():
|
||||
self.set_state(gtk.STATE_PRELIGHT)
|
||||
self._base_state_flags = gtk.STATE_PRELIGHT
|
||||
self.icon_hover.show()
|
||||
self.icon_display.hide()
|
||||
|
||||
def pointer_leave_cb(self, *args):
|
||||
self.set_state(gtk.STATE_NORMAL)
|
||||
self._base_state_flags = gtk.STATE_NORMAL
|
||||
self.icon_display.show()
|
||||
self.icon_hover.hide()
|
||||
|
||||
def cb(self, w,e):
|
||||
""" Hide items - first time """
|
||||
pass
|
||||
|
||||
358
bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py
Normal file
@@ -0,0 +1,358 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import glib
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import hic, HobXpmLabelButtonBox
|
||||
from bb.ui.crumbs.hoblistmodel import RecipeListModel
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
|
||||
from bb.ui.crumbs.hig import CrumbsDialog, BinbDialog, \
|
||||
AdvancedSettingDialog, LayerSelectionDialog
|
||||
|
||||
#
|
||||
# ImageConfigurationPage
|
||||
#
|
||||
class ImageConfigurationPage (HobPage):
|
||||
|
||||
__dummy_machine__ = "--select a machine--"
|
||||
|
||||
def __init__(self, builder):
|
||||
super(ImageConfigurationPage, self).__init__(builder, "Image configuration")
|
||||
|
||||
self.image_combo_id = None
|
||||
self.create_visual_elements()
|
||||
|
||||
def create_visual_elements(self):
|
||||
# create visual elements
|
||||
self.toolbar = gtk.Toolbar()
|
||||
self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
|
||||
self.toolbar.set_style(gtk.TOOLBAR_BOTH)
|
||||
|
||||
_, template_button = self.append_toolbar_button(self.toolbar,
|
||||
"Template",
|
||||
hic.ICON_TEMPLATES_DISPLAY_FILE,
|
||||
hic.ICON_TEMPLATES_HOVER_FILE,
|
||||
"Load a hob building template saved before",
|
||||
self.template_button_clicked_cb)
|
||||
_, my_images_button = self.append_toolbar_button(self.toolbar,
|
||||
"My images",
|
||||
hic.ICON_IMAGES_DISPLAY_FILE,
|
||||
hic.ICON_IMAGES_HOVER_FILE,
|
||||
"Open images built out previously for running or deployment",
|
||||
self.my_images_button_clicked_cb)
|
||||
_, settings_button = self.append_toolbar_button(self.toolbar,
|
||||
"Settings",
|
||||
hic.ICON_SETTINGS_DISPLAY_FILE,
|
||||
hic.ICON_SETTINGS_HOVER_FILE,
|
||||
"Other advanced settings for build",
|
||||
self.settings_button_clicked_cb)
|
||||
|
||||
self.config_top_button = self.add_onto_top_bar(self.toolbar)
|
||||
|
||||
self.gtable = gtk.Table(40, 40, True)
|
||||
self.create_config_machine()
|
||||
self.create_config_baseimg()
|
||||
self.config_build_button = self.create_config_build_button()
|
||||
|
||||
def _remove_all_widget(self):
|
||||
children = self.gtable.get_children() or []
|
||||
for child in children:
|
||||
self.gtable.remove(child)
|
||||
children = self.box_group_area.get_children() or []
|
||||
for child in children:
|
||||
self.box_group_area.remove(child)
|
||||
children = self.get_children() or []
|
||||
for child in children:
|
||||
self.remove(child)
|
||||
|
||||
def _pack_components(self):
|
||||
self._remove_all_widget()
|
||||
self.pack_start(self.config_top_button, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
self.box_group_area.pack_start(self.gtable, expand=True, fill=True)
|
||||
self.box_group_area.pack_end(self.config_build_button, expand=False, fill=False)
|
||||
|
||||
def show_machine(self):
|
||||
self._pack_components()
|
||||
self.set_config_machine_layout()
|
||||
self.show_all()
|
||||
self.progress_bar.reset()
|
||||
self.progress_bar.hide()
|
||||
self.config_build_button.hide_all()
|
||||
|
||||
def update_progress_bar(self, title, fraction, status=True):
|
||||
self.progress_bar.update(fraction)
|
||||
self.progress_bar.set_title(title)
|
||||
self.progress_bar.set_rcstyle(status)
|
||||
|
||||
def show_info_populating(self):
|
||||
self._pack_components()
|
||||
self.set_config_machine_layout()
|
||||
self.show_all()
|
||||
self.config_build_button.hide_all()
|
||||
|
||||
def show_info_populated(self):
|
||||
self._pack_components()
|
||||
self.set_config_machine_layout()
|
||||
self.set_config_baseimg_layout()
|
||||
self.show_all()
|
||||
self.progress_bar.reset()
|
||||
self.progress_bar.hide()
|
||||
|
||||
def create_config_machine(self):
|
||||
self.machine_title = gtk.Label()
|
||||
self.machine_title.set_alignment(0.0, 0.5)
|
||||
mark = "<span %s>Select a machine</span>" % self.span_tag('24px', 'bold')
|
||||
self.machine_title.set_markup(mark)
|
||||
|
||||
self.machine_title_desc = gtk.Label()
|
||||
self.machine_title_desc.set_alignment(0, 0.5)
|
||||
mark = ("<span %s>This is the profile of the target machine for which you"
|
||||
" are building the image.\n</span>") % (self.span_tag(px='14px'))
|
||||
self.machine_title_desc.set_markup(mark)
|
||||
|
||||
self.machine_combo = gtk.combo_box_new_text()
|
||||
self.machine_combo.connect("changed", self.machine_combo_changed_cb)
|
||||
|
||||
icon_file = hic.ICON_LAYERS_DISPLAY_FILE
|
||||
hover_file = hic.ICON_LAYERS_HOVER_FILE
|
||||
self.layer_button = HobXpmLabelButtonBox(icon_file, hover_file,
|
||||
"Layers", "Add support for machines, software, etc")
|
||||
self.layer_button.connect("button-release-event", self.layer_button_clicked_cb)
|
||||
|
||||
icon_file = hic.ICON_INFO_DISPLAY_FILE
|
||||
self.layer_info_icon = gtk.Image()
|
||||
pix_buffer = gtk.gdk.pixbuf_new_from_file(icon_file)
|
||||
self.layer_info_icon.set_from_pixbuf(pix_buffer)
|
||||
markup = "Layers are a powerful mechanism to extend the Yocto Project "
|
||||
markup += "with your own functionality.\n"
|
||||
markup += "For more on layers, check:\n"
|
||||
markup += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
|
||||
markup += "poky-ref-manual.html#usingpoky-changes-layers."
|
||||
self.layer_info_icon.set_tooltip_markup(markup)
|
||||
|
||||
self.progress_bar = HobProgressBar()
|
||||
self.machine_separator = gtk.HSeparator()
|
||||
|
||||
def set_config_machine_layout(self):
|
||||
self.gtable.attach(self.machine_title, 0, 40, 0, 4)
|
||||
self.gtable.attach(self.machine_title_desc, 0, 40, 4, 6)
|
||||
self.gtable.attach(self.machine_combo, 0, 12, 6, 9)
|
||||
self.gtable.attach(self.layer_button, 12, 36, 6, 10)
|
||||
self.gtable.attach(self.layer_info_icon, 36, 40, 6, 9)
|
||||
self.gtable.attach(self.progress_bar, 0, 40, 13, 17)
|
||||
self.gtable.attach(self.machine_separator, 0, 40, 12, 13)
|
||||
|
||||
def create_config_baseimg(self):
|
||||
self.image_title = gtk.Label()
|
||||
self.image_title.set_alignment(0, 1.0)
|
||||
mark = "<span %s>Select a base image</span>" % self.span_tag('24px', 'bold')
|
||||
self.image_title.set_markup(mark)
|
||||
|
||||
self.image_title_desc = gtk.Label()
|
||||
self.image_title_desc.set_alignment(0, 0.5)
|
||||
mark = ("<span %s>Base images are a starting point for the type of image you want. "
|
||||
"You can build them as \n"
|
||||
"they are or customize them to your specific needs.\n</span>") % self.span_tag('14px')
|
||||
self.image_title_desc.set_markup(mark)
|
||||
|
||||
self.image_combo = gtk.combo_box_new_text()
|
||||
self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
|
||||
|
||||
self.image_desc = gtk.Label()
|
||||
self.image_desc.set_alignment(0, 0)
|
||||
self.image_desc.set_line_wrap(True)
|
||||
|
||||
# button to view recipes
|
||||
icon_file = hic.ICON_RCIPE_DISPLAY_FILE
|
||||
hover_file = hic.ICON_RCIPE_HOVER_FILE
|
||||
self.view_recipes_button = HobXpmLabelButtonBox(icon_file, hover_file,
|
||||
"View Recipes", "Add/remove recipes and collections")
|
||||
self.view_recipes_button.connect("button-release-event", self.view_recipes_button_clicked_cb)
|
||||
|
||||
# button to view packages
|
||||
icon_file = hic.ICON_PACKAGES_DISPLAY_FILE
|
||||
hover_file = hic.ICON_PACKAGES_HOVER_FILE
|
||||
self.view_packages_button = HobXpmLabelButtonBox(icon_file, hover_file,
|
||||
"View Packages", "Add/remove packages")
|
||||
self.view_packages_button.connect("button-release-event", self.view_packages_button_clicked_cb)
|
||||
|
||||
self.image_separator = gtk.HSeparator()
|
||||
|
||||
def set_config_baseimg_layout(self):
|
||||
self.gtable.attach(self.image_title, 0, 40, 13, 17)
|
||||
self.gtable.attach(self.image_title_desc, 0, 40, 17, 22)
|
||||
self.gtable.attach(self.image_combo, 0, 12, 22, 25)
|
||||
self.gtable.attach(self.image_desc, 14, 38, 22, 27)
|
||||
self.gtable.attach(self.view_recipes_button, 0, 20, 28, 32)
|
||||
self.gtable.attach(self.view_packages_button, 20, 40, 28, 32)
|
||||
self.gtable.attach(self.image_separator, 0, 40, 35, 36)
|
||||
|
||||
def create_config_build_button(self):
|
||||
# Create the "Build packages" and "Just bake" buttons at the bottom
|
||||
button_box = gtk.HBox(False, 5)
|
||||
|
||||
# create button "Just bake"
|
||||
just_bake_button = gtk.Button()
|
||||
label = gtk.Label()
|
||||
mark = "<span %s>Just bake</span>" % self.span_tag('24px', 'bold')
|
||||
label.set_markup(mark)
|
||||
|
||||
just_bake_button.set_image(label)
|
||||
just_bake_button.set_size_request(205, 49)
|
||||
just_bake_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE))
|
||||
just_bake_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE))
|
||||
just_bake_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE))
|
||||
just_bake_button.set_tooltip_text("Build image to get your target image")
|
||||
just_bake_button.set_flags(gtk.CAN_DEFAULT)
|
||||
just_bake_button.grab_default()
|
||||
just_bake_button.connect("clicked", self.just_bake_button_clicked_cb)
|
||||
button_box.pack_end(just_bake_button, expand=False, fill=False)
|
||||
|
||||
label = gtk.Label(" or ")
|
||||
button_box.pack_end(label, expand=False, fill=False)
|
||||
|
||||
# create button "Build Packages"
|
||||
build_packages_button = gtk.LinkButton("Build packages first based on recipe selection "
|
||||
"for late customization on packages for the target image", "Build Packages")
|
||||
build_packages_button.connect("clicked", self.build_packages_button_clicked_cb)
|
||||
button_box.pack_end(build_packages_button, expand=False, fill=False)
|
||||
|
||||
return button_box
|
||||
|
||||
def machine_combo_changed_cb(self, machine_combo):
|
||||
combo_item = machine_combo.get_active_text()
|
||||
if not combo_item or combo_item == self.__dummy_machine__:
|
||||
self.builder.switch_page(self.builder.MACHINE_SELECTION)
|
||||
else:
|
||||
self.builder.configuration.curr_mach = combo_item
|
||||
# Do reparse recipes
|
||||
self.builder.switch_page(self.builder.RCPPKGINFO_POPULATING)
|
||||
|
||||
def update_machine_combo(self):
|
||||
all_machines = [self.__dummy_machine__] + self.builder.parameters.all_machines
|
||||
|
||||
model = self.machine_combo.get_model()
|
||||
model.clear()
|
||||
for machine in all_machines:
|
||||
self.machine_combo.append_text(machine)
|
||||
self.machine_combo.set_active(0)
|
||||
|
||||
def switch_machine_combo(self):
|
||||
model = self.machine_combo.get_model()
|
||||
active = 0
|
||||
while active < len(model):
|
||||
if model[active][0] == self.builder.configuration.curr_mach:
|
||||
self.machine_combo.set_active(active)
|
||||
return
|
||||
active += 1
|
||||
self.machine_combo.set_active(0)
|
||||
|
||||
def image_combo_changed_idle_cb(self, selected_image, selected_recipes, selected_packages):
|
||||
self.builder.update_recipe_model(selected_image, selected_recipes)
|
||||
self.builder.update_package_model(selected_packages)
|
||||
self.builder.window_sensitive(True)
|
||||
|
||||
def image_combo_changed_cb(self, combo):
|
||||
self.builder.window_sensitive(False)
|
||||
selected_image = self.image_combo.get_active_text()
|
||||
if not selected_image:
|
||||
return
|
||||
|
||||
selected_recipes = []
|
||||
|
||||
image_path = self.builder.recipe_model.pn_path[selected_image]
|
||||
image_iter = self.builder.recipe_model.get_iter(image_path)
|
||||
selected_packages = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_INSTALL).split()
|
||||
|
||||
mark = ("<span %s>%s</span>\n") % (self.span_tag('14px'), self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC))
|
||||
self.image_desc.set_markup(mark)
|
||||
|
||||
self.builder.recipe_model.reset()
|
||||
self.builder.package_model.reset()
|
||||
|
||||
glib.idle_add(self.image_combo_changed_idle_cb, selected_image, selected_recipes, selected_packages)
|
||||
|
||||
def _image_combo_connect_signal(self):
|
||||
if not self.image_combo_id:
|
||||
self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
|
||||
|
||||
def _image_combo_disconnect_signal(self):
|
||||
if self.image_combo_id:
|
||||
self.image_combo.disconnect(self.image_combo_id)
|
||||
self.image_combo_id = None
|
||||
|
||||
def update_image_combo(self, recipe_model, selected_image):
|
||||
# Update the image combo according to the images in the recipe_model
|
||||
# populate image combo
|
||||
filter = {RecipeListModel.COL_TYPE : ['image']}
|
||||
image_model = recipe_model.tree_model(filter)
|
||||
active = 0
|
||||
cnt = 0
|
||||
|
||||
it = image_model.get_iter_first()
|
||||
self._image_combo_disconnect_signal()
|
||||
model = self.image_combo.get_model()
|
||||
model.clear()
|
||||
# append and set active
|
||||
while it:
|
||||
path = image_model.get_path(it)
|
||||
image_name = image_model[path][recipe_model.COL_NAME]
|
||||
self.image_combo.append_text(image_name)
|
||||
if image_name == selected_image:
|
||||
active = cnt
|
||||
it = image_model.iter_next(it)
|
||||
cnt = cnt + 1
|
||||
self._image_combo_connect_signal()
|
||||
|
||||
self.image_combo.set_active(-1)
|
||||
self.image_combo.set_active(active)
|
||||
|
||||
def layer_button_clicked_cb(self, event, data):
|
||||
# Create a layer selection dialog
|
||||
self.builder.show_layer_selection_dialog()
|
||||
|
||||
def view_recipes_button_clicked_cb(self, event, data):
|
||||
self.builder.show_recipes()
|
||||
|
||||
def view_packages_button_clicked_cb(self, event, data):
|
||||
self.builder.show_packages()
|
||||
|
||||
def just_bake_button_clicked_cb(self, button):
|
||||
self.builder.just_bake()
|
||||
|
||||
def build_packages_button_clicked_cb(self, button):
|
||||
self.builder.build_packages()
|
||||
|
||||
def template_button_clicked_cb(self, button):
|
||||
self.builder.show_load_template_dialog()
|
||||
|
||||
def my_images_button_clicked_cb(self, button):
|
||||
self.builder.show_load_my_images_dialog()
|
||||
|
||||
def settings_button_clicked_cb(self, button):
|
||||
# Create an advanced settings dialog
|
||||
self.builder.show_adv_settings_dialog()
|
||||
294
bitbake/lib/bb/ui/crumbs/imagedetailspage.py
Executable file
@@ -0,0 +1,294 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import hic, HobWidget
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
|
||||
#
|
||||
# ImageDetailsPage
|
||||
#
|
||||
class ImageDetailsPage (HobPage):
|
||||
|
||||
class DetailBox (gtk.EventBox):
|
||||
def __init__(self, varlist, vallist, icon = None, button = None, color = HobColors.LIGHT_GRAY):
|
||||
gtk.EventBox.__init__(self)
|
||||
|
||||
# set color
|
||||
style = self.get_style().copy()
|
||||
style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
|
||||
self.set_style(style)
|
||||
|
||||
self.hbox = gtk.HBox()
|
||||
self.hbox.set_border_width(15)
|
||||
self.add(self.hbox)
|
||||
|
||||
# pack the icon and the text on the left
|
||||
row = len(varlist)
|
||||
self.table = gtk.Table(row, 20, True)
|
||||
self.table.set_size_request(100, -1)
|
||||
self.hbox.pack_start(self.table, expand=True, fill=True, padding=15)
|
||||
|
||||
colid = 0
|
||||
if icon != None:
|
||||
self.table.attach(icon, colid, colid + 2, 0, 1)
|
||||
colid = colid + 2
|
||||
for line in range(0, row):
|
||||
self.table.attach(self.text2label(varlist[line], vallist[line]), colid, 20, line, line + 1)
|
||||
|
||||
# pack the button on the right
|
||||
if button != None:
|
||||
self.hbox.pack_end(button, expand=False, fill=False)
|
||||
|
||||
def text2label(self, variable, value):
|
||||
# append the name:value to the left box
|
||||
# such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
|
||||
markup = "<span weight=\'bold\'>%s</span>" % variable
|
||||
markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % value
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
label.set_markup(markup)
|
||||
return label
|
||||
|
||||
def __init__(self, builder):
|
||||
super(ImageDetailsPage, self).__init__(builder, "Image details")
|
||||
|
||||
self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
|
||||
self.create_visual_elements()
|
||||
|
||||
def create_visual_elements(self):
|
||||
# create visual elements
|
||||
# create the toolbar
|
||||
self.toolbar = gtk.Toolbar()
|
||||
self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
|
||||
self.toolbar.set_style(gtk.TOOLBAR_BOTH)
|
||||
|
||||
_, my_images_button = self.append_toolbar_button(self.toolbar,
|
||||
"My images",
|
||||
hic.ICON_IMAGES_DISPLAY_FILE,
|
||||
hic.ICON_IMAGES_HOVER_FILE,
|
||||
"Open images built out previously for running or deployment",
|
||||
self.my_images_button_clicked_cb)
|
||||
|
||||
self.details_top_buttons = self.add_onto_top_bar(self.toolbar)
|
||||
|
||||
def _remove_all_widget(self):
|
||||
children = self.get_children() or []
|
||||
for child in children:
|
||||
self.remove(child)
|
||||
children = self.box_group_area.get_children() or []
|
||||
for child in children:
|
||||
self.box_group_area.remove(child)
|
||||
|
||||
def _size_to_string(self, size):
|
||||
if len(str(int(size))) > 6:
|
||||
size_str = '%.1f' % (size*1.0/(1024*1024)) + ' MB'
|
||||
elif len(str(int(size))) > 3:
|
||||
size_str = '%.1f' % (size*1.0/1024) + ' KB'
|
||||
else:
|
||||
size_str = str(size) + ' B'
|
||||
return size_str
|
||||
|
||||
def show_page(self, step):
|
||||
build_succeeded = (step == self.builder.IMAGE_GENERATED)
|
||||
image_addr = self.builder.parameters.image_addr
|
||||
image_names = self.builder.parameters.image_names
|
||||
if build_succeeded:
|
||||
image_addr = self.builder.parameters.image_addr
|
||||
image_names = self.builder.parameters.image_names
|
||||
machine = self.builder.configuration.curr_mach
|
||||
base_image = self.builder.recipe_model.get_selected_image()
|
||||
layers = self.builder.configuration.layers
|
||||
pkg_num = "%s" % len(self.builder.package_model.get_selected_packages())
|
||||
else:
|
||||
pkg_num = "N/A"
|
||||
|
||||
self._remove_all_widget()
|
||||
self.pack_start(self.details_top_buttons, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
if build_succeeded:
|
||||
# building is the previous step
|
||||
icon = gtk.Image()
|
||||
pixmap_path = hic.ICON_INDI_CONFIRM_FILE
|
||||
color = HobColors.RUNNING
|
||||
pix_buffer = gtk.gdk.pixbuf_new_from_file(pixmap_path)
|
||||
icon.set_from_pixbuf(pix_buffer)
|
||||
varlist = [""]
|
||||
vallist = ["Your image is ready"]
|
||||
build_result = self.DetailBox(varlist=varlist, vallist=vallist, icon=icon, button=None, color=color)
|
||||
self.box_group_area.pack_start(build_result, expand=False, fill=False)
|
||||
|
||||
# Name
|
||||
self.image_store.clear()
|
||||
for image_name in image_names:
|
||||
image_size = self._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size)
|
||||
self.image_store.set(self.image_store.append(), 0, image_name, 1, image_size, 2, False)
|
||||
images_widget, treeview = HobWidget.gen_images_widget(600, 200, 100)
|
||||
treeview.set_model(self.image_store)
|
||||
self.box_group_area.pack_start(images_widget, expand=False, fill=False)
|
||||
|
||||
# Machine, Base image and Layers
|
||||
layer_num_limit = 15
|
||||
varlist = ["Machine: ", "Base image: ", "Layers: "]
|
||||
vallist = []
|
||||
if build_succeeded:
|
||||
vallist.append(machine)
|
||||
vallist.append(base_image)
|
||||
i = 0
|
||||
for layer in layers:
|
||||
varlist.append(" - ")
|
||||
if i > layer_num_limit:
|
||||
break
|
||||
i += 1
|
||||
vallist.append("")
|
||||
i = 0
|
||||
for layer in layers:
|
||||
if i > layer_num_limit:
|
||||
break
|
||||
elif i == layer_num_limit:
|
||||
vallist.append("and more...")
|
||||
else:
|
||||
vallist.append(layer)
|
||||
i += 1
|
||||
|
||||
edit_config_button = gtk.LinkButton("Changes settings for build", "Edit configuration")
|
||||
edit_config_button.connect("clicked", self.edit_config_button_clicked_cb)
|
||||
setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, icon=None, button=edit_config_button)
|
||||
self.box_group_area.pack_start(setting_detail, expand=False, fill=False)
|
||||
|
||||
# Packages included, and Total image size
|
||||
varlist = ["Packages included: ", "Total image size: "]
|
||||
vallist = []
|
||||
vallist.append(pkg_num)
|
||||
vallist.append(image_size)
|
||||
if build_succeeded:
|
||||
edit_packages_button = gtk.LinkButton("Change package selection for customization", "Edit packages")
|
||||
edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb)
|
||||
else: # get to this page from "My images"
|
||||
edit_packages_button = None
|
||||
package_detail = self.DetailBox(varlist=varlist, vallist=vallist, icon=None, button=edit_packages_button)
|
||||
self.box_group_area.pack_start(package_detail, expand=False, fill=False)
|
||||
if build_succeeded:
|
||||
buttonlist = ["Build new image", "Save as template", "Run image", "Deploy image"]
|
||||
else: # get to this page from "My images"
|
||||
buttonlist = ["Build new image", "Run image", "Deploy image"]
|
||||
details_bottom_buttons = self.create_bottom_buttons(buttonlist)
|
||||
self.box_group_area.pack_end(details_bottom_buttons, expand=False, fill=False)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def create_bottom_buttons(self, buttonlist):
|
||||
# Create the buttons at the bottom
|
||||
bottom_buttons = gtk.HBox(False, 5)
|
||||
created = False
|
||||
|
||||
# create button "Deploy image"
|
||||
name = "Deploy image"
|
||||
if name in buttonlist:
|
||||
deploy_button = gtk.Button()
|
||||
label = gtk.Label()
|
||||
mark = "<span %s>Deploy image</span>" % self.span_tag('24px', 'bold')
|
||||
label.set_markup(mark)
|
||||
deploy_button.set_image(label)
|
||||
deploy_button.set_size_request(205, 49)
|
||||
deploy_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE))
|
||||
deploy_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE))
|
||||
deploy_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE))
|
||||
deploy_button.set_tooltip_text("Deploy image to get your target board")
|
||||
deploy_button.set_flags(gtk.CAN_DEFAULT)
|
||||
deploy_button.grab_default()
|
||||
deploy_button.connect("clicked", self.deploy_button_clicked_cb)
|
||||
bottom_buttons.pack_end(deploy_button, expand=False, fill=False)
|
||||
created = True
|
||||
|
||||
name = "Run image"
|
||||
if name in buttonlist:
|
||||
if created == True:
|
||||
# separator
|
||||
label = gtk.Label(" or ")
|
||||
bottom_buttons.pack_end(label, expand=False, fill=False)
|
||||
|
||||
# create button "Run image"
|
||||
run_button = gtk.LinkButton("Launch and boot the image in the QEMU emulator", "Run image")
|
||||
run_button.connect("clicked", self.run_button_clicked_cb)
|
||||
bottom_buttons.pack_end(run_button, expand=False, fill=False)
|
||||
created = True
|
||||
|
||||
name = "Save as template"
|
||||
if name in buttonlist:
|
||||
if created == True:
|
||||
# separator
|
||||
label = gtk.Label(" or ")
|
||||
bottom_buttons.pack_end(label, expand=False, fill=False)
|
||||
|
||||
# create button "Save as template"
|
||||
save_button = gtk.LinkButton("Save the hob build template for future use", "Save as template")
|
||||
save_button.connect("clicked", self.save_button_clicked_cb)
|
||||
bottom_buttons.pack_end(save_button, expand=False, fill=False)
|
||||
create = True
|
||||
|
||||
name = "Build new image"
|
||||
if name in buttonlist:
|
||||
# create button "Build new image"
|
||||
build_new_button = gtk.LinkButton("Initiate another new build from the beginning", "Build new image")
|
||||
build_new_button.connect("clicked", self.build_new_button_clicked_cb)
|
||||
bottom_buttons.pack_start(build_new_button, expand=False, fill=False)
|
||||
|
||||
return bottom_buttons
|
||||
|
||||
def _get_selected_image(self):
|
||||
image_name = ""
|
||||
iter = self.image_store.get_iter_first()
|
||||
while iter:
|
||||
path = self.image_store.get_path(iter)
|
||||
if self.image_store[path][2]:
|
||||
image_name = self.image_store[path][0]
|
||||
break
|
||||
iter = self.image_store.iter_next(iter)
|
||||
|
||||
return image_name
|
||||
|
||||
def save_button_clicked_cb(self, button):
|
||||
self.builder.show_save_template_dialog()
|
||||
|
||||
def deploy_button_clicked_cb(self, button):
|
||||
image_name = self._get_selected_image()
|
||||
self.builder.deploy_image(image_name)
|
||||
|
||||
def run_button_clicked_cb(self, button):
|
||||
image_name = self._get_selected_image()
|
||||
self.builder.runqemu_image(image_name)
|
||||
|
||||
def build_new_button_clicked_cb(self, button):
|
||||
self.builder.initiate_new_build()
|
||||
|
||||
def edit_config_button_clicked_cb(self, button):
|
||||
self.builder.show_configuration()
|
||||
|
||||
def edit_packages_button_clicked_cb(self, button):
|
||||
self.builder.show_packages(ask=False)
|
||||
|
||||
def my_images_button_clicked_cb(self, button):
|
||||
self.builder.show_load_my_images_dialog()
|
||||
@@ -1,153 +0,0 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
from bb.ui.crumbs.configurator import Configurator
|
||||
from bb.ui.crumbs.hig import CrumbsDialog
|
||||
|
||||
class LayerEditor(gtk.Dialog):
|
||||
"""
|
||||
Gtk+ Widget for enabling and disabling layers.
|
||||
Layers are added through using an open dialog to find the layer.conf
|
||||
Disabled layers are deleted from conf/bblayers.conf
|
||||
"""
|
||||
def __init__(self, configurator, parent=None):
|
||||
gtk.Dialog.__init__(self, "Layers", None,
|
||||
gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
(gtk.STOCK_CLOSE, gtk.RESPONSE_OK))
|
||||
|
||||
# We want to show a little more of the treeview in the default,
|
||||
# emptier, case
|
||||
self.set_size_request(-1, 300)
|
||||
self.set_border_width(6)
|
||||
self.vbox.set_property("spacing", 0)
|
||||
self.action_area.set_property("border-width", 6)
|
||||
|
||||
self.configurator = configurator
|
||||
self.newly_added = {}
|
||||
|
||||
# Label to inform users that meta is enabled but that you can't
|
||||
# disable it as it'd be a *bad* idea
|
||||
msg = "As the core of the build system the <i>meta</i> layer must always be included and therefore can't be viewed or edited here."
|
||||
lbl = gtk.Label()
|
||||
lbl.show()
|
||||
lbl.set_use_markup(True)
|
||||
lbl.set_markup(msg)
|
||||
lbl.set_line_wrap(True)
|
||||
lbl.set_justify(gtk.JUSTIFY_FILL)
|
||||
self.vbox.pack_start(lbl, expand=False, fill=False, padding=6)
|
||||
|
||||
# Create a treeview in which to list layers
|
||||
# ListStore of Name, Path, Enabled
|
||||
self.layer_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
|
||||
self.tv = gtk.TreeView(self.layer_store)
|
||||
self.tv.set_headers_visible(True)
|
||||
|
||||
col0 = gtk.TreeViewColumn('Name')
|
||||
self.tv.append_column(col0)
|
||||
col1 = gtk.TreeViewColumn('Path')
|
||||
self.tv.append_column(col1)
|
||||
col2 = gtk.TreeViewColumn('Enabled')
|
||||
self.tv.append_column(col2)
|
||||
|
||||
cell0 = gtk.CellRendererText()
|
||||
col0.pack_start(cell0, True)
|
||||
col0.set_attributes(cell0, text=0)
|
||||
cell1 = gtk.CellRendererText()
|
||||
col1.pack_start(cell1, True)
|
||||
col1.set_attributes(cell1, text=1)
|
||||
cell2 = gtk.CellRendererToggle()
|
||||
cell2.connect("toggled", self._toggle_layer_cb)
|
||||
col2.pack_start(cell2, True)
|
||||
col2.set_attributes(cell2, active=2)
|
||||
|
||||
self.tv.show()
|
||||
self.vbox.pack_start(self.tv, expand=True, fill=True, padding=0)
|
||||
|
||||
tb = gtk.Toolbar()
|
||||
tb.set_icon_size(gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
tb.set_style(gtk.TOOLBAR_BOTH)
|
||||
tb.set_tooltips(True)
|
||||
tb.show()
|
||||
icon = gtk.Image()
|
||||
icon.set_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
icon.show()
|
||||
tb.insert_item("Add Layer", "Add new layer", None, icon,
|
||||
self._find_layer_cb, None, -1)
|
||||
self.vbox.pack_start(tb, expand=False, fill=False, padding=0)
|
||||
|
||||
def set_parent_window(self, parent):
|
||||
self.set_transient_for(parent)
|
||||
|
||||
def load_current_layers(self, data):
|
||||
for layer, path in self.configurator.enabled_layers.items():
|
||||
if layer != 'meta':
|
||||
self.layer_store.append([layer, path, True])
|
||||
|
||||
def save_current_layers(self):
|
||||
self.configurator.writeLayerConf()
|
||||
|
||||
def _toggle_layer_cb(self, cell, path):
|
||||
name = self.layer_store[path][0]
|
||||
toggle = not self.layer_store[path][2]
|
||||
if toggle:
|
||||
self.configurator.addLayer(name, path)
|
||||
else:
|
||||
self.configurator.disableLayer(name)
|
||||
self.layer_store[path][2] = toggle
|
||||
|
||||
def _find_layer_cb(self, button):
|
||||
self.find_layer(self)
|
||||
|
||||
def find_layer(self, parent):
|
||||
def conf_error(parent, lbl):
|
||||
dialog = CrumbsDialog(parent, lbl)
|
||||
dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
dialog = gtk.FileChooserDialog("Add new layer", parent,
|
||||
gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_NO,
|
||||
gtk.STOCK_OPEN, gtk.RESPONSE_YES))
|
||||
label = gtk.Label("Select the layer.conf of the layer you wish to add")
|
||||
label.show()
|
||||
dialog.set_extra_widget(label)
|
||||
response = dialog.run()
|
||||
path = dialog.get_filename()
|
||||
dialog.destroy()
|
||||
|
||||
lbl = "<b>Error</b>\nUnable to load layer <i>%s</i> because " % path
|
||||
if response == gtk.RESPONSE_YES:
|
||||
# FIXME: verify we've actually got a layer conf?
|
||||
if path.endswith("layer.conf"):
|
||||
name, layerpath = self.configurator.addLayerConf(path)
|
||||
if name and layerpath:
|
||||
self.newly_added[name] = layerpath
|
||||
self.layer_store.append([name, layerpath, True])
|
||||
return
|
||||
elif name:
|
||||
return
|
||||
else:
|
||||
lbl += "there was a problem parsing the layer.conf."
|
||||
else:
|
||||
lbl += "it is not a layer.conf file."
|
||||
conf_error(parent, lbl)
|
||||
226
bitbake/lib/bb/ui/crumbs/packageselectionpage.py
Executable file
@@ -0,0 +1,226 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import glib
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import HobViewBar, HobViewTable
|
||||
from bb.ui.crumbs.hoblistmodel import PackageListModel
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
|
||||
#
|
||||
# PackageSelectionPage
|
||||
#
|
||||
class PackageSelectionPage (HobPage):
|
||||
|
||||
pages = [
|
||||
{
|
||||
'name' : 'All packages',
|
||||
'filter' : {},
|
||||
'columns' : [{
|
||||
'col_name' : 'Name',
|
||||
'col_id' : PackageListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'size',
|
||||
'col_id' : PackageListModel.COL_SIZE,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 500
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : PackageListModel.COL_INC,
|
||||
'col_style': 'toggle',
|
||||
'col_min' : 50,
|
||||
'col_max' : 50
|
||||
}]
|
||||
}, {
|
||||
'name' : 'Included',
|
||||
'filter' : { PackageListModel.COL_INC : [True] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Name',
|
||||
'col_id' : PackageListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300
|
||||
}, {
|
||||
'col_name' : 'Brought by',
|
||||
'col_id' : PackageListModel.COL_BINB,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 350
|
||||
}, {
|
||||
'col_name' : 'size',
|
||||
'col_id' : PackageListModel.COL_SIZE,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : PackageListModel.COL_INC,
|
||||
'col_style': 'toggle',
|
||||
'col_min' : 50,
|
||||
'col_max' : 50
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
def __init__(self, builder):
|
||||
super(PackageSelectionPage, self).__init__(builder, "Package Selection")
|
||||
|
||||
# set invisiable members
|
||||
self.package_model = self.builder.package_model
|
||||
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.label = gtk.Label("Packages included: 0\nSelected packages size: 0 MB")
|
||||
self.eventbox = self.add_onto_top_bar(self.label, 73)
|
||||
self.pack_start(self.eventbox, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
# set visiable members
|
||||
self.grid = gtk.Table(10, 1, True)
|
||||
self.grid.set_col_spacings(3)
|
||||
|
||||
self.ins = gtk.Notebook()
|
||||
self.ins.set_show_tabs(False)
|
||||
self.tables = [] # we need to modify table when the dialog is shown
|
||||
# append the tab
|
||||
for i in range(len(self.pages)):
|
||||
columns = self.pages[i]['columns']
|
||||
tab = HobViewTable(columns, self.reset_clicked_cb, self.table_toggled_cb)
|
||||
filter = self.pages[i]['filter']
|
||||
tab.table_tree.set_model(self.package_model.tree_model(filter))
|
||||
label = gtk.Label(self.pages[i]['name'])
|
||||
self.ins.append_page(tab, label)
|
||||
self.tables.append(tab)
|
||||
|
||||
self.grid.attach(self.ins, 0, 1, 1, 10, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 1, 1)
|
||||
# a black bar associated with the notebook
|
||||
self.topbar = HobViewBar(self.ins)
|
||||
self.grid.attach(self.topbar, 0, 1, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 1, 1)
|
||||
# set the search entry for each table
|
||||
for tab in self.tables:
|
||||
tab.table_tree.set_search_entry(self.topbar.search)
|
||||
|
||||
inctab_tree_view = self.tables[len(self.pages)-1].table_tree
|
||||
inctab_tree_selection = inctab_tree_view.get_selection()
|
||||
inctab_tree_selection.connect("changed", self.tree_selection_cb, inctab_tree_view)
|
||||
|
||||
# add all into the dialog
|
||||
self.box_group_area.add(self.grid)
|
||||
|
||||
button_box = gtk.HBox(False, 5)
|
||||
self.box_group_area.pack_start(button_box, expand=False, fill=False)
|
||||
|
||||
self.build_image_button = gtk.Button()
|
||||
label = gtk.Label()
|
||||
mark = "<span %s>Build image</span>" % self.span_tag('24px', 'bold')
|
||||
label.set_markup(mark)
|
||||
self.build_image_button.set_image(label)
|
||||
self.build_image_button.set_size_request(205, 49)
|
||||
self.build_image_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE))
|
||||
self.build_image_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE))
|
||||
self.build_image_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE))
|
||||
self.build_image_button.set_tooltip_text("Build image to get your target image")
|
||||
self.build_image_button.set_flags(gtk.CAN_DEFAULT)
|
||||
self.build_image_button.grab_default()
|
||||
self.build_image_button.connect("clicked", self.build_image_clicked_cb)
|
||||
button_box.pack_end(self.build_image_button, expand=False, fill=False)
|
||||
|
||||
self.back_button = gtk.LinkButton("Go back to Image Configuration screen", "<< Back to image configuration")
|
||||
self.back_button.connect("clicked", self.back_button_clicked_cb)
|
||||
button_box.pack_start(self.back_button, expand=False, fill=False)
|
||||
|
||||
def tree_selection_cb(self, tree_selection, tree_view):
|
||||
tree_model = tree_view.get_model()
|
||||
path, column = tree_view.get_cursor()
|
||||
if not path or column == tree_view.get_column(2):
|
||||
return
|
||||
|
||||
it = tree_model.get_iter(path)
|
||||
binb = tree_model.get_value(it, PackageListModel.COL_BINB)
|
||||
if binb:
|
||||
self.builder.show_binb_dialog(binb)
|
||||
|
||||
def build_image_clicked_cb(self, button):
|
||||
self.builder.build_image()
|
||||
|
||||
def back_button_clicked_cb(self, button):
|
||||
self.builder.show_configuration()
|
||||
|
||||
def _expand_all(self):
|
||||
for tab in self.tables:
|
||||
tab.table_tree.expand_all()
|
||||
|
||||
def refresh_selection(self):
|
||||
self._expand_all()
|
||||
|
||||
self.builder.configuration.selected_packages = self.package_model.get_selected_packages()
|
||||
selected_packages_num = len(self.builder.configuration.selected_packages)
|
||||
selected_packages_size = float(self.package_model.get_packages_size())
|
||||
selected_packages_size_str = self._size_to_string(selected_packages_size)
|
||||
|
||||
image_overhead_factor = self.builder.configuration.image_overhead_factor
|
||||
image_rootfs_size = self.builder.configuration.image_rootfs_size
|
||||
image_extra_size = self.builder.configuration.image_extra_size
|
||||
base_size = image_overhead_factor * selected_packages_size
|
||||
image_total_size = max(base_size, image_rootfs_size) + image_extra_size
|
||||
image_total_size_str = self._size_to_string(image_total_size)
|
||||
|
||||
self.label.set_text("Packages included: %s\nSelected packages size: %s\nTotal image size: %s" %
|
||||
(selected_packages_num, selected_packages_size_str, image_total_size_str))
|
||||
|
||||
"""
|
||||
Helper function to convert the package size to string format.
|
||||
The unit of size is KB
|
||||
"""
|
||||
def _size_to_string(self, size):
|
||||
if len(str(int(size))) > 3:
|
||||
size_str = '%.1f' % (size*1.0/1024) + ' MB'
|
||||
else:
|
||||
size_str = str(size) + ' KB'
|
||||
return size_str
|
||||
|
||||
# Callback functions
|
||||
def reset_clicked_cb(self, button):
|
||||
self.package_model.reset()
|
||||
self.builder.reset_package_model()
|
||||
|
||||
def toggle_item_idle_cb(self, path):
|
||||
if not self.package_model.path_included(path):
|
||||
self.package_model.include_item(item_path=path, binb="User Selected")
|
||||
else:
|
||||
self.package_model.exclude_item(item_path=path)
|
||||
|
||||
self.builder.window_sensitive(True)
|
||||
|
||||
def table_toggled_cb(self, cell, view_path, view_tree):
|
||||
# Click to include a package
|
||||
self.builder.window_sensitive(False)
|
||||
view_model = view_tree.get_model()
|
||||
path = self.package_model.convert_vpath_to_path(view_model, view_path)
|
||||
glib.idle_add(self.toggle_item_idle_cb, path)
|
||||
52
bitbake/lib/bb/ui/crumbs/progressbar.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
|
||||
class HobProgressBar (gtk.ProgressBar):
|
||||
def __init__(self):
|
||||
gtk.ProgressBar.__init__(self)
|
||||
self.set_rcstyle(True)
|
||||
self.percentage = 0
|
||||
|
||||
def set_rcstyle(self, status):
|
||||
rcstyle = gtk.RcStyle()
|
||||
rcstyle.fg[2] = gtk.gdk.Color(HobColors.BLACK)
|
||||
if status:
|
||||
rcstyle.bg[3] = gtk.gdk.Color(HobColors.RUNNING)
|
||||
else:
|
||||
rcstyle.bg[3] = gtk.gdk.Color(HobColors.ERROR)
|
||||
self.modify_style(rcstyle)
|
||||
|
||||
def set_title(self, text=None):
|
||||
if not text:
|
||||
text = ""
|
||||
text += " %.0f%%" % self.percentage
|
||||
self.set_text(text)
|
||||
|
||||
def reset(self):
|
||||
self.set_fraction(0)
|
||||
self.set_text("")
|
||||
self.set_rcstyle(True)
|
||||
self.percentage = 0
|
||||
|
||||
def update(self, fraction):
|
||||
self.percentage = int(fraction * 100)
|
||||
self.set_fraction(fraction)
|
||||
221
bitbake/lib/bb/ui/crumbs/recipeselectionpage.py
Executable file
@@ -0,0 +1,221 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import glib
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import HobWidget, HobViewBar, HobViewTable
|
||||
from bb.ui.crumbs.hoblistmodel import RecipeListModel
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
|
||||
#
|
||||
# RecipeSelectionPage
|
||||
#
|
||||
class RecipeSelectionPage (HobPage):
|
||||
pages = [
|
||||
{
|
||||
'name' : 'Recipe',
|
||||
'filter' : { RecipeListModel.COL_TYPE : ['recipe'] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Recipe',
|
||||
'col_id' : RecipeListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'License',
|
||||
'col_id' : RecipeListModel.COL_LIC,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'Group',
|
||||
'col_id' : RecipeListModel.COL_GROUP,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : RecipeListModel.COL_INC,
|
||||
'col_style': 'toggle',
|
||||
'col_min' : 50,
|
||||
'col_max' : 50
|
||||
}]
|
||||
}, {
|
||||
'name' : 'Recipe Collection',
|
||||
'filter' : { RecipeListModel.COL_TYPE : ['task'] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Recipe Collection',
|
||||
'col_id' : RecipeListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'Description',
|
||||
'col_id' : RecipeListModel.COL_DESC,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : RecipeListModel.COL_INC,
|
||||
'col_style': 'toggle',
|
||||
'col_min' : 50,
|
||||
'col_max' : 50
|
||||
}]
|
||||
}, {
|
||||
'name' : 'Included',
|
||||
'filter' : { RecipeListModel.COL_INC : [True],
|
||||
RecipeListModel.COL_TYPE : ['recipe', 'task'] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Recipe',
|
||||
'col_id' : RecipeListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400
|
||||
}, {
|
||||
'col_name' : 'Brought by',
|
||||
'col_id' : RecipeListModel.COL_BINB,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 500
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : RecipeListModel.COL_INC,
|
||||
'col_style': 'toggle',
|
||||
'col_min' : 50,
|
||||
'col_max' : 50
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
def __init__(self, builder = None):
|
||||
super(RecipeSelectionPage, self).__init__(builder, "Recipe Selection")
|
||||
|
||||
# set invisiable members
|
||||
self.recipe_model = self.builder.recipe_model
|
||||
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.label = gtk.Label("Recipes included: %s" % len(self.builder.configuration.selected_recipes))
|
||||
self.eventbox = self.add_onto_top_bar(self.label, 73)
|
||||
self.pack_start(self.eventbox, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
# set visiable members
|
||||
self.grid = gtk.Table(10, 1, True)
|
||||
self.grid.set_col_spacings(3)
|
||||
|
||||
# draw the left part of the window
|
||||
# a notebook
|
||||
self.ins = gtk.Notebook()
|
||||
self.ins.set_show_tabs(False)
|
||||
self.tables = [] # we need modify table when the dialog is shown
|
||||
# append the tabs in order
|
||||
for i in range(len(self.pages)):
|
||||
columns = self.pages[i]['columns']
|
||||
tab = HobViewTable(columns, self.reset_clicked_cb, self.table_toggled_cb)
|
||||
filter = self.pages[i]['filter']
|
||||
tab.table_tree.set_model(self.recipe_model.tree_model(filter))
|
||||
label = gtk.Label(self.pages[i]['name'])
|
||||
self.ins.append_page(tab, label)
|
||||
self.tables.append(tab)
|
||||
|
||||
self.grid.attach(self.ins, 0, 1, 1, 10, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND)
|
||||
# a black bar associated with the notebook
|
||||
self.topbar = HobViewBar(self.ins)
|
||||
self.grid.attach(self.topbar, 0, 1, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND)
|
||||
# set the search entry for each table
|
||||
for tab in self.tables:
|
||||
tab.table_tree.set_search_entry(self.topbar.search)
|
||||
|
||||
inctab_tree_view = self.tables[len(self.pages)-1].table_tree
|
||||
inctab_tree_selection = inctab_tree_view.get_selection()
|
||||
inctab_tree_selection.connect("changed", self.tree_selection_cb, inctab_tree_view)
|
||||
|
||||
# add all into the window
|
||||
self.box_group_area.add(self.grid)
|
||||
|
||||
button_box = gtk.HBox(False, 5)
|
||||
self.box_group_area.pack_end(button_box, expand=False, fill=False)
|
||||
|
||||
self.build_packages_button = gtk.Button()
|
||||
label = gtk.Label()
|
||||
mark = "<span %s>Build packages</span>" % self.span_tag('24px', 'bold')
|
||||
label.set_markup(mark)
|
||||
self.build_packages_button.set_image(label)
|
||||
self.build_packages_button.set_size_request(205, 49)
|
||||
self.build_packages_button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.ORANGE))
|
||||
self.build_packages_button.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.ORANGE))
|
||||
self.build_packages_button.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.ORANGE))
|
||||
self.build_packages_button.set_tooltip_text("Build packages for customization")
|
||||
self.build_packages_button.set_flags(gtk.CAN_DEFAULT)
|
||||
self.build_packages_button.grab_default()
|
||||
self.build_packages_button.connect("clicked", self.build_packages_clicked_cb)
|
||||
button_box.pack_end(self.build_packages_button, expand=False, fill=False)
|
||||
|
||||
self.back_button = gtk.LinkButton("Go back to Image Configuration screen", "<< Back to image configuration")
|
||||
self.back_button.connect("clicked", self.back_button_clicked_cb)
|
||||
button_box.pack_start(self.back_button, expand=False, fill=False)
|
||||
|
||||
def tree_selection_cb(self, tree_selection, tree_view):
|
||||
tree_model = tree_view.get_model()
|
||||
path, column = tree_view.get_cursor()
|
||||
if not path or column == tree_view.get_column(2):
|
||||
return
|
||||
|
||||
it = tree_model.get_iter(path)
|
||||
binb = tree_model.get_value(it, RecipeListModel.COL_BINB)
|
||||
if binb:
|
||||
self.builder.show_binb_dialog(binb)
|
||||
|
||||
def build_packages_clicked_cb(self, button):
|
||||
self.builder.build_packages()
|
||||
|
||||
def back_button_clicked_cb(self, button):
|
||||
self.builder.show_configuration()
|
||||
|
||||
def refresh_selection(self):
|
||||
self.builder.configuration.selected_image = self.recipe_model.get_selected_image()
|
||||
_, self.builder.configuration.selected_recipes = self.recipe_model.get_selected_recipes()
|
||||
self.label.set_text("Recipes included: %s" % len(self.builder.configuration.selected_recipes))
|
||||
|
||||
# Callback functions
|
||||
def reset_clicked_cb(self, button):
|
||||
self.builder.reset_recipe_model()
|
||||
|
||||
def toggle_item_idle_cb(self, path):
|
||||
if not self.recipe_model.path_included(path):
|
||||
self.recipe_model.include_item(item_path=path, binb="User Selected", image_contents=False)
|
||||
else:
|
||||
self.recipe_model.exclude_item(item_path=path)
|
||||
|
||||
self.builder.window_sensitive(True)
|
||||
|
||||
def table_toggled_cb(self, cell, view_path, view_tree):
|
||||
# Click to include a recipe
|
||||
self.builder.window_sensitive(False)
|
||||
view_model = view_tree.get_model()
|
||||
path = self.recipe_model.convert_vpath_to_path(view_model, view_path)
|
||||
glib.idle_add(self.toggle_item_idle_cb, path)
|
||||
@@ -25,12 +25,7 @@ import logging
|
||||
import time
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
class Colors(object):
|
||||
OK = "#ffffff"
|
||||
RUNNING = "#aaffaa"
|
||||
WARNING ="#f88017"
|
||||
ERROR = "#ffaaaa"
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
|
||||
class RunningBuildModel (gtk.TreeStore):
|
||||
(COL_LOG, COL_PACKAGE, COL_TASK, COL_MESSAGE, COL_ICON, COL_COLOR, COL_NUM_ACTIVE) = range(7)
|
||||
@@ -58,7 +53,10 @@ class RunningBuild (gobject.GObject):
|
||||
()),
|
||||
'build-complete' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
())
|
||||
()),
|
||||
'task-started' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
}
|
||||
pids_to_task = {}
|
||||
tasks_to_iter = {}
|
||||
@@ -108,13 +106,13 @@ class RunningBuild (gobject.GObject):
|
||||
|
||||
if event.levelno >= logging.ERROR:
|
||||
icon = "dialog-error"
|
||||
color = Colors.ERROR
|
||||
color = HobColors.ERROR
|
||||
elif event.levelno >= logging.WARNING:
|
||||
icon = "dialog-warning"
|
||||
color = Colors.WARNING
|
||||
color = HobColors.WARNING
|
||||
else:
|
||||
icon = None
|
||||
color = Colors.OK
|
||||
color = HobColors.OK
|
||||
|
||||
# if we know which package we belong to, we'll append onto its list.
|
||||
# otherwise, we'll jump to the top of the master list
|
||||
@@ -152,7 +150,7 @@ class RunningBuild (gobject.GObject):
|
||||
None,
|
||||
"Package: %s" % (package),
|
||||
None,
|
||||
Colors.OK,
|
||||
HobColors.OK,
|
||||
0))
|
||||
self.tasks_to_iter[(package, None)] = parent
|
||||
|
||||
@@ -160,7 +158,7 @@ class RunningBuild (gobject.GObject):
|
||||
# such.
|
||||
# @todo if parent is already in error, don't mark it green
|
||||
self.model.set(parent, self.model.COL_ICON, "gtk-execute",
|
||||
self.model.COL_COLOR, Colors.RUNNING)
|
||||
self.model.COL_COLOR, HobColors.RUNNING)
|
||||
|
||||
# Add an entry in the model for this task
|
||||
i = self.model.append (parent, (None,
|
||||
@@ -168,7 +166,7 @@ class RunningBuild (gobject.GObject):
|
||||
task,
|
||||
"Task: %s" % (task),
|
||||
"gtk-execute",
|
||||
Colors.RUNNING,
|
||||
HobColors.RUNNING,
|
||||
0))
|
||||
|
||||
# update the parent's active task count
|
||||
@@ -179,10 +177,6 @@ class RunningBuild (gobject.GObject):
|
||||
# that we need to attach to a task.
|
||||
self.tasks_to_iter[(package, task)] = i
|
||||
|
||||
# If we don't handle these the GUI does not proceed
|
||||
elif isinstance(event, bb.build.TaskInvalid):
|
||||
return
|
||||
|
||||
elif isinstance(event, bb.build.TaskBase):
|
||||
current = self.tasks_to_iter[(package, task)]
|
||||
parent = self.tasks_to_iter[(package, None)]
|
||||
@@ -194,20 +188,20 @@ class RunningBuild (gobject.GObject):
|
||||
if isinstance(event, bb.build.TaskFailed):
|
||||
# Mark the task and parent as failed
|
||||
icon = "dialog-error"
|
||||
color = Colors.ERROR
|
||||
color = HobColors.ERROR
|
||||
|
||||
logfile = event.logfile
|
||||
if logfile and os.path.exists(logfile):
|
||||
with open(logfile) as f:
|
||||
logdata = f.read()
|
||||
self.model.append(current, ('pastebin', None, None, logdata, 'gtk-error', Colors.OK, 0))
|
||||
self.model.append(current, ('pastebin', None, None, logdata, 'gtk-error', HobColors.OK, 0))
|
||||
|
||||
for i in (current, parent):
|
||||
self.model.set(i, self.model.COL_ICON, icon,
|
||||
self.model.COL_COLOR, color)
|
||||
else:
|
||||
icon = None
|
||||
color = Colors.OK
|
||||
color = HobColors.OK
|
||||
|
||||
# Mark the task as inactive
|
||||
self.model.set(current, self.model.COL_ICON, icon,
|
||||
@@ -219,7 +213,7 @@ class RunningBuild (gobject.GObject):
|
||||
if self.model.get(parent, self.model.COL_ICON) != 'dialog-error':
|
||||
self.model.set(parent, self.model.COL_ICON, icon)
|
||||
if num_active == 0:
|
||||
self.model.set(parent, self.model.COL_COLOR, Colors.OK)
|
||||
self.model.set(parent, self.model.COL_COLOR, HobColors.OK)
|
||||
|
||||
# Clear the iters and the pids since when the task goes away the
|
||||
# pid will no longer be used for messages
|
||||
@@ -234,8 +228,12 @@ class RunningBuild (gobject.GObject):
|
||||
None,
|
||||
"Build Started (%s)" % time.strftime('%m/%d/%Y %H:%M:%S'),
|
||||
None,
|
||||
Colors.OK,
|
||||
HobColors.OK,
|
||||
0))
|
||||
if pbar:
|
||||
pbar.update(0, None, bb.event.getName(event))
|
||||
pbar.set_title()
|
||||
|
||||
elif isinstance(event, bb.event.BuildCompleted):
|
||||
failures = int (event._failures)
|
||||
self.model.prepend(None, (None,
|
||||
@@ -243,7 +241,7 @@ class RunningBuild (gobject.GObject):
|
||||
None,
|
||||
"Build Completed (%s)" % time.strftime('%m/%d/%Y %H:%M:%S'),
|
||||
None,
|
||||
Colors.OK,
|
||||
HobColors.OK,
|
||||
0))
|
||||
|
||||
# Emit the appropriate signal depending on the number of failures
|
||||
@@ -254,6 +252,8 @@ class RunningBuild (gobject.GObject):
|
||||
# Emit a generic "build-complete" signal for things wishing to
|
||||
# handle when the build is finished
|
||||
self.emit("build-complete")
|
||||
if pbar:
|
||||
pbar.set_text(event.msg)
|
||||
|
||||
elif isinstance(event, bb.command.CommandFailed):
|
||||
if event.error.startswith("Exited with"):
|
||||
@@ -280,6 +280,15 @@ class RunningBuild (gobject.GObject):
|
||||
pbar.update(event.current, self.progress_total)
|
||||
elif isinstance(event, bb.event.ParseCompleted) and pbar:
|
||||
pbar.hide()
|
||||
#using runqueue events as many as possible to update the progress bar
|
||||
elif isinstance(event, (bb.runqueue.runQueueTaskStarted, bb.runqueue.sceneQueueTaskStarted)):
|
||||
message = {}
|
||||
message["eventname"] = bb.event.getName(event)
|
||||
num_of_completed = event.stats.completed + event.stats.failed
|
||||
message["current"] = num_of_completed
|
||||
message["total"] = event.stats.total
|
||||
message["title"] = ""
|
||||
self.emit("task-started", message)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -1,620 +0,0 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Joshua Lock <josh@linux.intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
import re
|
||||
|
||||
class BuildRep(gobject.GObject):
|
||||
|
||||
def __init__(self, userpkgs, allpkgs, base_image=None):
|
||||
gobject.GObject.__init__(self)
|
||||
self.base_image = base_image
|
||||
self.allpkgs = allpkgs
|
||||
self.userpkgs = userpkgs
|
||||
|
||||
def loadRecipe(self, pathname):
|
||||
contents = []
|
||||
packages = ""
|
||||
base_image = ""
|
||||
|
||||
with open(pathname, 'r') as f:
|
||||
contents = f.readlines()
|
||||
|
||||
pkg_pattern = "^\s*(IMAGE_INSTALL)\s*([+=.?]+)\s*(\".*?\")"
|
||||
img_pattern = "^\s*(require)\s+(\S+.bb)"
|
||||
|
||||
for line in contents:
|
||||
matchpkg = re.search(pkg_pattern, line)
|
||||
matchimg = re.search(img_pattern, line)
|
||||
if matchpkg:
|
||||
packages = packages + matchpkg.group(3).strip('"')
|
||||
if matchimg:
|
||||
base_image = os.path.basename(matchimg.group(2)).split(".")[0]
|
||||
|
||||
self.base_image = base_image
|
||||
self.userpkgs = packages
|
||||
|
||||
def writeRecipe(self, writepath, model):
|
||||
template = """
|
||||
# Recipe generated by the HOB
|
||||
|
||||
require %s
|
||||
|
||||
IMAGE_INSTALL += "%s"
|
||||
"""
|
||||
|
||||
empty_template = """
|
||||
# Recipe generated by the HOB
|
||||
|
||||
inherit core-image
|
||||
|
||||
IMAGE_INSTALL = "%s"
|
||||
"""
|
||||
if self.base_image and not self.base_image == "empty":
|
||||
meta_path = model.find_image_path(self.base_image)
|
||||
recipe = template % (meta_path, self.userpkgs)
|
||||
else:
|
||||
recipe = empty_template % self.allpkgs
|
||||
|
||||
if os.path.exists(writepath):
|
||||
os.rename(writepath, "%s~" % writepath)
|
||||
|
||||
with open(writepath, 'w') as r:
|
||||
r.write(recipe)
|
||||
|
||||
return writepath
|
||||
|
||||
class TaskListModel(gtk.ListStore):
|
||||
"""
|
||||
This class defines an gtk.ListStore subclass which will convert the output
|
||||
of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
|
||||
providing convenience functions to access gtk.TreeModel subclasses which
|
||||
provide filtered views of the data.
|
||||
"""
|
||||
(COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_PATH, COL_PN) = range(11)
|
||||
|
||||
__gsignals__ = {
|
||||
"tasklist-populated" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
"contents-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_INT,)),
|
||||
"image-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING,)),
|
||||
}
|
||||
|
||||
"""
|
||||
"""
|
||||
def __init__(self):
|
||||
self.contents = None
|
||||
self.tasks = None
|
||||
self.packages = None
|
||||
self.images = None
|
||||
self.selected_image = None
|
||||
|
||||
gtk.ListStore.__init__ (self,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_BOOLEAN,
|
||||
gobject.TYPE_BOOLEAN,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING)
|
||||
|
||||
"""
|
||||
Helper method to determine whether name is a target pn
|
||||
"""
|
||||
def non_target_name(self, name):
|
||||
if ('-native' in name) or ('-cross' in name) or name.startswith('virtual/'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def contents_changed_cb(self, tree_model, path, it=None):
|
||||
pkg_cnt = self.contents.iter_n_children(None)
|
||||
self.emit("contents-changed", pkg_cnt)
|
||||
|
||||
def contents_model_filter(self, model, it):
|
||||
if not model.get_value(it, self.COL_INC) or model.get_value(it, self.COL_TYPE) == 'image':
|
||||
return False
|
||||
name = model.get_value(it, self.COL_NAME)
|
||||
if self.non_target_name(name):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModel
|
||||
containing only the items which are to be included in the
|
||||
image
|
||||
"""
|
||||
def contents_model(self):
|
||||
if not self.contents:
|
||||
self.contents = self.filter_new()
|
||||
self.contents.set_visible_func(self.contents_model_filter)
|
||||
self.contents.connect("row-inserted", self.contents_changed_cb)
|
||||
self.contents.connect("row-deleted", self.contents_changed_cb)
|
||||
return self.contents
|
||||
|
||||
"""
|
||||
Helper function to determine whether an item is a task
|
||||
"""
|
||||
def task_model_filter(self, model, it):
|
||||
if model.get_value(it, self.COL_TYPE) == 'task':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModel
|
||||
containing only the items which are tasks
|
||||
"""
|
||||
def tasks_model(self):
|
||||
if not self.tasks:
|
||||
self.tasks = self.filter_new()
|
||||
self.tasks.set_visible_func(self.task_model_filter)
|
||||
return self.tasks
|
||||
|
||||
"""
|
||||
Helper function to determine whether an item is an image
|
||||
"""
|
||||
def image_model_filter(self, model, it):
|
||||
if model.get_value(it, self.COL_TYPE) == 'image':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModel
|
||||
containing only the items which are images
|
||||
"""
|
||||
def images_model(self):
|
||||
if not self.images:
|
||||
self.images = self.filter_new()
|
||||
self.images.set_visible_func(self.image_model_filter)
|
||||
return self.images
|
||||
|
||||
"""
|
||||
Helper function to determine whether an item is a package
|
||||
"""
|
||||
def package_model_filter(self, model, it):
|
||||
if model.get_value(it, self.COL_TYPE) != 'package':
|
||||
return False
|
||||
else:
|
||||
name = model.get_value(it, self.COL_NAME)
|
||||
if self.non_target_name(name):
|
||||
return False
|
||||
return True
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModel
|
||||
containing only the items which are packages
|
||||
"""
|
||||
def packages_model(self):
|
||||
if not self.packages:
|
||||
self.packages = self.filter_new()
|
||||
self.packages.set_visible_func(self.package_model_filter)
|
||||
return self.packages
|
||||
|
||||
"""
|
||||
The populate() function takes as input the data from a
|
||||
bb.event.TargetsTreeGenerated event and populates the TaskList.
|
||||
Once the population is done it emits gsignal tasklist-populated
|
||||
to notify any listeners that the model is ready
|
||||
"""
|
||||
def populate(self, event_model):
|
||||
# First clear the model, in case repopulating
|
||||
self.clear()
|
||||
for item in event_model["pn"]:
|
||||
atype = 'package'
|
||||
name = item
|
||||
summary = event_model["pn"][item]["summary"]
|
||||
lic = event_model["pn"][item]["license"]
|
||||
group = event_model["pn"][item]["section"]
|
||||
filename = event_model["pn"][item]["filename"]
|
||||
if ('task-' in name):
|
||||
atype = 'task'
|
||||
elif ('-image-' in name):
|
||||
atype = 'image'
|
||||
|
||||
# Create a combined list of build and runtime dependencies and
|
||||
# then remove any duplicate entries and any entries for -dev
|
||||
# packages
|
||||
depends = event_model["depends"].get(item, [])
|
||||
rdepends = event_model["rdepends-pn"].get(item, [])
|
||||
packages = {}
|
||||
for pkg in event_model["packages"]:
|
||||
if event_model["packages"][pkg]["pn"] == name:
|
||||
deps = []
|
||||
deps.extend(depends)
|
||||
deps.extend(event_model["rdepends-pkg"].get(pkg, []))
|
||||
deps.extend(rdepends)
|
||||
deps = self.squish(deps)
|
||||
# rdepends-pn includes pn-dev
|
||||
if ("%s-dev" % item) in deps:
|
||||
deps.remove("%s-dev" % item)
|
||||
# rdepends-on includes pn
|
||||
if pkg in deps:
|
||||
deps.remove(pkg)
|
||||
packages[pkg] = deps
|
||||
|
||||
for p in packages:
|
||||
self.set(self.append(), self.COL_NAME, p, self.COL_DESC, summary,
|
||||
self.COL_LIC, lic, self.COL_GROUP, group,
|
||||
self.COL_DEPS, " ".join(packages[p]), self.COL_BINB, "",
|
||||
self.COL_TYPE, atype, self.COL_INC, False,
|
||||
self.COL_IMG, False, self.COL_PATH, filename,
|
||||
self.COL_PN, item)
|
||||
|
||||
self.emit("tasklist-populated")
|
||||
|
||||
"""
|
||||
Load a BuildRep into the model
|
||||
"""
|
||||
def load_image_rep(self, rep):
|
||||
# Unset everything
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
path = self.get_path(it)
|
||||
self[path][self.COL_INC] = False
|
||||
self[path][self.COL_IMG] = False
|
||||
it = self.iter_next(it)
|
||||
|
||||
# Iterate the images and disable them all
|
||||
it = self.images.get_iter_first()
|
||||
while it:
|
||||
path = self.images.convert_path_to_child_path(self.images.get_path(it))
|
||||
name = self[path][self.COL_NAME]
|
||||
if name == rep.base_image:
|
||||
self.include_item(path, image_contents=True)
|
||||
else:
|
||||
self[path][self.COL_INC] = False
|
||||
it = self.images.iter_next(it)
|
||||
|
||||
# Mark all of the additional packages for inclusion
|
||||
packages = rep.userpkgs.split(" ")
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
path = self.get_path(it)
|
||||
name = self[path][self.COL_NAME]
|
||||
if name in packages:
|
||||
self.include_item(path, binb="User Selected")
|
||||
packages.remove(name)
|
||||
it = self.iter_next(it)
|
||||
|
||||
self.emit("image-changed", rep.base_image)
|
||||
|
||||
"""
|
||||
squish lst so that it doesn't contain any duplicate entries
|
||||
"""
|
||||
def squish(self, lst):
|
||||
seen = {}
|
||||
for l in lst:
|
||||
seen[l] = 1
|
||||
return seen.keys()
|
||||
|
||||
"""
|
||||
Mark the item at path as not included
|
||||
NOTE:
|
||||
path should be a gtk.TreeModelPath into self (not a filtered model)
|
||||
"""
|
||||
def remove_item_path(self, path):
|
||||
self[path][self.COL_BINB] = ""
|
||||
self[path][self.COL_INC] = False
|
||||
|
||||
"""
|
||||
Recursively called to mark the item at opath and any package which
|
||||
depends on it for removal.
|
||||
NOTE: This method dumbly removes user selected packages and since we don't
|
||||
do significant reverse dependency tracking it's easier and simpler to save
|
||||
the items marked as user selected and re-add them once the removal sweep is
|
||||
complete.
|
||||
"""
|
||||
def mark(self, opath):
|
||||
usersel = {}
|
||||
removed = []
|
||||
|
||||
it = self.get_iter_first()
|
||||
# The name of the item we're removing, so that we can use it to find
|
||||
# other items which either depend on it, or were brought in by it
|
||||
marked_name = self[opath][self.COL_NAME]
|
||||
|
||||
# Remove the passed item
|
||||
self.remove_item_path(opath)
|
||||
|
||||
# Remove all dependent packages, update binb
|
||||
while it:
|
||||
path = self.get_path(it)
|
||||
it = self.iter_next(it)
|
||||
|
||||
inc = self[path][self.COL_INC]
|
||||
deps = self[path][self.COL_DEPS]
|
||||
binb = self[path][self.COL_BINB].split(', ')
|
||||
itype = self[path][self.COL_TYPE]
|
||||
itname = self[path][self.COL_NAME]
|
||||
|
||||
# We ignore anything that isn't a package
|
||||
if not itype == "package":
|
||||
continue
|
||||
|
||||
# If the user added this item and it's not the item we're removing
|
||||
# we should keep it and its dependencies, the easiest way to do so
|
||||
# is to save its name and re-mark it for inclusion once dependency
|
||||
# processing is complete
|
||||
if "User Selected" in binb:
|
||||
usersel[itname] = self[path][self.COL_IMG]
|
||||
|
||||
# If the iterated item is included and depends on the removed
|
||||
# item it should also be removed.
|
||||
# FIXME: need to ensure partial name matching doesn't happen
|
||||
if inc and marked_name in deps and itname not in removed:
|
||||
# found a dependency, remove it
|
||||
removed.append(itname)
|
||||
self.mark(path)
|
||||
|
||||
# If the iterated item was brought in by the removed (passed) item
|
||||
# try and find an alternative dependee and update the binb column
|
||||
if inc and marked_name in binb:
|
||||
binb.remove(marked_name)
|
||||
self[path][self.COL_BINB] = ', '.join(binb).lstrip(', ')
|
||||
|
||||
# Re-add any removed user selected items
|
||||
for u in usersel:
|
||||
npath = self.find_path_for_item(u)
|
||||
self.include_item(item_path=npath,
|
||||
binb="User Selected",
|
||||
image_contents=usersel[u])
|
||||
"""
|
||||
Remove items from contents if the have an empty COL_BINB (brought in by)
|
||||
caused by all packages they are a dependency of being removed.
|
||||
If the item isn't a package we leave it included.
|
||||
"""
|
||||
def sweep_up(self):
|
||||
it = self.contents.get_iter_first()
|
||||
while it:
|
||||
binb = self.contents.get_value(it, self.COL_BINB)
|
||||
itype = self.contents.get_value(it, self.COL_TYPE)
|
||||
remove = False
|
||||
|
||||
if itype == 'package' and not binb:
|
||||
oit = self.contents.convert_iter_to_child_iter(it)
|
||||
opath = self.get_path(oit)
|
||||
self.mark(opath)
|
||||
remove = True
|
||||
|
||||
# When we remove a package from the contents model we alter the
|
||||
# model, so continuing to iterate is bad. *Furthermore* it's
|
||||
# likely that the removal has affected an already iterated item
|
||||
# so we should start from the beginning anyway.
|
||||
# Only when we've managed to iterate the entire contents model
|
||||
# without removing any items do we allow the loop to exit.
|
||||
if remove:
|
||||
it = self.contents.get_iter_first()
|
||||
else:
|
||||
it = self.contents.iter_next(it)
|
||||
|
||||
"""
|
||||
Check whether the item at item_path is included or not
|
||||
"""
|
||||
def contents_includes_path(self, item_path):
|
||||
return self[item_path][self.COL_INC]
|
||||
|
||||
"""
|
||||
Add this item, and any of its dependencies, to the image contents
|
||||
"""
|
||||
def include_item(self, item_path, binb="", image_contents=False):
|
||||
item_name = self[item_path][self.COL_NAME]
|
||||
item_deps = self[item_path][self.COL_DEPS]
|
||||
|
||||
self[item_path][self.COL_INC] = True
|
||||
|
||||
item_bin = self[item_path][self.COL_BINB].split(', ')
|
||||
if binb and not binb in item_bin:
|
||||
item_bin.append(binb)
|
||||
self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
|
||||
|
||||
# We want to do some magic with things which are brought in by the
|
||||
# base image so tag them as so
|
||||
if image_contents:
|
||||
self[item_path][self.COL_IMG] = True
|
||||
if self[item_path][self.COL_TYPE] == 'image':
|
||||
self.selected_image = item_name
|
||||
|
||||
if item_deps:
|
||||
# Ensure all of the items deps are included and, where appropriate,
|
||||
# add this item to their COL_BINB
|
||||
for dep in item_deps.split(" "):
|
||||
# If the contents model doesn't already contain dep, add it
|
||||
dep_path = self.find_path_for_item(dep)
|
||||
if not dep_path:
|
||||
continue
|
||||
dep_included = self.contents_includes_path(dep_path)
|
||||
|
||||
if dep_included and not dep in item_bin:
|
||||
# don't set the COL_BINB to this item if the target is an
|
||||
# item in our own COL_BINB
|
||||
dep_bin = self[dep_path][self.COL_BINB].split(', ')
|
||||
if not item_name in dep_bin:
|
||||
dep_bin.append(item_name)
|
||||
self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
elif not dep_included:
|
||||
self.include_item(dep_path, binb=item_name, image_contents=image_contents)
|
||||
|
||||
"""
|
||||
Find the model path for the item_name
|
||||
Returns the path in the model or None
|
||||
"""
|
||||
def find_path_for_item(self, item_name):
|
||||
# We don't include virtual/* or *-native items in the model so save a
|
||||
# heavy iteration loop by exiting early for these items
|
||||
if self.non_target_name(item_name):
|
||||
return None
|
||||
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
if (self.get_value(it, self.COL_NAME) == item_name):
|
||||
return self.get_path(it)
|
||||
else:
|
||||
it = self.iter_next(it)
|
||||
return None
|
||||
|
||||
"""
|
||||
Empty self.contents by setting the include of each entry to None
|
||||
"""
|
||||
def reset(self):
|
||||
# Deselect images - slightly more complex logic so that we don't
|
||||
# have to iterate all of the contents of the main model, instead
|
||||
# just iterate the images model.
|
||||
if self.selected_image:
|
||||
iit = self.images.get_iter_first()
|
||||
while iit:
|
||||
pit = self.images.convert_iter_to_child_iter(iit)
|
||||
self.set(pit, self.COL_INC, False)
|
||||
iit = self.images.iter_next(iit)
|
||||
self.selected_image = None
|
||||
|
||||
it = self.contents.get_iter_first()
|
||||
while it:
|
||||
oit = self.contents.convert_iter_to_child_iter(it)
|
||||
self.set(oit,
|
||||
self.COL_INC, False,
|
||||
self.COL_BINB, "",
|
||||
self.COL_IMG, False)
|
||||
# As we've just removed the first item...
|
||||
it = self.contents.get_iter_first()
|
||||
|
||||
"""
|
||||
Returns two lists. One of user selected packages and the other containing
|
||||
all selected packages
|
||||
"""
|
||||
def get_selected_packages(self):
|
||||
allpkgs = []
|
||||
userpkgs = []
|
||||
|
||||
it = self.contents.get_iter_first()
|
||||
while it:
|
||||
sel = "User Selected" in self.contents.get_value(it, self.COL_BINB)
|
||||
name = self.contents.get_value(it, self.COL_NAME)
|
||||
allpkgs.append(name)
|
||||
if sel:
|
||||
userpkgs.append(name)
|
||||
it = self.contents.iter_next(it)
|
||||
return userpkgs, allpkgs
|
||||
|
||||
"""
|
||||
Return a squished (uniquified) list of the PN's of all selected items
|
||||
"""
|
||||
def get_selected_pn(self):
|
||||
pns = []
|
||||
|
||||
it = self.contents.get_iter_first()
|
||||
while it:
|
||||
if self.contents.get_value(it, self.COL_BINB):
|
||||
pns.append(self.contents.get_value(it, self.COL_PN))
|
||||
it = self.contents.iter_next(it)
|
||||
|
||||
return self.squish(pns)
|
||||
|
||||
def image_contents_removed(self):
|
||||
it = self.get_iter_first()
|
||||
while it:
|
||||
sel = self.get_value(it, self.COL_INC)
|
||||
img = self.get_value(it, self.COL_IMG)
|
||||
if img and not sel:
|
||||
return True
|
||||
it = self.iter_next(it)
|
||||
return False
|
||||
|
||||
def get_build_rep(self):
|
||||
userpkgs, allpkgs = self.get_selected_packages()
|
||||
# If base image contents have been removed start from an empty rootfs
|
||||
if not self.selected_image or self.image_contents_removed():
|
||||
image = "empty"
|
||||
else:
|
||||
image = self.selected_image
|
||||
|
||||
return BuildRep(" ".join(userpkgs), " ".join(allpkgs), image)
|
||||
|
||||
def find_reverse_depends(self, pn):
|
||||
revdeps = []
|
||||
it = self.contents.get_iter_first()
|
||||
|
||||
while it:
|
||||
name = self.contents.get_value(it, self.COL_NAME)
|
||||
itype = self.contents.get_value(it, self.COL_TYPE)
|
||||
deps = self.contents.get_value(it, self.COL_DEPS)
|
||||
|
||||
it = self.contents.iter_next(it)
|
||||
|
||||
if not itype == 'package':
|
||||
continue
|
||||
|
||||
if pn in deps:
|
||||
revdeps.append(name)
|
||||
|
||||
if pn in revdeps:
|
||||
revdeps.remove(pn)
|
||||
return revdeps
|
||||
|
||||
def set_selected_image(self, img):
|
||||
self.selected_image = img
|
||||
path = self.find_path_for_item(img)
|
||||
self.include_item(item_path=path,
|
||||
binb="User Selected",
|
||||
image_contents=True)
|
||||
|
||||
self.emit("image-changed", self.selected_image)
|
||||
|
||||
def set_selected_packages(self, pkglist):
|
||||
selected = pkglist
|
||||
it = self.get_iter_first()
|
||||
|
||||
while it:
|
||||
name = self.get_value(it, self.COL_NAME)
|
||||
if name in pkglist:
|
||||
pkglist.remove(name)
|
||||
path = self.get_path(it)
|
||||
self.include_item(item_path=path,
|
||||
binb="User Selected")
|
||||
if len(pkglist) == 0:
|
||||
return
|
||||
it = self.iter_next(it)
|
||||
|
||||
def find_image_path(self, image):
|
||||
it = self.images.get_iter_first()
|
||||
|
||||
while it:
|
||||
image_name = self.images.get_value(it, self.COL_NAME)
|
||||
if image_name == image:
|
||||
path = self.images.get_value(it, self.COL_PATH)
|
||||
meta_pattern = "(\S*)/(meta*/)(\S*)"
|
||||
meta_match = re.search(meta_pattern, path)
|
||||
if meta_match:
|
||||
_, lyr, bbrel = path.partition(meta_match.group(2))
|
||||
if bbrel:
|
||||
path = bbrel
|
||||
return path
|
||||
it = self.images.iter_next(it)
|
||||
180
bitbake/lib/bb/ui/crumbs/template.py
Normal file
@@ -0,0 +1,180 @@
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2011 Intel Corporation
|
||||
#
|
||||
# Authored by Shane Wang <shane.wang@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import gobject
|
||||
import os
|
||||
import re
|
||||
|
||||
class File(gobject.GObject):
|
||||
|
||||
def __init__(self, pathfilename, suffix):
|
||||
if not pathfilename.endswith(suffix):
|
||||
pathfilename = "%s%s" % (pathfilename, suffix)
|
||||
gobject.GObject.__init__(self)
|
||||
self.pathfilename = pathfilename
|
||||
|
||||
def readFile(self):
|
||||
if not os.path.isfile(self.pathfilename):
|
||||
return None
|
||||
if not os.path.exists(self.pathfilename):
|
||||
return None
|
||||
|
||||
with open(self.pathfilename, 'r') as f:
|
||||
contents = f.readlines()
|
||||
f.close()
|
||||
|
||||
return contents
|
||||
|
||||
def writeFile(self, contents):
|
||||
if os.path.exists(self.pathfilename):
|
||||
orig = "%s.orig" % self.pathfilename
|
||||
if os.path.exists(orig):
|
||||
os.remove(orig)
|
||||
os.rename(self.pathfilename, orig)
|
||||
|
||||
with open(self.pathfilename, 'w') as f:
|
||||
f.write(contents)
|
||||
f.close()
|
||||
|
||||
class ConfigFile(File):
|
||||
"""
|
||||
This object does save general config file. (say bblayers.conf, or local.conf). Again, it is the base class for other template files and image bb files.
|
||||
"""
|
||||
def __init__(self, pathfilename, suffix = None, header = None):
|
||||
if suffix:
|
||||
File.__init__(self, pathfilename, suffix)
|
||||
else:
|
||||
File.__init__(self, pathfilename, ".conf")
|
||||
if header:
|
||||
self.header = header
|
||||
else:
|
||||
self.header = "# Config generated by the HOB\n\n"
|
||||
self.dictionary = {}
|
||||
|
||||
def setVar(self, var, val):
|
||||
if isinstance(val, list):
|
||||
liststr = ""
|
||||
if val:
|
||||
i = 0
|
||||
for value in val:
|
||||
if i < len(val) - 1:
|
||||
liststr += "%s " % value
|
||||
else:
|
||||
liststr += "%s" % value
|
||||
i += 1
|
||||
self.dictionary[var] = liststr
|
||||
else:
|
||||
self.dictionary[var] = val
|
||||
|
||||
def save(self):
|
||||
contents = self.header
|
||||
for var, val in self.dictionary.items():
|
||||
contents += "%s = \"%s\"\n" % (var, val)
|
||||
File.writeFile(self, contents)
|
||||
|
||||
class HobTemplateFile(ConfigFile):
|
||||
"""
|
||||
This object does save or load hob specific file.
|
||||
"""
|
||||
def __init__(self, pathfilename):
|
||||
ConfigFile.__init__(self, pathfilename, ".hob", "# Hob Template generated by the HOB\n\n")
|
||||
|
||||
def getVar(self, var):
|
||||
if var in self.dictionary:
|
||||
return self.dictionary[var]
|
||||
else:
|
||||
return ""
|
||||
|
||||
def load(self):
|
||||
contents = ConfigFile.readFile(self)
|
||||
self.dictionary.clear()
|
||||
|
||||
pattern = "^\s*(\S+)\s*=\s*(\".*?\")"
|
||||
|
||||
for line in contents:
|
||||
match = re.search(pattern, line)
|
||||
if match:
|
||||
var = match.group(1)
|
||||
val = match.group(2).strip('"')
|
||||
self.dictionary[var] = val
|
||||
return self.dictionary
|
||||
|
||||
class RecipeFile(ConfigFile):
|
||||
"""
|
||||
This object is for image bb file.
|
||||
"""
|
||||
def __init__(self, pathfilename):
|
||||
ConfigFile.__init__(self, pathfilename, ".bb", "# Recipe generated by the HOB\n\ninherit core-image\n")
|
||||
|
||||
class TemplateMgr(gobject.GObject):
|
||||
|
||||
__gLocalVars__ = ["MACHINE", "PACKAGE_CLASSES", "DISTRO", "DL_DIR", "SSTATE_DIR", "SSTATE_MIRROR", "PARALLEL_MAKE", "BB_NUMBER_THREAD"]
|
||||
__gBBLayersVars__ = ["BBLAYERS"]
|
||||
__gRecipeVars__ = ["DEPENDS", "IMAGE_INSTALL"]
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self.template_hob = None
|
||||
self.bblayers_conf = None
|
||||
self.local_conf = None
|
||||
self.image_bb = None
|
||||
|
||||
def open(self, filename, path):
|
||||
self.template_hob = HobTemplateFile("%s/%s%s%s" % (path, "template-", filename, ".hob"))
|
||||
self.bblayers_conf = ConfigFile("%s/%s%s%s" % (path, "bblayers-", filename, ".conf"))
|
||||
self.local_conf = ConfigFile("%s/%s%s%s" % (path, "local-", filename, ".conf"))
|
||||
self.image_bb = RecipeFile("%s/%s%s%s" % (path, "hob-image-", filename, ".bb"))
|
||||
|
||||
def setVar(self, var, val):
|
||||
if var in TemplateMgr.__gLocalVars__:
|
||||
self.local_conf.setVar(var, val)
|
||||
if var in TemplateMgr.__gBBLayersVars__:
|
||||
self.bblayers_conf.setVar(var, val)
|
||||
if var in TemplateMgr.__gRecipeVars__:
|
||||
self.image_bb.setVar(var, val)
|
||||
|
||||
self.template_hob.setVar(var, val)
|
||||
|
||||
def save(self):
|
||||
self.local_conf.save()
|
||||
self.bblayers_conf.save()
|
||||
self.image_bb.save()
|
||||
self.template_hob.save()
|
||||
|
||||
def load(self, path):
|
||||
self.template_hob = HobTemplateFile(path)
|
||||
self.dictionary = self.template_hob.load()
|
||||
|
||||
def getVar(self, var):
|
||||
return self.template_hob.getVar(var)
|
||||
|
||||
def destroy(self):
|
||||
if self.template_hob:
|
||||
del self.template_hob
|
||||
template_hob = None
|
||||
if self.bblayers_conf:
|
||||
del self.bblayers_conf
|
||||
self.bblayers_conf = None
|
||||
if self.local_conf:
|
||||
del self.local_conf
|
||||
self.local_conf = None
|
||||
if self.image_bb:
|
||||
del self.image_bb
|
||||
self.image_bb = None
|
||||
1111
bitbake/lib/bb/ui/hob.py
Normal file → Executable file
BIN
bitbake/lib/bb/ui/icons/images/images_display.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
bitbake/lib/bb/ui/icons/images/images_hover.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/alert.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/confirmation.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/denied.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/error.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/issues.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/refresh.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
bitbake/lib/bb/ui/icons/indicators/tick.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
bitbake/lib/bb/ui/icons/info/info_display.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
bitbake/lib/bb/ui/icons/info/info_hover.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
bitbake/lib/bb/ui/icons/layers/layers_display.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
bitbake/lib/bb/ui/icons/layers/layers_hover.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
bitbake/lib/bb/ui/icons/packages/packages_display.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
bitbake/lib/bb/ui/icons/packages/packages_hover.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
bitbake/lib/bb/ui/icons/recipe/recipe_display.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
bitbake/lib/bb/ui/icons/recipe/recipe_hover.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
bitbake/lib/bb/ui/icons/settings/settings_display.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
bitbake/lib/bb/ui/icons/settings/settings_hover.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
bitbake/lib/bb/ui/icons/templates/templates_display.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
bitbake/lib/bb/ui/icons/templates/templates_hover.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
@@ -64,6 +64,12 @@ def new_progress(msg, maxval):
|
||||
else:
|
||||
return NonInteractiveProgress(msg, maxval)
|
||||
|
||||
def pluralise(singular, plural, qty):
|
||||
if(qty == 1):
|
||||
return singular % qty
|
||||
else:
|
||||
return plural % qty
|
||||
|
||||
def main(server, eventHandler):
|
||||
|
||||
# Get values of variables which control our output
|
||||
@@ -104,13 +110,17 @@ def main(server, eventHandler):
|
||||
parseprogress = None
|
||||
cacheprogress = None
|
||||
shutdown = 0
|
||||
interrupted = False
|
||||
return_value = 0
|
||||
errors = 0
|
||||
warnings = 0
|
||||
taskfailures = []
|
||||
while True:
|
||||
try:
|
||||
event = eventHandler.waitEvent(0.25)
|
||||
if event is None:
|
||||
if shutdown > 1:
|
||||
break
|
||||
continue
|
||||
helper.eventHandler(event)
|
||||
if isinstance(event, bb.runqueue.runQueueExitWait):
|
||||
@@ -127,7 +137,7 @@ def main(server, eventHandler):
|
||||
if event.levelno >= format.ERROR:
|
||||
errors = errors + 1
|
||||
return_value = 1
|
||||
if event.levelno >= format.WARNING:
|
||||
elif event.levelno == format.WARNING:
|
||||
warnings = warnings + 1
|
||||
# For "normal" logging conditions, don't show note logs from tasks
|
||||
# but do show them if the user has changed the default log level to
|
||||
@@ -142,7 +152,7 @@ def main(server, eventHandler):
|
||||
logfile = event.logfile
|
||||
if logfile and os.path.exists(logfile):
|
||||
print("ERROR: Logfile of failure stored in: %s" % logfile)
|
||||
if 1 or includelogs:
|
||||
if includelogs and not event.errprinted:
|
||||
print("Log data follows:")
|
||||
f = open(logfile, "r")
|
||||
lines = []
|
||||
@@ -192,18 +202,19 @@ def main(server, eventHandler):
|
||||
print("Loaded %d entries from dependency cache." % event.num_entries)
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.command.CommandCompleted):
|
||||
break
|
||||
if isinstance(event, bb.command.CommandFailed):
|
||||
return_value = event.exitcode
|
||||
errors = errors + 1
|
||||
logger.error("Command execution failed: %s", event.error)
|
||||
break
|
||||
shutdown = 2
|
||||
continue
|
||||
if isinstance(event, bb.command.CommandExit):
|
||||
if not return_value:
|
||||
return_value = event.exitcode
|
||||
continue
|
||||
if isinstance(event, bb.cooker.CookerExit):
|
||||
break
|
||||
if isinstance(event, (bb.command.CommandCompleted, bb.cooker.CookerExit)):
|
||||
shutdown = 2
|
||||
continue
|
||||
if isinstance(event, bb.event.MultipleProviders):
|
||||
logger.info("multiple providers are available for %s%s (%s)", event._is_runtime and "runtime " or "",
|
||||
event._item,
|
||||
@@ -227,6 +238,10 @@ def main(server, eventHandler):
|
||||
logger.error("%s", reason)
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
|
||||
logger.info("Running setscene task %d of %d (%s)" % (event.stats.completed + event.stats.active + event.stats.failed + 1, event.stats.total, event.taskstring))
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.runqueue.runQueueTaskStarted):
|
||||
if event.noexec:
|
||||
tasktype = 'noexec task'
|
||||
@@ -240,10 +255,16 @@ def main(server, eventHandler):
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.runqueue.runQueueTaskFailed):
|
||||
taskfailures.append(event.taskstring)
|
||||
logger.error("Task %s (%s) failed with exit code '%s'",
|
||||
event.taskid, event.taskstring, event.exitcode)
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
|
||||
logger.warn("Setscene task %s (%s) failed with exit code '%s' - real task will be run instead",
|
||||
event.taskid, event.taskstring, event.exitcode)
|
||||
continue
|
||||
|
||||
# ignore
|
||||
if isinstance(event, (bb.event.BuildBase,
|
||||
bb.event.StampUpdate,
|
||||
@@ -251,7 +272,10 @@ def main(server, eventHandler):
|
||||
bb.event.RecipeParsed,
|
||||
bb.event.RecipePreFinalise,
|
||||
bb.runqueue.runQueueEvent,
|
||||
bb.runqueue.runQueueExitWait)):
|
||||
bb.runqueue.runQueueExitWait,
|
||||
bb.event.OperationStarted,
|
||||
bb.event.OperationCompleted,
|
||||
bb.event.OperationProgress)):
|
||||
continue
|
||||
|
||||
logger.error("Unknown event: %s", event)
|
||||
@@ -261,19 +285,34 @@ def main(server, eventHandler):
|
||||
if ioerror.args[0] == 4:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
if shutdown == 2:
|
||||
print("\nThird Keyboard Interrupt, exit.\n")
|
||||
break
|
||||
if shutdown == 1:
|
||||
print("\nSecond Keyboard Interrupt, stopping...\n")
|
||||
server.runCommand(["stateStop"])
|
||||
if shutdown == 0:
|
||||
interrupted = True
|
||||
print("\nKeyboard Interrupt, closing down...\n")
|
||||
server.runCommand(["stateShutdown"])
|
||||
shutdown = shutdown + 1
|
||||
pass
|
||||
|
||||
summary = ""
|
||||
if taskfailures:
|
||||
summary += pluralise("\nSummary: %s task failed:",
|
||||
"\nSummary: %s tasks failed:", len(taskfailures))
|
||||
for failure in taskfailures:
|
||||
summary += "\n %s" % failure
|
||||
if warnings:
|
||||
print("Summary: There were %s WARNING messages shown.\n" % warnings)
|
||||
summary += pluralise("\nSummary: There was %s WARNING message shown.",
|
||||
"\nSummary: There were %s WARNING messages shown.", warnings)
|
||||
if return_value:
|
||||
print("Summary: There were %s ERROR messages shown, returning a non-zero exit code.\n" % errors)
|
||||
summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
|
||||
"\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
|
||||
if summary:
|
||||
print(summary)
|
||||
|
||||
if interrupted:
|
||||
print("Execution was interrupted, returning a non-zero exit code.")
|
||||
if return_value == 0:
|
||||
return_value = 1
|
||||
|
||||
return return_value
|
||||
|
||||
@@ -28,13 +28,14 @@ import socket, threading, pickle
|
||||
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
|
||||
|
||||
class BBUIEventQueue:
|
||||
def __init__(self, BBServer):
|
||||
def __init__(self, BBServer, clientinfo=("localhost, 0")):
|
||||
|
||||
self.eventQueue = []
|
||||
self.eventQueueLock = threading.Lock()
|
||||
self.eventQueueNotify = threading.Event()
|
||||
|
||||
self.BBServer = BBServer
|
||||
self.clientinfo = clientinfo
|
||||
|
||||
self.t = threading.Thread()
|
||||
self.t.setDaemon(True)
|
||||
@@ -72,7 +73,7 @@ class BBUIEventQueue:
|
||||
|
||||
def startCallbackHandler(self):
|
||||
|
||||
server = UIXMLRPCServer()
|
||||
server = UIXMLRPCServer(self.clientinfo)
|
||||
self.host, self.port = server.socket.getsockname()
|
||||
|
||||
server.register_function( self.system_quit, "event.quit" )
|
||||
@@ -98,7 +99,7 @@ class BBUIEventQueue:
|
||||
|
||||
class UIXMLRPCServer (SimpleXMLRPCServer):
|
||||
|
||||
def __init__( self, interface = ("localhost", 0) ):
|
||||
def __init__( self, interface ):
|
||||
self.quit = False
|
||||
SimpleXMLRPCServer.__init__( self,
|
||||
interface,
|
||||
|
||||
@@ -32,11 +32,52 @@ class BBUIHelper:
|
||||
if isinstance(event, bb.build.TaskSucceeded):
|
||||
del self.running_tasks[event.pid]
|
||||
self.needUpdate = True
|
||||
if isinstance(event, bb.build.TaskFailed):
|
||||
if isinstance(event, bb.build.TaskFailed) or isinstance(event, bb.build.TaskFailedSilent):
|
||||
del self.running_tasks[event.pid]
|
||||
self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)})
|
||||
self.needUpdate = True
|
||||
|
||||
def getTasks(self):
|
||||
self.needUpdate = False
|
||||
return (self.running_tasks, self.failed_tasks)
|
||||
|
||||
def findServerDetails(self):
|
||||
import sys
|
||||
import optparse
|
||||
from bb.server.xmlrpc import BitbakeServerInfo, BitBakeServerConnection
|
||||
host = ""
|
||||
port = 0
|
||||
bind = ""
|
||||
parser = optparse.OptionParser(
|
||||
usage = """%prog -H host -P port -B bindaddr""")
|
||||
|
||||
parser.add_option("-H", "--host", help = "Bitbake server's IP address",
|
||||
action = "store", dest = "host", default = None)
|
||||
|
||||
parser.add_option("-P", "--port", help = "Bitbake server's Port number",
|
||||
action = "store", dest = "port", default = None)
|
||||
|
||||
parser.add_option("-B", "--bind", help = "Hob2 local bind address",
|
||||
action = "store", dest = "bind", default = None)
|
||||
|
||||
options, args = parser.parse_args(sys.argv)
|
||||
for key, val in options.__dict__.items():
|
||||
if key == 'host' and val:
|
||||
host = val
|
||||
elif key == 'port' and val:
|
||||
port = int(val)
|
||||
elif key == 'bind' and val:
|
||||
bind = val
|
||||
|
||||
if not host or not port or not bind:
|
||||
parser.print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
serverinfo = BitbakeServerInfo(host, port)
|
||||
clientinfo = (bind, 0)
|
||||
connection = BitBakeServerConnection(serverinfo, clientinfo)
|
||||
|
||||
server = connection.connection
|
||||
eventHandler = connection.events
|
||||
|
||||
return server, eventHandler, host, bind
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import errno
|
||||
import logging
|
||||
import bb
|
||||
import bb.msg
|
||||
import multiprocessing
|
||||
from commands import getstatusoutput
|
||||
from contextlib import contextmanager
|
||||
|
||||
@@ -862,3 +863,6 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
|
||||
if checkvalues.issubset(val):
|
||||
return truevalue
|
||||
return falsevalue
|
||||
|
||||
def cpu_count():
|
||||
return multiprocessing.cpu_count()
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import os,sys,logging
|
||||
import signal, time, atexit, threading
|
||||
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
|
||||
import xmlrpclib,sqlite3
|
||||
import xmlrpclib
|
||||
|
||||
try:
|
||||
import sqlite3
|
||||
except ImportError:
|
||||
from pysqlite2 import dbapi2 as sqlite3
|
||||
|
||||
import bb.server.xmlrpc
|
||||
import prserv
|
||||
@@ -263,7 +268,7 @@ def is_local_special(host, port):
|
||||
|
||||
def auto_start(d):
|
||||
global singleton
|
||||
if d.getVar('USE_PR_SERV', True) == '0':
|
||||
if (not d.getVar('PRSERV_HOST', True)) or (not d.getVar('PRSERV_PORT', True)):
|
||||
return True
|
||||
|
||||
if is_local_special(d.getVar('PRSERV_HOST', True), int(d.getVar('PRSERV_PORT', True))) and not singleton:
|
||||
|
||||
@@ -14,4 +14,4 @@ PACKAGES += "${PN}-tools"
|
||||
FILES_${PN}-tools = "${bindir}"
|
||||
FILES_${PN} = "${libdir}/*.so.*"
|
||||
|
||||
export VERBOSE=1
|
||||
export VERBOSE="1"
|
||||
|
||||
17
meta-hob/COPYING.MIT
Normal file
@@ -0,0 +1,17 @@
|
||||
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.
|
||||
9
meta-hob/conf/layer.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
# We have a conf and classes directory, add to BBPATH
|
||||
BBPATH := "${BBPATH}:${LAYERDIR}"
|
||||
|
||||
# We have a packages directory, add to BBFILES
|
||||
BBFILES := "${BBFILES} ${LAYERDIR}/recipes-*/*/*.bb"
|
||||
|
||||
BBFILE_COLLECTIONS += "hob"
|
||||
BBFILE_PATTERN_hob := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_hob = "1"
|
||||
1
meta-hob/recipes-core/images/hob-image.bb
Normal file
@@ -0,0 +1 @@
|
||||
inherit image
|
||||
10
meta-hob/recipes-core/meta/hob-toolchain.bb
Normal file
@@ -0,0 +1,10 @@
|
||||
DESCRIPTION = "dummy toolchain"
|
||||
LICENSE = "MIT"
|
||||
|
||||
PR = "r0"
|
||||
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=3f40d7994397109285ec7b81fdeb3b58 \
|
||||
file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
|
||||
|
||||
IMAGETEST ?= "dummy"
|
||||
inherit populate_sdk imagetest-${IMAGETEST}
|
||||
7
meta-yocto/conf/abi_version.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# OELAYOUT_ABI allows us to notify users when the format of TMPDIR changes in
|
||||
# an incompatible way. Such changes should usually be detailed in the commit
|
||||
# that breaks the format and have been previously discussed on the mailing list
|
||||
# with general agreement from the core team.
|
||||
#
|
||||
OELAYOUT_ABI = "8"
|
||||
@@ -55,6 +55,11 @@ ENABLE_WIDEC="false"
|
||||
# eglibc->bash->gettext->libc-posix-clang-wchar dependency.
|
||||
USE_NLS="no"
|
||||
|
||||
# -dev packages require pkgconfig, but it pulls in glib->dbus->shadow
|
||||
# which breaks with tiny's minimal libc.
|
||||
# -dev packages are not currently supported on poky-tiny.
|
||||
ASSUME_PROVIDED += "pkgconfig$"
|
||||
|
||||
# Reconfigure eglibc for a smaller installation
|
||||
# Comment out any of the lines below to disable them in the build
|
||||
DISTRO_FEATURES_LIBC_TINY = "libc-libm libc-crypt"
|
||||
|
||||
@@ -12,12 +12,12 @@ LOCALCONF_VERSION = "1"
|
||||
|
||||
DISTRO_FEATURES_append = " largefile opengl"
|
||||
|
||||
PREFERRED_VERSION_linux-yocto ?= "2.6.37+git%"
|
||||
PREFERRED_VERSION_linux-yocto_qemux86 ?= "3.0%"
|
||||
PREFERRED_VERSION_linux-yocto_qemux86-64 ?= "3.0%"
|
||||
PREFERRED_VERSION_linux-yocto_qemuarm ?= "3.0%"
|
||||
PREFERRED_VERSION_linux-yocto_qemumips ?= "3.0%"
|
||||
PREFERRED_VERSION_linux-yocto_qemuppc ?= "3.0%"
|
||||
PREFERRED_VERSION_linux-yocto ?= "3.0%"
|
||||
PREFERRED_VERSION_linux-yocto_qemux86 ?= "3.2%"
|
||||
PREFERRED_VERSION_linux-yocto_qemux86-64 ?= "3.2%"
|
||||
PREFERRED_VERSION_linux-yocto_qemuarm ?= "3.2%"
|
||||
PREFERRED_VERSION_linux-yocto_qemumips ?= "3.2%"
|
||||
PREFERRED_VERSION_linux-yocto_qemuppc ?= "3.2%"
|
||||
|
||||
SDK_NAME = "${DISTRO}-${TCLIBC}-${SDK_ARCH}-${TARGET_ARCH}"
|
||||
SDKPATH = "/opt/${DISTRO}/${SDK_VERSION}"
|
||||
@@ -44,19 +44,19 @@ QEMU_TARGETS ?= "arm i386 mips mipsel ppc x86_64"
|
||||
# Other QEMU_TARGETS "mips64 mips64el sh4"
|
||||
|
||||
PREMIRRORS ?= "\
|
||||
bzr://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
cvs://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
git://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
hg://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
osc://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
p4://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
svk://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
svn://.*/.* http://autobuilder.yoctoproject.org/sources/ \n"
|
||||
bzr://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
cvs://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
git://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
hg://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
osc://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
p4://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
svk://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
svn://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n"
|
||||
|
||||
MIRRORS =+ "\
|
||||
ftp://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
http://.*/.* http://autobuilder.yoctoproject.org/sources/ \n \
|
||||
https://.*/.* http://autobuilder.yoctoproject.org/sources/ \n"
|
||||
ftp://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
http://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n \
|
||||
https://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \n"
|
||||
|
||||
# The CONNECTIVITY_CHECK_URI's are used to test whether we can succesfully
|
||||
# fetch from the network (and warn you if not). To disable the test set
|
||||
@@ -65,3 +65,5 @@ CONNECTIVITY_CHECK_URIS ?= "git://git.yoctoproject.org/yocto-firewall-test;proto
|
||||
https://eula-downloads.yoctoproject.org/index.php \
|
||||
http://bugzilla.yoctoproject.org/report.cgi"
|
||||
|
||||
# Default hash policy for distro
|
||||
BB_SIGNATURE_HANDLER ?= 'OEBasicHash'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# We have a conf and classes directory, add to BBPATH
|
||||
BBPATH := "${BBPATH}:${LAYERDIR}"
|
||||
BBPATH := "${LAYERDIR}:${BBPATH}"
|
||||
|
||||
# We have a packages directory, add to BBFILES
|
||||
BBFILES := "${BBFILES} ${LAYERDIR}/recipes-*/*/*.bb \
|
||||
|
||||
@@ -115,8 +115,12 @@
|
||||
#DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
|
||||
|
||||
# The network based PR service host and port
|
||||
# Uncomment the following lines to enable PRservice.
|
||||
# Set PRSERV_HOST to 'localhost' and PRSERV_PORT to '0' to automatically
|
||||
# start local PRService.
|
||||
# Set to other values to use remote PRService.
|
||||
#PRSERV_HOST = "localhost"
|
||||
#PRSERV_PORT = "8585"
|
||||
#PRSERV_PORT = "0"
|
||||
|
||||
# Additional image generation features
|
||||
#
|
||||
@@ -130,3 +134,51 @@
|
||||
# do update(remove/add some pkgs) on it. NOTE: This is not suggested
|
||||
# when you want to create a productive rootfs
|
||||
#INC_RPM_IMAGE_GEN = "1"
|
||||
|
||||
# This is a list of packages that require a commercial license to ship
|
||||
# product. If shipped as part of an image these packages may have
|
||||
# implications so they are disabled by default. To enable them,
|
||||
# un-comment the below as appropriate.
|
||||
#LICENSE_FLAGS_WHITELIST = "commercial_gst-fluendo-mp3 \
|
||||
# commercial_gst-openmax \
|
||||
# commercial_gst-plugins-ugly \
|
||||
# commercial_lame \
|
||||
# commercial_libmad \
|
||||
# commercial_libomxil \
|
||||
# commercial_mpeg2dec \
|
||||
# commercial_qmmp"
|
||||
|
||||
|
||||
#
|
||||
# Disk space monitor, take action when the disk space or the amount of
|
||||
# inode is running low, it is enabled when BB_DISKMON_DIRS is set.
|
||||
#
|
||||
# Set the directories to monitor for disk usage, if more than one
|
||||
# directories are mounted in the same device, then only one directory
|
||||
# would be monitored since the monitor is based on the device.
|
||||
# The format is:
|
||||
# "action,directory,minimum_space,minimum_free_inode"
|
||||
#
|
||||
# The "action" must be set and should be one of:
|
||||
# ABORT: Immediately abort
|
||||
# STOPTASKS: The new tasks can't be executed any more, will stop the build
|
||||
# when the running tasks have been done.
|
||||
# WARN: show warnings (see BB_DISKMON_WARNINTERVAL for more information)
|
||||
#
|
||||
# The "directory" must be set, any directory is OK.
|
||||
#
|
||||
# Either "minimum_space" or "minimum_free_inode" (or both of them)
|
||||
# should be set, otherwise the monitor would not be enabled,
|
||||
# the unit can be G, M, K or none, but do NOT use GB, MB or KB
|
||||
# (B is not needed).
|
||||
#BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},1G,100K WARN,${SSTATE_DIR},1G,100K"
|
||||
#
|
||||
# Set disk space and inode interval (only works when the action is "WARN",
|
||||
# the unit can be G, M, or K, but do NOT use the GB, MB or KB
|
||||
# (B is not needed), the format is:
|
||||
# "disk_space_interval,disk_inode_interval", the default value is
|
||||
# "50M,5K" which means that it would warn when the free space is
|
||||
# lower than the minimum space(or inode), and would repeat the warning
|
||||
# when the disk space reduces 50M (or the amount of inode reduces 5k).
|
||||
#BB_DISKMON_WARNINTERVAL = "50M,5K"
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@ XSERVER = "xserver-xorg-lite \
|
||||
# Ship all kernel modules by default
|
||||
MACHINE_EXTRA_RRECOMMENDS = " kernel-modules"
|
||||
|
||||
# Setup sane default mixer settings
|
||||
MACHINE_EXTRA_RRECOMMENDS += "beagleboard-audio"
|
||||
|
||||
# Allow for MMC booting (required by the NAND-less Beagleboard XM)
|
||||
EXTRA_IMAGEDEPENDS += "u-boot x-load"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
require conf/machine/include/tune-mips32.inc
|
||||
|
||||
MACHINE_FEATURES = "kernel26 screen keyboard pci usbhost ext2 ext3 \
|
||||
serial usbgadget"
|
||||
serial"
|
||||
|
||||
KERNEL_IMAGETYPE = "vmlinux"
|
||||
KERNEL_ALT_IMAGETYPE = "vmlinux.bin"
|
||||
|
||||
1
meta-yocto/recipes-bsp/alsa-state/alsa-state.bbappend
Normal file
@@ -0,0 +1 @@
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
@@ -0,0 +1,656 @@
|
||||
state.omap3beagle {
|
||||
control.1 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 'Option 2 (voice/audio)'
|
||||
comment.item.1 'Option 1 (audio)'
|
||||
iface MIXER
|
||||
name 'Codec Operation Mode'
|
||||
value 'Option 1 (audio)'
|
||||
}
|
||||
control.2 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 63'
|
||||
comment.dbmin -6300
|
||||
comment.dbmax 0
|
||||
iface MIXER
|
||||
name 'DAC1 Digital Fine Playback Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.3 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 63'
|
||||
comment.dbmin -6300
|
||||
comment.dbmax 0
|
||||
iface MIXER
|
||||
name 'DAC2 Digital Fine Playback Volume'
|
||||
value.0 50
|
||||
value.1 50
|
||||
}
|
||||
control.4 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 2'
|
||||
comment.dbmin 0
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'DAC1 Digital Coarse Playback Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.5 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 2'
|
||||
comment.dbmin 0
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'DAC2 Digital Coarse Playback Volume'
|
||||
value.0 2
|
||||
value.1 2
|
||||
}
|
||||
control.6 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 18'
|
||||
comment.dbmin -2400
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'DAC1 Analog Playback Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.7 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 18'
|
||||
comment.dbmin -2400
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'DAC2 Analog Playback Volume'
|
||||
value.0 15
|
||||
value.1 15
|
||||
}
|
||||
control.8 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 2
|
||||
iface MIXER
|
||||
name 'DAC1 Analog Playback Switch'
|
||||
value.0 false
|
||||
value.1 false
|
||||
}
|
||||
control.9 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 2
|
||||
iface MIXER
|
||||
name 'DAC2 Analog Playback Switch'
|
||||
value.0 true
|
||||
value.1 true
|
||||
}
|
||||
control.10 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 1
|
||||
comment.range '0 - 49'
|
||||
comment.dbmin -3700
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'DAC Voice Digital Downlink Volume'
|
||||
value 0
|
||||
}
|
||||
control.11 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 1
|
||||
comment.range '0 - 18'
|
||||
comment.dbmin -2400
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'DAC Voice Analog Downlink Volume'
|
||||
value 18
|
||||
}
|
||||
control.12 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'DAC Voice Analog Downlink Switch'
|
||||
value false
|
||||
}
|
||||
control.13 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 3'
|
||||
comment.dbmin -1200
|
||||
comment.dbmax 600
|
||||
iface MIXER
|
||||
name 'PreDriv Playback Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.14 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 3'
|
||||
comment.dbmin -1200
|
||||
comment.dbmax 600
|
||||
iface MIXER
|
||||
name 'Headset Playback Volume'
|
||||
value.0 3
|
||||
value.1 3
|
||||
}
|
||||
control.15 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 3'
|
||||
comment.dbmin -1200
|
||||
comment.dbmax 600
|
||||
iface MIXER
|
||||
name 'Carkit Playback Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.16 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 1
|
||||
comment.range '0 - 3'
|
||||
comment.dbmin -600
|
||||
comment.dbmax 1200
|
||||
iface MIXER
|
||||
name 'Earpiece Playback Volume'
|
||||
value 0
|
||||
}
|
||||
control.17 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 31'
|
||||
comment.dbmin 0
|
||||
comment.dbmax 3100
|
||||
iface MIXER
|
||||
name 'TX1 Digital Capture Volume'
|
||||
value.0 12
|
||||
value.1 12
|
||||
}
|
||||
control.18 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 31'
|
||||
comment.dbmin 0
|
||||
comment.dbmax 3100
|
||||
iface MIXER
|
||||
name 'TX2 Digital Capture Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.19 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 2
|
||||
comment.range '0 - 5'
|
||||
comment.dbmin 0
|
||||
comment.dbmax 3000
|
||||
iface MIXER
|
||||
name 'Analog Capture Volume'
|
||||
value.0 0
|
||||
value.1 0
|
||||
}
|
||||
control.20 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 'Voice high priority'
|
||||
comment.item.1 'HiFi high priority'
|
||||
iface MIXER
|
||||
name 'AVADC Clock Priority'
|
||||
value 'Voice high priority'
|
||||
}
|
||||
control.21 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 '27/20/14 ms'
|
||||
comment.item.1 '55/40/27 ms'
|
||||
comment.item.2 '109/81/55 ms'
|
||||
comment.item.3 '218/161/109 ms'
|
||||
comment.item.4 '437/323/218 ms'
|
||||
comment.item.5 '874/645/437 ms'
|
||||
comment.item.6 '1748/1291/874 ms'
|
||||
comment.item.7 '3495/2581/1748 ms'
|
||||
iface MIXER
|
||||
name 'HS ramp delay'
|
||||
value '27/20/14 ms'
|
||||
}
|
||||
control.22 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 'Vibra H-bridge direction'
|
||||
comment.item.1 'Audio data MSB'
|
||||
iface MIXER
|
||||
name 'Vibra H-bridge mode'
|
||||
value 'Vibra H-bridge direction'
|
||||
}
|
||||
control.23 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 'Positive polarity'
|
||||
comment.item.1 'Negative polarity'
|
||||
iface MIXER
|
||||
name 'Vibra H-bridge direction'
|
||||
value 'Positive polarity'
|
||||
}
|
||||
control.24 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Analog Right Sub Mic Capture Switch'
|
||||
value false
|
||||
}
|
||||
control.25 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Analog Right AUXR Capture Switch'
|
||||
value true
|
||||
}
|
||||
control.26 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Analog Left Main Mic Capture Switch'
|
||||
value false
|
||||
}
|
||||
control.27 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Analog Left Headset Mic Capture Switch'
|
||||
value false
|
||||
}
|
||||
control.28 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Analog Left AUXL Capture Switch'
|
||||
value true
|
||||
}
|
||||
control.29 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Analog Left Carkit Mic Capture Switch'
|
||||
value false
|
||||
}
|
||||
control.30 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 Analog
|
||||
comment.item.1 Digimic1
|
||||
iface MIXER
|
||||
name 'TX2 Capture Route'
|
||||
value Analog
|
||||
}
|
||||
control.31 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 Analog
|
||||
comment.item.1 Digimic0
|
||||
iface MIXER
|
||||
name 'TX1 Capture Route'
|
||||
value Analog
|
||||
}
|
||||
control.32 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 'Local vibrator'
|
||||
comment.item.1 Audio
|
||||
iface MIXER
|
||||
name 'Vibra Route'
|
||||
value 'Local vibrator'
|
||||
}
|
||||
control.33 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 AudioL1
|
||||
comment.item.1 AudioR1
|
||||
comment.item.2 AudioL2
|
||||
comment.item.3 AudioR2
|
||||
iface MIXER
|
||||
name 'Vibra Mux'
|
||||
value AudioL1
|
||||
}
|
||||
control.34 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HandsfreeR Switch'
|
||||
value false
|
||||
}
|
||||
control.35 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 Voice
|
||||
comment.item.1 AudioR1
|
||||
comment.item.2 AudioR2
|
||||
comment.item.3 AudioL2
|
||||
iface MIXER
|
||||
name 'HandsfreeR Mux'
|
||||
value Voice
|
||||
}
|
||||
control.36 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HandsfreeL Switch'
|
||||
value false
|
||||
}
|
||||
control.37 {
|
||||
comment.access 'read write'
|
||||
comment.type ENUMERATED
|
||||
comment.count 1
|
||||
comment.item.0 Voice
|
||||
comment.item.1 AudioL1
|
||||
comment.item.2 AudioL2
|
||||
comment.item.3 AudioR2
|
||||
iface MIXER
|
||||
name 'HandsfreeL Mux'
|
||||
value Voice
|
||||
}
|
||||
control.38 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'CarkitR Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.39 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'CarkitR Mixer AudioR1'
|
||||
value false
|
||||
}
|
||||
control.40 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'CarkitR Mixer AudioR2'
|
||||
value false
|
||||
}
|
||||
control.41 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'CarkitL Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.42 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'CarkitL Mixer AudioL1'
|
||||
value false
|
||||
}
|
||||
control.43 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'CarkitL Mixer AudioL2'
|
||||
value false
|
||||
}
|
||||
control.44 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HeadsetR Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.45 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HeadsetR Mixer AudioR1'
|
||||
value false
|
||||
}
|
||||
control.46 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HeadsetR Mixer AudioR2'
|
||||
value true
|
||||
}
|
||||
control.47 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HeadsetL Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.48 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HeadsetL Mixer AudioL1'
|
||||
value false
|
||||
}
|
||||
control.49 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'HeadsetL Mixer AudioL2'
|
||||
value true
|
||||
}
|
||||
control.50 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveR Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.51 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveR Mixer AudioR1'
|
||||
value false
|
||||
}
|
||||
control.52 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveR Mixer AudioR2'
|
||||
value false
|
||||
}
|
||||
control.53 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveR Mixer AudioL2'
|
||||
value false
|
||||
}
|
||||
control.54 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveL Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.55 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveL Mixer AudioL1'
|
||||
value false
|
||||
}
|
||||
control.56 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveL Mixer AudioL2'
|
||||
value false
|
||||
}
|
||||
control.57 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'PredriveL Mixer AudioR2'
|
||||
value false
|
||||
}
|
||||
control.58 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Earpiece Mixer Voice'
|
||||
value false
|
||||
}
|
||||
control.59 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Earpiece Mixer AudioL1'
|
||||
value false
|
||||
}
|
||||
control.60 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Earpiece Mixer AudioL2'
|
||||
value false
|
||||
}
|
||||
control.61 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Earpiece Mixer AudioR1'
|
||||
value false
|
||||
}
|
||||
control.62 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 1
|
||||
comment.range '0 - 41'
|
||||
comment.dbmin -5100
|
||||
comment.dbmax -1000
|
||||
iface MIXER
|
||||
name 'Voice Digital Loopback Volume'
|
||||
value 0
|
||||
}
|
||||
control.63 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 1
|
||||
comment.range '0 - 7'
|
||||
comment.dbmin -2400
|
||||
comment.dbmax 0
|
||||
iface MIXER
|
||||
name 'Right Digital Loopback Volume'
|
||||
value 0
|
||||
}
|
||||
control.64 {
|
||||
comment.access 'read write'
|
||||
comment.type INTEGER
|
||||
comment.count 1
|
||||
comment.range '0 - 7'
|
||||
comment.dbmin -2400
|
||||
comment.dbmax 0
|
||||
iface MIXER
|
||||
name 'Left Digital Loopback Volume'
|
||||
value 0
|
||||
}
|
||||
control.65 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Voice Analog Loopback Switch'
|
||||
value false
|
||||
}
|
||||
control.66 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Left2 Analog Loopback Switch'
|
||||
value false
|
||||
}
|
||||
control.67 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Right2 Analog Loopback Switch'
|
||||
value false
|
||||
}
|
||||
control.68 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Left1 Analog Loopback Switch'
|
||||
value false
|
||||
}
|
||||
control.69 {
|
||||
comment.access 'read write'
|
||||
comment.type BOOLEAN
|
||||
comment.count 1
|
||||
iface MIXER
|
||||
name 'Right1 Analog Loopback Switch'
|
||||
value false
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
SUMMARY = "Provide a basic init script to enable audio"
|
||||
DESCRIPTION = "Set the volume and unmute the Front mixer setting during boot."
|
||||
SECTION = "base"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=3f40d7994397109285ec7b81fdeb3b58"
|
||||
|
||||
PR = "r5"
|
||||
|
||||
inherit update-rc.d
|
||||
|
||||
RDEPENDS_${PN} = "alsa-utils-amixer"
|
||||
|
||||
SRC_URI = "file://beagleboard-audio"
|
||||
|
||||
INITSCRIPT_NAME = "beagleboard-audio"
|
||||
INITSCRIPT_PARAMS = "defaults 90"
|
||||
|
||||
COMPATIBLE_MACHINE = "beagleboard"
|
||||
INHIBIT_DEFAULT_DEPS = "1"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${sysconfdir} \
|
||||
${D}${sysconfdir}/init.d
|
||||
install -m 0755 ${WORKDIR}/beagleboard-audio ${D}${sysconfdir}/init.d
|
||||
cat ${WORKDIR}/${INITSCRIPT_NAME} | \
|
||||
sed -e 's,/etc,${sysconfdir},g' \
|
||||
-e 's,/usr/sbin,${sbindir},g' \
|
||||
-e 's,/var,${localstatedir},g' \
|
||||
-e 's,/usr/bin,${bindir},g' \
|
||||
-e 's,/usr,${prefix},g' > ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME}
|
||||
chmod 755 ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: beagleboard mixer setup
|
||||
# Required-Start: $syslog
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Initialize the beagleboard audio mixer
|
||||
# Description: Unmute FRONT and set volume to ~70%.
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Darren Hart <dvhart@linux.intel.com>
|
||||
# Based on /etc/init.d/skeleton
|
||||
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="Audio mixer settings"
|
||||
NAME=beagleboard-audio
|
||||
AMIXER=`which amixer`
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
|
||||
# Exit if amixer is not installed
|
||||
[ -x "$AMIXER" ] || exit 0
|
||||
|
||||
do_start() {
|
||||
# Enable the Headset (Audio Out)
|
||||
$AMIXER sset "Headset" 2 > /dev/null
|
||||
$AMIXER sset "HeadsetL Mixer AudioL1" on > /dev/null
|
||||
$AMIXER sset "HeadsetR Mixer AudioR1" on > /dev/null
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "$NAME: setting default mixer settings."
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
914
meta-yocto/recipes-core/psplash/files/psplash-poky-img.h
Normal file
@@ -0,0 +1,914 @@
|
||||
/* Yocto Project logo for psplash
|
||||
*
|
||||
* Created using make-image-header.sh (distributed with psplash)
|
||||
*/
|
||||
|
||||
/* GdkPixbuf RGBA C-Source image dump 1-byte-run-length-encoded */
|
||||
|
||||
#define POKY_IMG_ROWSTRIDE (1708)
|
||||
#define POKY_IMG_WIDTH (427)
|
||||
#define POKY_IMG_HEIGHT (214)
|
||||
#define POKY_IMG_BYTES_PER_PIXEL (4) /* 3:RGB, 4:RGBA */
|
||||
#define POKY_IMG_RLE_PIXEL_DATA ((uint8*) \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\237\350\354\340\377\1\350\354\342\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\254\350\354\340\377\2\241\243" \
|
||||
"\244\377;AC\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\252\350\354\340\377\2\275\277\277\377LQR\377\202.46\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\250\350\354\340" \
|
||||
"\377\2\321\322\323\377]ac\377\204.46\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\246\350\354\340\377\3\346\347\347\377" \
|
||||
"w{|\377/57\377\205.46\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\245\350\354\340\377\2\223\226\227\3775;=\377\207.46" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\243" \
|
||||
"\350\354\340\377\2\253\255\256\377BHJ\377\211.46\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\241\350\354\340\377\2\304" \
|
||||
"\306\306\377PUW\377\213.46\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\240\350\354\340\377\1\306\310\311\377\215.46\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\240\350" \
|
||||
"\354\340\377\1\302\303\304\377\215.46\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\240\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\240\350\354\340\377\1\302\303\304\377\215.46\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\240\350\354\340\377\1\302\303" \
|
||||
"\304\377\215.46\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\240\350\354\340\377\1\302\303\304\377\215.46\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\240\350\354\340\377" \
|
||||
"\1\302\303\304\377\215.46\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\240\350\354\340\377\1\302\303\304\377\215.46\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\240\350" \
|
||||
"\354\340\377\1\302\303\304\377\215.46\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\240\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\240\350\354\340\377\1\302\303\304\377\215.46\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\240\350\354\340\377\1\302\303" \
|
||||
"\304\377\215.46\377\377\350\354\340\377\305\350\354\340\377\1\346\347" \
|
||||
"\347\377\256\350\354\340\377\1\341\342\343\377\377\350\354\340\377\252" \
|
||||
"\350\354\340\377\1\302\303\304\377\215.46\377\377\350\354\340\377\304" \
|
||||
"\350\354\340\377\3\220\223\224\3775;=\377\244\247\250\377\254\350\354" \
|
||||
"\340\377\4\302\303\304\377179\377\205\210\212\377\350\354\342\377\377" \
|
||||
"\350\354\340\377\250\350\354\340\377\1\302\303\304\377\215.46\377\377" \
|
||||
"\350\354\340\377\302\350\354\340\377\2\250\253\253\377>DF\377\202.46" \
|
||||
"\377\1@FG\377\254\350\354\340\377\1Y^`\377\202.46\377\2;AC\377\241\243" \
|
||||
"\244\377\377\350\354\340\377\247\350\354\340\377\1\302\303\304\377\215" \
|
||||
".46\377\377\350\354\340\377\300\350\354\340\377\2\303\305\305\377PUW" \
|
||||
"\377\205.46\377\1\230\233\234\377\252\350\354\340\377\1\303\305\305\377" \
|
||||
"\205.46\377\2LQR\377\275\277\277\377\244\350\354\340\377\16\350\352\351" \
|
||||
"\377\313\314\315\377\254\257\257\377\224\227\230\377\214\220\221\377" \
|
||||
"\202\205\206\377w{|\377uy{\377\202\205\206\377\213\216\217\377\223\226" \
|
||||
"\227\377\253\255\256\377\310\312\312\377\346\346\347\377\362\350\354" \
|
||||
"\340\377\1\302\303\304\377\215.46\377\267\350\354\340\377\16\352\354" \
|
||||
"\345\377\315\316\317\377\257\262\263\377\225\230\231\377\216\221\222" \
|
||||
"\377\202\205\206\377x|}\377txy\377\202\205\206\377\211\214\215\377\221" \
|
||||
"\224\225\377\247\252\253\377\305\306\307\377\342\343\343\377\370\350" \
|
||||
"\354\340\377\2\327\330\330\377bgh\377\207.46\377\1""9\77A\377\252\350" \
|
||||
"\354\340\377\1]ac\377\207.46\377\2bgh\377\327\330\330\377\236\350\354" \
|
||||
"\340\377\4\323\324\324\377\237\242\243\377kop\3779>@\377\216.46\377\4" \
|
||||
"7=\77\377fjl\377\232\235\236\377\316\317\320\377\303\350\354\340\377" \
|
||||
"\7\352\354\346\377\332\333\334\377\303\305\305\377\271\273\274\377\263" \
|
||||
"\265\266\377\253\256\257\377\247\252\253\377\244\235\240\241\377\1}\200" \
|
||||
"\202\377\215.46\377\1\227\232\233\377\221\235\240\241\377\1\335\336\336" \
|
||||
"\377\240\350\354\340\377\4\330\332\332\377\244\247\250\377ptu\377>CE" \
|
||||
"\377\216.46\377\4""4:<\377_de\377\224\230\231\377\311\312\313\377\362" \
|
||||
"\350\354\340\377\3\352\353\347\377~\202\203\377068\377\211.46\377\1\216" \
|
||||
"\221\222\377\250\350\354\340\377\1\306\310\311\377\211.46\377\3""068" \
|
||||
"\377~\202\203\377\352\353\347\377\231\350\354\340\377\3\332\333\334\377" \
|
||||
"\214\220\221\377CIJ\377\226.46\377\3>CE\377\207\212\213\377\321\322\323" \
|
||||
"\377\272\350\354\340\377\6\324\325\325\377\257\261\262\377\213\217\220" \
|
||||
"\377gkl\377FKM\37728:\377\313.46\377\1\265\267\270\377\235\350\354\340" \
|
||||
"\377\3\341\342\342\377\224\230\231\377JOQ\377\226.46\377\3""9\77A\377" \
|
||||
"}\200\202\377\312\313\314\377\356\350\354\340\377\2\225\230\231\3778" \
|
||||
">\77\377\213.46\377\2""5;=\377\350\352\351\377\247\350\354\340\377\1" \
|
||||
"_de\377\213.46\377\2""8>\77\377\232\235\236\377\226\350\354\340\377\2" \
|
||||
"\264\266\266\377V[]\377\234.46\377\2PUV\377\253\256\257\377\264\350\354" \
|
||||
"\340\377\4\322\323\324\377\235\237\240\377gkl\3776<>\377\321.46\377\1" \
|
||||
"\265\267\270\377\233\350\354\340\377\2\277\301\302\377`ef\377\234.46" \
|
||||
"\377\2GMN\377\240\243\244\377\354\350\354\340\377\1BHJ\377\215.46\377" \
|
||||
"\1\202\205\206\377\246\350\354\340\377\1\311\312\313\377\215.46\377\1" \
|
||||
"CIJ\377\224\350\354\340\377\2\241\243\244\377FKM\377\240.46\377\2@FG" \
|
||||
"\377\231\233\234\377\257\350\354\340\377\3\325\326\327\377\214\220\221" \
|
||||
"\377EJL\377\325.46\377\1\265\267\270\377\231\350\354\340\377\2\255\257" \
|
||||
"\260\377NSU\377\240.46\377\3""9\77A\377\220\223\224\377\350\354\342\377" \
|
||||
"\351\350\354\340\377\1\251\253\254\377\215.46\377\2""179\377\341\342" \
|
||||
"\343\377\245\350\354\340\377\1bfh\377\215.46\377\1\244\247\250\377\222" \
|
||||
"\350\354\340\377\2\275\277\277\377LQR\377\244.46\377\2BHJ\377\264\267" \
|
||||
"\267\377\253\350\354\340\377\2\253\256\257\377PUV\377\330.46\377\1\265" \
|
||||
"\267\270\377\227\350\354\340\377\2\313\314\315\377UY[\377\244.46\377" \
|
||||
"\2;AC\377\247\252\253\377\351\350\354\340\377\1LQS\377\215.46\377\1x" \
|
||||
"|}\377\244\350\354\340\377\1\314\316\316\377\215.46\377\1BGI\377\221" \
|
||||
"\350\354\340\377\2\346\347\347\377hmn\377\250.46\377\2]ac\377\340\341" \
|
||||
"\341\377\247\350\354\340\377\2\235\237\240\377BGI\377\332.46\377\1\265" \
|
||||
"\267\270\377\225\350\354\340\377\2\350\354\342\377txz\377\250.46\377" \
|
||||
"\2PUW\377\324\326\326\377\347\350\354\340\377\1\270\272\272\377\215." \
|
||||
"46\377\2""068\377\330\332\332\377\243\350\354\340\377\1eik\377\215.4" \
|
||||
"6\377\1\242\244\245\377\220\350\354\340\377\2\275\277\277\377=BD\377" \
|
||||
"\252.46\377\2""8>\77\377\261\263\264\377\244\350\354\340\377\2\265\267" \
|
||||
"\270\377BHJ\377\334.46\377\1\265\267\270\377\224\350\354\340\377\2\313" \
|
||||
"\315\315\377EJL\377\252.46\377\2""28:\377\240\243\244\377\347\350\354" \
|
||||
"\340\377\1V[]\377\215.46\377\1kpq\377\242\350\354\340\377\1\316\317\320" \
|
||||
"\377\215.46\377\1@FG\377\220\350\354\340\377\1\210\214\215\377\256.4" \
|
||||
"6\377\1y}\177\377\241\350\354\340\377\2\336\337\337\377aeg\377\336.4" \
|
||||
"6\377\1\265\267\270\377\223\350\354\340\377\2\231\234\235\377068\377" \
|
||||
"\255.46\377\1imo\377\346\350\354\340\377\1\304\306\306\377\216.46\377" \
|
||||
"\1\317\321\321\377\241\350\354\340\377\1glm\377\215.46\377\1\236\241" \
|
||||
"\242\377\217\350\354\340\377\1ptu\377\260.46\377\1chi\377\237\350\354" \
|
||||
"\340\377\2\264\267\267\3778>\77\377\337.46\377\1\265\267\270\377\222" \
|
||||
"\350\354\340\377\1\202\205\206\377\260.46\377\2TYZ\377\352\353\347\377" \
|
||||
"\345\350\354\340\377\1chi\377\215.46\377\1bfh\377\240\350\354\340\377" \
|
||||
"\1\321\322\323\377\215.46\377\1>DF\377\217\350\354\340\377\1_de\377\262" \
|
||||
".46\377\2TYZ\377\352\353\347\377\234\350\354\340\377\1\202\205\206\377" \
|
||||
"\341.46\377\1\265\267\270\377\221\350\354\340\377\1ptv\377\262.46\377" \
|
||||
"\2HMO\377\337\340\340\377\344\350\354\340\377\2\322\323\324\377/57\377" \
|
||||
"\215.46\377\1\304\306\306\377\237\350\354\340\377\1kop\377\215.46\377" \
|
||||
"\1\234\237\240\377\216\350\354\340\377\1aeg\377\264.46\377\1SXY\377\233" \
|
||||
"\350\354\340\377\1fjl\377\342.46\377\1\265\267\270\377\220\350\354\340" \
|
||||
"\377\1ptu\377\264.46\377\2EJL\377\350\351\351\377\344\350\354\340\377" \
|
||||
"\1ptv\377\215.46\377\1V[]\377\236\350\354\340\377\1\324\326\326\377\215" \
|
||||
".46\377\1=BD\377\216\350\354\340\377\1nrs\377\226.46\377\12=BD\377`e" \
|
||||
"f\377\200\204\205\377\220\223\224\377\233\236\237\377\234\237\240\377" \
|
||||
"\220\223\224\377\202\205\206\377bgh\377>DF\377\226.46\377\1dij\377\231" \
|
||||
"\350\354\340\377\1_de\377\231.46\377\3""39;\377EJL\377Y^`\377\202fjl" \
|
||||
"\377\1swx\377\244txy\377\1_de\377\215.46\377\1ptu\377\221txy\377\1\316" \
|
||||
"\317\320\377\217\350\354\340\377\1\204\210\211\377\226.46\377\12""9\77" \
|
||||
"A\377[`a\377}\200\202\377\220\223\224\377\231\234\235\377\235\240\241" \
|
||||
"\377\220\223\224\377\205\210\212\377fjl\377BHJ\377\226.46\377\1SXY\377" \
|
||||
"\344\350\354\340\377\2\335\336\336\377068\377\215.46\377\1\271\273\274" \
|
||||
"\377\235\350\354\340\377\1lqr\377\215.46\377\1\231\233\234\377\215\350" \
|
||||
"\354\340\377\1\207\213\214\377\224.46\377\3PUW\377\234\237\240\377\327" \
|
||||
"\330\330\377\212\350\354\340\377\3\332\333\334\377\236\241\242\377PU" \
|
||||
"V\377\224.46\377\1x|}\377\227\350\354\340\377\1[`a\377\225.46\377\5K" \
|
||||
"PR\377\177\203\204\377\247\252\253\377\311\312\313\377\352\354\346\377" \
|
||||
"\252\350\354\340\377\1\302\303\304\377\215.46\377\241\350\354\340\377" \
|
||||
"\1\237\242\243\377\224.46\377\3JOQ\377\226\231\232\377\320\322\322\377" \
|
||||
"\212\350\354\340\377\3\336\337\337\377\242\245\246\377Y]_\377\224.46" \
|
||||
"\377\1eik\377\344\350\354\340\377\1~\201\202\377\215.46\377\1OTV\377" \
|
||||
"\234\350\354\340\377\2\326\327\330\377/57\377\214.46\377\1;AC\377\215" \
|
||||
"\350\354\340\377\1\271\273\274\377\222.46\377\3/57\377ptu\377\314\316" \
|
||||
"\316\377\220\350\354\340\377\2\312\313\314\377jnp\377\223.46\377\1\254" \
|
||||
"\257\257\377\225\350\354\340\377\1y|~\377\222.46\377\4/57\377]ac\377" \
|
||||
"\247\252\253\377\346\347\347\377\257\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\240\350\354\340\377\2\316\317\320\377068\377\222.46\377\2" \
|
||||
"fjl\377\305\306\307\377\220\350\354\340\377\3\323\324\324\377txy\377" \
|
||||
"068\377\222.46\377\1\225\230\231\377\343\350\354\340\377\2\347\350\350" \
|
||||
"\3775:<\377\215.46\377\1\256\260\261\377\233\350\354\340\377\1ptu\377" \
|
||||
"\215.46\377\1\226\231\232\377\214\350\354\340\377\2\344\345\345\377:" \
|
||||
"@B\377\221.46\377\2gkl\377\332\333\334\377\224\350\354\340\377\2\324" \
|
||||
"\326\326\377^ce\377\221.46\377\2""6<>\377\335\336\337\377\223\350\354" \
|
||||
"\340\377\1\235\240\241\377\221.46\377\3""39;\377\177\203\204\377\341" \
|
||||
"\342\342\377\262\350\354\340\377\1\302\303\304\377\215.46\377\237\350" \
|
||||
"\354\340\377\2\350\354\342\377FKM\377\221.46\377\2[`a\377\321\322\323" \
|
||||
"\377\224\350\354\340\377\2\335\336\337\377kop\377\221.46\377\2""068\377" \
|
||||
"\314\316\316\377\343\350\354\340\377\1\213\217\220\377\215.46\377\1F" \
|
||||
"KM\377\232\350\354\340\377\2\331\332\333\377/57\377\214.46\377\1:@B\377" \
|
||||
"\215\350\354\340\377\1^ce\377\220.46\377\2;AC\377\265\267\270\377\230" \
|
||||
"\350\354\340\377\2\251\253\254\3775;=\377\220.46\377\1Y]_\377\222\350" \
|
||||
"\354\340\377\2\325\326\327\377068\377\220.46\377\2ptu\377\346\346\347" \
|
||||
"\377\264\350\354\340\377\1\302\303\304\377\215.46\377\237\350\354\340" \
|
||||
"\377\1txz\377\220.46\377\2""6<>\377\250\253\253\377\230\350\354\340\377" \
|
||||
"\2\270\272\272\377<BC\377\220.46\377\1GMN\377\343\350\354\340\377\2\350" \
|
||||
"\354\342\3779\77A\377\215.46\377\1\244\247\250\377\231\350\354\340\377" \
|
||||
"\1rvw\377\215.46\377\1\223\226\227\377\214\350\354\340\377\1\261\263" \
|
||||
"\264\377\220.46\377\2X]^\377\344\345\345\377\232\350\354\340\377\2\327" \
|
||||
"\330\330\377HMO\377\220.46\377\1\255\257\260\377\221\350\354\340\377" \
|
||||
"\1UY[\377\217.46\377\2<BC\377\274\276\276\377\266\350\354\340\377\1\302" \
|
||||
"\303\304\377\215.46\377\236\350\354\340\377\1\311\312\313\377\220.46" \
|
||||
"\377\2LQS\377\330\332\332\377\232\350\354\340\377\2\342\343\343\377S" \
|
||||
"XY\377\220.46\377\1\224\230\231\377\343\350\354\340\377\1\230\233\234" \
|
||||
"\377\215.46\377\1@FG\377\230\350\354\340\377\2\332\333\334\377068\377" \
|
||||
"\214.46\377\1""9>@\377\215\350\354\340\377\1AFH\377\217.46\377\1gkl\377" \
|
||||
"\235\350\354\340\377\2\352\353\347\377OTV\377\217.46\377\1\77EG\377\220" \
|
||||
"\350\354\340\377\1\232\235\236\377\217.46\377\2MRT\377\340\341\341\377" \
|
||||
"\267\350\354\340\377\1\302\303\304\377\215.46\377\236\350\354\340\377" \
|
||||
"\1OTV\377\217.46\377\2W\\]\377\350\354\342\377\235\350\354\340\377\1" \
|
||||
"\\ab\377\217.46\377\2""5:<\377\346\346\347\377\343\350\354\340\377\1" \
|
||||
"AFH\377\215.46\377\1\230\233\234\377\227\350\354\340\377\1uy{\377\215" \
|
||||
".46\377\1\220\224\225\377\214\350\354\340\377\1\217\222\223\377\217." \
|
||||
"46\377\1imo\377\237\350\354\340\377\2\352\354\346\377LQR\377\217.46\377" \
|
||||
"\1\220\224\225\377\217\350\354\340\377\1""9>@\377\216.46\377\2OTV\377" \
|
||||
"\351\354\343\377\270\350\354\340\377\1\302\303\304\377\215.46\377\235" \
|
||||
"\350\354\340\377\1\246\251\252\377\217.46\377\1[`a\377\240\350\354\340" \
|
||||
"\377\1[`a\377\217.46\377\1{\177\200\377\343\350\354\340\377\1\246\251" \
|
||||
"\252\377\215.46\377\2""9\77A\377\350\354\342\377\225\350\354\340\377" \
|
||||
"\2\335\336\337\377068\377\214.46\377\2""8>\77\377\351\354\343\377\214" \
|
||||
"\350\354\340\377\1""9>@\377\216.46\377\1QVX\377\241\350\354\340\377\2" \
|
||||
"\341\342\343\377\77EG\377\216.46\377\1;AC\377\216\350\354\340\377\1\224" \
|
||||
"\230\231\377\216.46\377\2GLN\377\350\351\351\377\271\350\354\340\377" \
|
||||
"\1\302\303\304\377\215.46\377\235\350\354\340\377\1GLN\377\216.46\377" \
|
||||
"\2EJL\377\350\351\351\377\240\350\354\340\377\2\351\354\343\377JOQ\377" \
|
||||
"\216.46\377\2""179\377\346\347\347\377\343\350\354\340\377\1INP\377\215" \
|
||||
".46\377\1\216\221\222\377\225\350\354\340\377\1x|}\377\215.46\377\1\216" \
|
||||
"\221\222\377\214\350\354\340\377\1\230\233\234\377\216.46\377\2""7=\77" \
|
||||
"\377\337\340\340\377\242\350\354\340\377\2\312\313\314\377068\377\216" \
|
||||
".46\377\1\242\244\245\377\215\350\354\340\377\1;AC\377\215.46\377\2""0" \
|
||||
"68\377\316\317\320\377\272\350\354\340\377\1\302\303\304\377\215.46\377" \
|
||||
"\234\350\354\340\377\1\257\261\262\377\216.46\377\2""068\377\317\320" \
|
||||
"\320\377\242\350\354\340\377\2\330\332\332\3775:<\377\216.46\377\1\213" \
|
||||
"\216\217\377\343\350\354\340\377\1\264\266\266\377\215.46\377\2""5;=" \
|
||||
"\377\350\352\351\377\223\350\354\340\377\2\337\340\340\377068\377\214" \
|
||||
".46\377\2""6<>\377\352\354\346\377\214\350\354\340\377\1>DF\377\216." \
|
||||
"46\377\1\246\250\251\377\244\350\354\340\377\1\216\221\222\377\216.4" \
|
||||
"6\377\1GLN\377\214\350\354\340\377\1\246\251\252\377\216.46\377\1\223" \
|
||||
"\226\227\377\273\350\354\340\377\1\302\303\304\377\215.46\377\234\350" \
|
||||
"\354\340\377\1OTV\377\216.46\377\1\220\223\224\377\244\350\354\340\377" \
|
||||
"\1\244\247\250\377\216.46\377\1""8>\77\377\344\350\354\340\377\1UY[\377" \
|
||||
"\215.46\377\1\202\205\206\377\223\350\354\340\377\1z~\177\377\215.46" \
|
||||
"\377\1\213\216\217\377\214\350\354\340\377\1\271\273\274\377\216.46\377" \
|
||||
"\1Z_a\377\246\350\354\340\377\1JOQ\377\216.46\377\1\310\312\312\377\213" \
|
||||
"\350\354\340\377\1[`a\377\215.46\377\1BHJ\377\274\350\354\340\377\1\302" \
|
||||
"\303\304\377\215.46\377\233\350\354\340\377\1\320\322\322\377\216.46" \
|
||||
"\377\1HMO\377\246\350\354\340\377\1\\ab\377\216.46\377\1\260\263\263" \
|
||||
"\377\343\350\354\340\377\1\302\303\304\377\215.46\377\2""179\377\341" \
|
||||
"\342\342\377\221\350\354\340\377\2\341\342\343\377179\377\214.46\377" \
|
||||
"\2""5;=\377\352\353\347\377\214\350\354\340\377\1nrs\377\216.46\377\1" \
|
||||
"\316\317\320\377\246\350\354\340\377\1\273\275\276\377\216.46\377\1|" \
|
||||
"\200\201\377\212\350\354\340\377\1\341\342\343\377\216.46\377\1\253\255" \
|
||||
"\256\377\274\350\354\340\377\1\302\303\304\377\215.46\377\233\350\354" \
|
||||
"\340\377\1\204\210\211\377\216.46\377\1\270\272\272\377\246\350\354\340" \
|
||||
"\377\2\321\322\323\377/57\377\215.46\377\1eik\377\344\350\354\340\377" \
|
||||
"\1_de\377\215.46\377\1x|}\377\221\350\354\340\377\1~\201\202\377\215" \
|
||||
".46\377\1\210\214\215\377\214\350\354\340\377\2\350\354\342\37728:\377" \
|
||||
"\215.46\377\1hmn\377\250\350\354\340\377\1X]^\377\215.46\377\1""9>@\377" \
|
||||
"\212\350\354\340\377\1\231\234\235\377\215.46\377\1;AC\377\275\350\354" \
|
||||
"\340\377\1\302\303\304\377\215.46\377\233\350\354\340\377\1=BD\377\215" \
|
||||
".46\377\1PUW\377\250\350\354\340\377\1ost\377\215.46\377\2""068\377\351" \
|
||||
"\352\350\377\343\350\354\340\377\1\316\317\320\377\215.46\377\2""068" \
|
||||
"\377\330\332\332\377\217\350\354\340\377\2\343\344\344\377179\377\214" \
|
||||
".46\377\2""4:<\377\350\352\351\377\214\350\354\340\377\1\265\267\270" \
|
||||
"\377\216.46\377\1\305\306\307\377\250\350\354\340\377\1\271\273\273\377" \
|
||||
"\216.46\377\1\303\305\305\377\211\350\354\340\377\1eik\377\215.46\377" \
|
||||
"\1\207\212\213\377\275\350\354\340\377\1\302\303\304\377\215.46\377\232" \
|
||||
"\350\354\340\377\1\313\314\315\377\216.46\377\1\260\263\263\377\250\350" \
|
||||
"\354\340\377\1\317\320\320\377\216.46\377\1\254\257\257\377\344\350\354" \
|
||||
"\340\377\1nrs\377\215.46\377\1kpq\377\217\350\354\340\377\1\200\204\205" \
|
||||
"\377\215.46\377\1\205\210\212\377\215\350\354\340\377\1\201\204\206\377" \
|
||||
"\215.46\377\1MRT\377\252\350\354\340\377\1BHJ\377\215.46\377\1\217\222" \
|
||||
"\223\377\211\350\354\340\377\1""6<>\377\215.46\377\1\312\313\314\377" \
|
||||
"\275\350\354\340\377\1\302\303\304\377\215.46\377\232\350\354\340\377" \
|
||||
"\1\226\231\232\377\215.46\377\1=BD\377\252\350\354\340\377\1W\\]\377" \
|
||||
"\215.46\377\1x|}\377\344\350\354\340\377\2\333\334\334\377068\377\215" \
|
||||
".46\377\1\317\320\320\377\215\350\354\340\377\2\345\346\346\37739;\377" \
|
||||
"\214.46\377\2""39;\377\347\350\350\377\215\350\354\340\377\1LQR\377\215" \
|
||||
".46\377\1\225\230\231\377\252\350\354\340\377\1\211\214\215\377\215." \
|
||||
"46\377\1\\ab\377\210\350\354\340\377\1\321\322\323\377\215.46\377\1:" \
|
||||
"@B\377\276\350\354\340\377\1\302\303\304\377\215.46\377\232\350\354\340" \
|
||||
"\377\1bgh\377\215.46\377\1\177\203\204\377\252\350\354\340\377\1\237" \
|
||||
"\242\243\377\215.46\377\1DIK\377\345\350\354\340\377\1z~\177\377\215" \
|
||||
".46\377\1bfh\377\215\350\354\340\377\1\203\207\210\377\215.46\377\1\203" \
|
||||
"\207\210\377\215\350\354\340\377\1\352\354\346\377\216.46\377\1\335\336" \
|
||||
"\336\377\252\350\354\340\377\1\316\317\320\377\215.46\377\1""179\377" \
|
||||
"\210\350\354\340\377\1\246\251\252\377\215.46\377\1imo\377\276\350\354" \
|
||||
"\340\377\1\302\303\304\377\215.46\377\232\350\354\340\377\1""5:<\377" \
|
||||
"\215.46\377\1\306\310\311\377\252\350\354\340\377\1\344\345\345\377\216" \
|
||||
".46\377\1\344\345\345\377\252\350\354\340\377\5\304\336\373\377\236\311" \
|
||||
"\370\377\220\301\367\377\234\310\370\377\273\331\372\377\265\350\354" \
|
||||
"\340\377\2\344\345\345\37739;\377\215.46\377\1\304\306\306\377\213\350" \
|
||||
"\354\340\377\2\347\350\350\37739;\377\214.46\377\2""28:\377\345\346\346" \
|
||||
"\377\215\350\354\340\377\1\313\315\315\377\215.46\377\1@FG\377\254\350" \
|
||||
"\354\340\377\1""6<>\377\215.46\377\1\331\332\333\377\207\350\354\340" \
|
||||
"\377\1\212\215\216\377\215.46\377\1\222\225\226\377\276\350\354\340\377" \
|
||||
"\1\302\303\304\377\215.46\377\231\350\354\340\377\1\341\342\343\377\215" \
|
||||
".46\377\1""28:\377\254\350\354\340\377\1HMO\377\215.46\377\1\302\304" \
|
||||
"\305\377\250\350\354\340\377\2\262\324\371\377[\244\363\377\205O\235" \
|
||||
"\362\377\2U\240\362\377\236\311\370\377\264\350\354\340\377\1\211\214" \
|
||||
"\215\377\215.46\377\1V[]\377\213\350\354\340\377\1\205\210\212\377\215" \
|
||||
".46\377\1\200\204\205\377\216\350\354\340\377\1\253\256\257\377\215." \
|
||||
"46\377\1quw\377\254\350\354\340\377\1chi\377\215.46\377\1\275\277\277" \
|
||||
"\377\207\350\354\340\377\1mqs\377\215.46\377\1\270\272\272\377\276\350" \
|
||||
"\354\340\377\1\302\303\304\377\215.46\377\231\350\354\340\377\1\302\304" \
|
||||
"\305\377\215.46\377\1[`a\377\254\350\354\340\377\1y}\177\377\215.46\377" \
|
||||
"\1\246\250\251\377\247\350\354\340\377\1\214\277\366\377\211O\235\362" \
|
||||
"\377\1u\262\365\377\263\350\354\340\377\2\352\354\345\3779>@\377\215" \
|
||||
".46\377\1\271\273\273\377\211\350\354\340\377\2\350\352\351\3775:<\377" \
|
||||
"\214.46\377\2""179\377\343\344\344\377\216\350\354\340\377\1\217\222" \
|
||||
"\223\377\215.46\377\1\231\233\234\377\254\350\354\340\377\1\212\215\216" \
|
||||
"\377\215.46\377\1\235\240\241\377\207\350\354\340\377\1QVX\377\215.4" \
|
||||
"6\377\1\320\322\322\377\276\350\354\340\377\1\302\303\304\377\215.46" \
|
||||
"\377\231\350\354\340\377\1\246\250\251\377\215.46\377\1\202\205\206\377" \
|
||||
"\254\350\354\340\377\1\237\242\243\377\215.46\377\1\207\212\213\377\246" \
|
||||
"\350\354\340\377\1\236\311\370\377\213O\235\362\377\1\177\270\366\377" \
|
||||
"\263\350\354\340\377\1\225\230\231\377\215.46\377\1OTV\377\211\350\354" \
|
||||
"\340\377\1\210\214\215\377\215.46\377\1}\200\202\377\217\350\354\340" \
|
||||
"\377\1y|~\377\215.46\377\1\264\267\267\377\254\350\354\340\377\1\246" \
|
||||
"\251\252\377\215.46\377\1\206\211\212\377\207\350\354\340\377\1;AC\377" \
|
||||
"\215.46\377\1\347\350\350\377\276\350\354\340\377\1\302\303\304\377\215" \
|
||||
".46\377\231\350\354\340\377\1\216\221\222\377\215.46\377\1\235\240\241" \
|
||||
"\377\254\350\354\340\377\1\274\276\276\377\215.46\377\1nrs\377\245\350" \
|
||||
"\354\340\377\2\342\357\375\377Q\236\362\377\214O\235\362\377\1\304\336" \
|
||||
"\373\377\263\350\354\340\377\1>DF\377\215.46\377\1\256\260\261\377\207" \
|
||||
"\350\354\340\377\2\352\353\347\3775;=\377\214.46\377\2""179\377\341\342" \
|
||||
"\342\377\217\350\354\340\377\1kpq\377\215.46\377\1\313\315\315\377\254" \
|
||||
"\350\354\340\377\1\276\300\301\377\215.46\377\1{\177\200\377\207\350" \
|
||||
"\354\340\377\1""179\377\215.46\377\277\350\354\340\377\1\302\303\304" \
|
||||
"\377\215.46\377\231\350\354\340\377\1\204\210\211\377\215.46\377\1\267" \
|
||||
"\271\272\377\254\350\354\340\377\1\326\327\330\377\215.46\377\1eik\377" \
|
||||
"\245\350\354\340\377\1\232\307\370\377\215O\235\362\377\1z\265\365\377" \
|
||||
"\263\350\354\340\377\1\243\246\247\377\215.46\377\1FKM\377\207\350\354" \
|
||||
"\340\377\1\213\216\217\377\215.46\377\1y}\177\377\220\350\354\340\377" \
|
||||
"\1bgh\377\215.46\377\1\332\333\334\377\254\350\354\340\377\1\314\316" \
|
||||
"\316\377\215.46\377\1quw\377\207\350\354\340\377\216.46\377\277\350\354" \
|
||||
"\340\377\1\302\303\304\377\215.46\377\231\350\354\340\377\1y|~\377\215" \
|
||||
".46\377\1\302\303\304\377\254\350\354\340\377\1\341\342\343\377\215." \
|
||||
"46\377\1[`a\377\245\350\354\340\377\1i\254\364\377\215O\235\362\377\1" \
|
||||
"Q\236\362\377\264\350\354\340\377\1GMN\377\215.46\377\1\243\246\247\377" \
|
||||
"\205\350\354\340\377\2\352\354\346\3776<>\377\214.46\377\2""068\377\337" \
|
||||
"\340\340\377\220\350\354\340\377\1Y^`\377\215.46\377\1\341\342\343\377" \
|
||||
"\254\350\354\340\377\1\324\326\326\377\215.46\377\1hmn\377\207\350\354" \
|
||||
"\340\377\215.46\377\1""8>\77\377\277\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\231\350\354\340\377\1ptu\377\215.46\377\1\314\316\316\377" \
|
||||
"\254\350\354\340\377\1\351\352\350\377\215.46\377\1QVX\377\245\350\354" \
|
||||
"\340\377\1U\240\362\377\216O\235\362\377\1\344\360\375\377\263\350\354" \
|
||||
"\340\377\1\260\263\263\377\215.46\377\1@FG\377\205\350\354\340\377\1" \
|
||||
"\216\221\222\377\215.46\377\1w{|\377\221\350\354\340\377\1Y]_\377\215" \
|
||||
".46\377\1\342\343\343\377\254\350\354\340\377\1\325\326\327\377\215." \
|
||||
"46\377\1glm\377\206\350\354\340\377\1\351\352\350\377\215.46\377\1""5" \
|
||||
";=\377\277\350\354\340\377\1\302\303\304\377\215.46\377\231\350\354\340" \
|
||||
"\377\1ptu\377\215.46\377\1\315\316\317\377\254\350\354\340\377\1\352" \
|
||||
"\353\347\377\215.46\377\1QVX\377\245\350\354\340\377\1U\240\362\377\216" \
|
||||
"O\235\362\377\1\345\361\375\377\264\350\354\340\377\1PUW\377\215.46\377" \
|
||||
"\1\230\233\234\377\203\350\354\340\377\2\351\354\343\3778>\77\377\214" \
|
||||
".46\377\2""068\377\335\336\336\377\221\350\354\340\377\1bfh\377\215." \
|
||||
"46\377\1\332\333\334\377\254\350\354\340\377\1\314\316\316\377\215.4" \
|
||||
"6\377\1quw\377\207\350\354\340\377\216.46\377\277\350\354\340\377\1\302" \
|
||||
"\303\304\377\215.46\377\231\350\354\340\377\1x|}\377\215.46\377\1\302" \
|
||||
"\303\304\377\254\350\354\340\377\1\341\342\343\377\215.46\377\1Z_a\377" \
|
||||
"\245\350\354\340\377\1l\255\364\377\215O\235\362\377\1R\237\362\377\265" \
|
||||
"\350\354\340\377\1\275\277\300\377\215.46\377\2""9\77A\377\350\354\342" \
|
||||
"\377\202\350\354\340\377\1\220\224\225\377\215.46\377\1txz\377\222\350" \
|
||||
"\354\340\377\1kpq\377\215.46\377\1\314\316\316\377\254\350\354\340\377" \
|
||||
"\1\277\301\302\377\215.46\377\1z~\177\377\207\350\354\340\377\216.46" \
|
||||
"\377\1\352\354\345\377\276\350\354\340\377\1\302\303\304\377\215.46\377" \
|
||||
"\231\350\354\340\377\1\204\210\211\377\215.46\377\1\271\273\273\377\254" \
|
||||
"\350\354\340\377\1\327\330\330\377\215.46\377\1dij\377\245\350\354\340" \
|
||||
"\377\1\236\311\370\377\215O\235\362\377\1\177\270\366\377\266\350\354" \
|
||||
"\340\377\1]ac\377\215.46\377\4\215\220\221\377\350\354\340\377\350\354" \
|
||||
"\342\3779>@\377\214.46\377\2/57\377\332\333\334\377\222\350\354\340\377" \
|
||||
"\1w{|\377\215.46\377\1\265\267\270\377\254\350\354\340\377\1\250\253" \
|
||||
"\253\377\215.46\377\1\205\210\212\377\207\350\354\340\377\1""068\377" \
|
||||
"\215.46\377\1\341\342\342\377\276\350\354\340\377\1\302\303\304\377\215" \
|
||||
".46\377\231\350\354\340\377\1\215\220\221\377\215.46\377\1\237\242\243" \
|
||||
"\377\254\350\354\340\377\1\276\300\301\377\215.46\377\1mqs\377\245\350" \
|
||||
"\354\340\377\2\350\362\375\377S\237\362\377\214O\235\362\377\1\315\343" \
|
||||
"\373\377\266\350\354\340\377\1\313\315\315\377\215.46\377\3""5;=\377" \
|
||||
"\350\352\351\377\223\226\227\377\215.46\377\1quw\377\223\350\354\340" \
|
||||
"\377\1\216\221\222\377\215.46\377\1\231\234\235\377\254\350\354\340\377" \
|
||||
"\1\214\220\221\377\215.46\377\1\234\237\240\377\207\350\354\340\377\1" \
|
||||
"AFH\377\215.46\377\1\321\322\323\377\276\350\354\340\377\1\302\303\304" \
|
||||
"\377\215.46\377\231\350\354\340\377\1\244\247\250\377\215.46\377\1\203" \
|
||||
"\207\210\377\254\350\354\340\377\1\241\243\244\377\215.46\377\1\205\210" \
|
||||
"\212\377\246\350\354\340\377\1\253\320\371\377\213O\235\362\377\1\214" \
|
||||
"\277\366\377\270\350\354\340\377\1imo\377\215.46\377\2uy{\377:@B\377" \
|
||||
"\214.46\377\2/57\377\330\332\332\377\223\350\354\340\377\1\252\254\255" \
|
||||
"\377\215.46\377\1txy\377\254\350\354\340\377\1gkl\377\215.46\377\1\272" \
|
||||
"\274\275\377\207\350\354\340\377\1W\\]\377\215.46\377\1\251\253\254\377" \
|
||||
"\276\350\354\340\377\1\302\303\304\377\215.46\377\231\350\354\340\377" \
|
||||
"\1\301\302\303\377\215.46\377\1^ce\377\254\350\354\340\377\1}\200\202" \
|
||||
"\377\215.46\377\1\243\246\247\377\247\350\354\340\377\1\231\306\367\377" \
|
||||
"\211O\235\362\377\1\200\270\366\377\271\350\354\340\377\2\327\330\330" \
|
||||
"\377068\377\232.46\377\1nrs\377\224\350\354\340\377\1\311\312\313\377" \
|
||||
"\215.46\377\1CIJ\377\254\350\354\340\377\1""8>\77\377\215.46\377\1\330" \
|
||||
"\331\331\377\207\350\354\340\377\1kpq\377\215.46\377\1\177\203\204\377" \
|
||||
"\276\350\354\340\377\1\302\303\304\377\215.46\377\231\350\354\340\377" \
|
||||
"\1\337\340\340\377\215.46\377\1""4:<\377\254\350\354\340\377\1LQR\377" \
|
||||
"\215.46\377\1\301\302\303\377\250\350\354\340\377\2\303\336\373\377d" \
|
||||
"\251\364\377\205O\235\362\377\2Z\243\363\377\260\323\371\377\273\350" \
|
||||
"\354\340\377\1x|}\377\231.46\377\2/57\377\325\326\327\377\224\350\354" \
|
||||
"\340\377\1\351\352\350\377\216.46\377\1\340\341\341\377\252\350\354\340" \
|
||||
"\377\1\321\322\323\377\215.46\377\1""068\377\210\350\354\340\377\1\213" \
|
||||
"\217\220\377\215.46\377\1V[]\377\276\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\232\350\354\340\377\1""39;\377\215.46\377\1\312\313\314\377" \
|
||||
"\252\350\354\340\377\1\350\351\351\377\216.46\377\1\341\342\342\377\252" \
|
||||
"\350\354\340\377\5\323\346\374\377\255\321\371\377\236\311\370\377\251" \
|
||||
"\317\371\377\313\342\373\377\275\350\354\340\377\2\342\343\343\37728" \
|
||||
":\377\230.46\377\1kpq\377\226\350\354\340\377\1INP\377\215.46\377\1\232" \
|
||||
"\235\236\377\252\350\354\340\377\1\214\220\221\377\215.46\377\1X]^\377" \
|
||||
"\210\350\354\340\377\1\261\263\264\377\215.46\377\1""179\377\276\350" \
|
||||
"\354\340\377\1\302\303\304\377\215.46\377\232\350\354\340\377\1_de\377" \
|
||||
"\215.46\377\1\204\210\211\377\252\350\354\340\377\1\243\246\247\377\215" \
|
||||
".46\377\1BGI\377\356\350\354\340\377\1\204\210\211\377\230.46\377\1\323" \
|
||||
"\324\324\377\226\350\354\340\377\1}\200\202\377\215.46\377\1QVX\377\252" \
|
||||
"\350\354\340\377\1GLN\377\215.46\377\1\214\220\221\377\210\350\354\340" \
|
||||
"\377\1\330\331\331\377\216.46\377\1\253\256\257\377\275\350\354\340\377" \
|
||||
"\1\302\303\304\377\215.46\377\232\350\354\340\377\1\224\227\230\377\215" \
|
||||
".46\377\1\77EG\377\252\350\354\340\377\1[`a\377\215.46\377\1txz\377\356" \
|
||||
"\350\354\340\377\2\352\353\347\3776<>\377\226.46\377\1imo\377\227\350" \
|
||||
"\354\340\377\1\262\264\265\377\216.46\377\1\313\314\315\377\250\350\354" \
|
||||
"\340\377\1\276\300\301\377\216.46\377\1\300\302\302\377\211\350\354\340" \
|
||||
"\377\1;AC\377\215.46\377\1_de\377\275\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\232\350\354\340\377\1\306\310\311\377\216.46\377\1\265\267" \
|
||||
"\270\377\250\350\354\340\377\1\324\325\325\377\216.46\377\1\251\253\254" \
|
||||
"\377\357\350\354\340\377\1\223\226\227\377\226.46\377\1\320\322\322\377" \
|
||||
"\227\350\354\340\377\2\352\354\350\377179\377\215.46\377\1ost\377\250" \
|
||||
"\350\354\340\377\1]ac\377\215.46\377\1""6<>\377\212\350\354\340\377\1" \
|
||||
"mqs\377\215.46\377\2/57\377\341\342\343\377\274\350\354\340\377\1\302" \
|
||||
"\303\304\377\215.46\377\233\350\354\340\377\1""9\77A\377\215.46\377\1" \
|
||||
"V[]\377\250\350\354\340\377\1txz\377\215.46\377\2/57\377\346\346\347" \
|
||||
"\377\360\350\354\340\377\1=BD\377\224.46\377\1fjl\377\231\350\354\340" \
|
||||
"\377\1imo\377\215.46\377\2/57\377\324\325\325\377\246\350\354\340\377" \
|
||||
"\1\303\305\305\377\216.46\377\1x|}\377\212\350\354\340\377\1\246\251" \
|
||||
"\252\377\216.46\377\1y}\177\377\274\350\354\340\377\1\302\303\304\377" \
|
||||
"\215.46\377\233\350\354\340\377\1\200\204\205\377\216.46\377\1\276\300" \
|
||||
"\301\377\246\350\354\340\377\2\330\331\331\377068\377\215.46\377\1`e" \
|
||||
"f\377\361\350\354\340\377\1\237\242\243\377\224.46\377\1\316\317\320" \
|
||||
"\377\231\350\354\340\377\1\264\267\267\377\216.46\377\1aeg\377\246\350" \
|
||||
"\354\340\377\1OTV\377\216.46\377\1\303\305\305\377\212\350\354\340\377" \
|
||||
"\2\351\352\350\377068\377\215.46\377\2/57\377\323\324\324\377\273\350" \
|
||||
"\354\340\377\1\302\303\304\377\215.46\377\233\350\354\340\377\1\313\315" \
|
||||
"\315\377\216.46\377\1NSU\377\246\350\354\340\377\1chi\377\216.46\377" \
|
||||
"\1\253\256\257\377\362\350\354\340\377\1DIK\377\222.46\377\1chi\377\233" \
|
||||
"\350\354\340\377\1;AC\377\216.46\377\1\257\262\263\377\244\350\354\340" \
|
||||
"\377\1\230\233\234\377\216.46\377\1BHJ\377\214\350\354\340\377\1aeg\377" \
|
||||
"\216.46\377\1]ac\377\273\350\354\340\377\1\302\303\304\377\215.46\377" \
|
||||
"\234\350\354\340\377\1JOQ\377\216.46\377\1\231\233\234\377\244\350\354" \
|
||||
"\340\377\1\256\260\261\377\216.46\377\1""5;=\377\363\350\354\340\377" \
|
||||
"\1\256\260\261\377\222.46\377\1\313\314\315\377\233\350\354\340\377\1" \
|
||||
"\224\227\230\377\216.46\377\2:@B\377\346\346\347\377\242\350\354\340" \
|
||||
"\377\2\322\323\324\377179\377\216.46\377\1\235\240\241\377\214\350\354" \
|
||||
"\340\377\1\262\264\265\377\217.46\377\1\220\223\224\377\272\350\354\340" \
|
||||
"\377\1\302\303\304\377\215.46\377\234\350\354\340\377\1\252\254\255\377" \
|
||||
"\216.46\377\2""39;\377\326\327\330\377\242\350\354\340\377\2\340\341" \
|
||||
"\341\3778>\77\377\216.46\377\1\207\212\213\377\364\350\354\340\377\1" \
|
||||
"OTV\377\220.46\377\1`ef\377\234\350\354\340\377\2\350\354\342\3778>\77" \
|
||||
"\377\216.46\377\1Y]_\377\241\350\354\340\377\2\350\351\351\377EJL\377" \
|
||||
"\216.46\377\1;AC\377\216\350\354\340\377\1BHJ\377\216.46\377\2/57\377" \
|
||||
"\264\267\267\377\271\350\354\340\377\1\302\303\304\377\215.46\377\235" \
|
||||
"\350\354\340\377\1EJL\377\216.46\377\2KPR\377\351\354\343\377\241\350" \
|
||||
"\354\340\377\1NSU\377\216.46\377\2""179\377\346\346\347\377\364\350\354" \
|
||||
"\340\377\1\272\274\275\377\220.46\377\1\307\311\311\377\235\350\354\340" \
|
||||
"\377\1\220\223\224\377\217.46\377\1swx\377\240\350\354\340\377\1SXY\377" \
|
||||
"\217.46\377\1\220\224\225\377\216\350\354\340\377\1\233\236\237\377\217" \
|
||||
".46\377\2""6<>\377\301\302\303\377\270\350\354\340\377\1\302\303\304" \
|
||||
"\377\215.46\377\1\352\354\350\377\234\350\354\340\377\1\246\251\252\377" \
|
||||
"\217.46\377\1bfh\377\240\350\354\340\377\1chi\377\217.46\377\1z~\177" \
|
||||
"\377\366\350\354\340\377\1Y]_\377\216.46\377\1^ce\377\237\350\354\340" \
|
||||
"\377\1BGI\377\217.46\377\1lqr\377\235\350\354\340\377\2\352\354\350\377" \
|
||||
"SXY\377\217.46\377\1BGI\377\220\350\354\340\377\1@FG\377\217.46\377\2" \
|
||||
"068\377\246\251\252\377\267\350\354\340\377\1\302\303\304\377\215.46" \
|
||||
"\377\1\335\336\337\377\235\350\354\340\377\1QVX\377\217.46\377\1\\ab" \
|
||||
"\377\236\350\354\340\377\1_de\377\217.46\377\2""6<>\377\346\347\347\377" \
|
||||
"\366\350\354\340\377\1\311\312\313\377\216.46\377\1\304\306\306\377\237" \
|
||||
"\350\354\340\377\1\265\267\270\377\220.46\377\2W\\]\377\344\345\345\377" \
|
||||
"\232\350\354\340\377\2\326\327\330\377HMO\377\220.46\377\1\261\263\264" \
|
||||
"\377\220\350\354\340\377\1\247\252\253\377\221.46\377\1\202\206\207\377" \
|
||||
"\242\350\354\340\377\2\264\267\267\377\276\300\301\377\222\350\354\340" \
|
||||
"\377\1\310\312\312\377\215.46\377\1\267\271\272\377\235\350\354\340\377" \
|
||||
"\2\314\316\316\377/57\377\217.46\377\2LQS\377\330\331\331\377\232\350" \
|
||||
"\354\340\377\2\341\342\342\377SXY\377\220.46\377\1\231\233\234\377\367" \
|
||||
"\350\354\340\377\2\341\342\343\377068\377\214.46\377\1[`a\377\241\350" \
|
||||
"\354\340\377\1eik\377\220.46\377\2;AC\377\263\265\266\377\230\350\354" \
|
||||
"\340\377\2\246\251\252\3775:<\377\220.46\377\1]ac\377\222\350\354\340" \
|
||||
"\377\1Y]_\377\221.46\377\2BHJ\377\264\267\267\377\235\350\354\340\377" \
|
||||
"\5\331\332\333\377\207\213\214\377=BD\377.46\377FKM\377\222\350\354\340" \
|
||||
"\377\1\327\330\330\377\215.46\377\1uy{\377\220\350\354\340\377\1\350" \
|
||||
"\354\342\377\215\350\354\340\377\1|\200\201\377\220.46\377\2""5:<\377" \
|
||||
"\245\247\250\377\230\350\354\340\377\2\265\267\270\377;AC\377\220.46" \
|
||||
"\377\1KPR\377\370\350\354\340\377\1\205\210\212\377\215.46\377\1\302" \
|
||||
"\303\304\377\241\350\354\340\377\2\350\351\351\377>DF\377\221.46\377" \
|
||||
"\2fjl\377\335\336\336\377\224\350\354\340\377\2\327\330\330\377^bd\377" \
|
||||
"\221.46\377\2""9\77A\377\342\343\343\377\222\350\354\340\377\2\332\333" \
|
||||
"\334\37739;\377\222.46\377\2W\\]\377\257\262\263\377\230\350\354\340" \
|
||||
"\377\3\320\322\322\377\217\222\223\377MRT\377\205.46\377\1\246\250\251" \
|
||||
"\377\221\350\354\340\377\1\347\350\350\377\215.46\377\2""179\377\324" \
|
||||
"\326\326\377\215\350\354\340\377\3\235\240\241\377CIJ\377txz\377\216" \
|
||||
"\350\354\340\377\1KPR\377\221.46\377\2[`a\377\324\325\325\377\224\350" \
|
||||
"\354\340\377\2\341\342\342\377kop\377\221.46\377\2""39;\377\323\324\324" \
|
||||
"\377\367\350\354\340\377\2\350\354\342\3775;=\377\214.46\377\1Y]_\377" \
|
||||
"\243\350\354\340\377\2\303\305\305\377/57\377\221.46\377\3""068\377{" \
|
||||
"\177\200\377\332\333\334\377\220\350\354\340\377\3\325\326\327\377tx" \
|
||||
"z\377/57\377\222.46\377\1\270\272\272\377\224\350\354\340\377\1\244\247" \
|
||||
"\250\377\224.46\377\3>DF\377\206\211\212\377\277\301\302\377\221\350" \
|
||||
"\354\340\377\4\325\326\327\377\245\247\250\377txy\377BGI\377\210.46\377" \
|
||||
"\1BGI\377\222\350\354\340\377\1/57\377\215.46\377\2CIJ\377\330\332\332" \
|
||||
"\377\211\350\354\340\377\3\302\304\305\377|\200\201\3777=\77\377\202" \
|
||||
".46\377\2""068\377\332\333\334\377\215\350\354\340\377\2\326\327\330" \
|
||||
"\3774:<\377\221.46\377\3/57\377ptv\377\320\322\322\377\220\350\354\340" \
|
||||
"\377\3\336\337\337\377\201\204\206\377179\377\222.46\377\1\237\242\243" \
|
||||
"\377\370\350\354\340\377\1\224\227\230\377\215.46\377\1\277\301\302\377" \
|
||||
"\244\350\354\340\377\1\224\227\230\377\224.46\377\3TYZ\377\232\235\236" \
|
||||
"\377\317\320\320\377\212\350\354\340\377\3\321\322\323\377\232\235\236" \
|
||||
"\377SXY\377\224.46\377\1\207\212\213\377\226\350\354\340\377\1vz{\377" \
|
||||
"\226.46\377\21""179\377\\ab\377~\201\202\377\233\236\237\377\272\274" \
|
||||
"\275\377\313\315\315\377\325\326\327\377\333\334\334\377\343\344\344" \
|
||||
"\377\331\332\333\377\315\316\317\377\301\302\303\377\264\266\266\377" \
|
||||
"\224\230\231\377uy{\377V[]\3776<>\377\215.46\377\1\236\241\242\377\221" \
|
||||
"\350\354\340\377\1PUW\377\216.46\377\12""179\377y}\177\377\274\276\276" \
|
||||
"\377\337\340\340\377\343\344\344\377\332\333\334\377\305\306\307\377" \
|
||||
"\235\237\240\377rvw\377<BC\377\206.46\377\1quw\377\216\350\354\340\377" \
|
||||
"\1\253\256\257\377\224.46\377\3NSU\377\223\226\227\377\312\313\314\377" \
|
||||
"\212\350\354\340\377\3\327\330\330\377\241\243\244\377]ac\377\224.46" \
|
||||
"\377\1ptu\377\371\350\354\340\377\1=BD\377\214.46\377\1V[]\377\246\350" \
|
||||
"\354\340\377\1|\200\201\377\226.46\377\12""39;\377PUV\377nrs\377~\201" \
|
||||
"\202\377\207\212\213\377\210\214\215\377~\202\203\377ost\377RWY\3774" \
|
||||
":<\377\226.46\377\1nrs\377\230\350\354\340\377\1aeg\377\263.46\377\1" \
|
||||
">CE\377\221\350\354\340\377\1\204\210\211\377\236.46\377\2/57\377\330" \
|
||||
"\331\331\377\216\350\354\340\377\1\220\224\225\377\226.46\377\12""28" \
|
||||
":\377LQS\377kop\377|\200\201\377\205\210\212\377\211\214\215\377\200" \
|
||||
"\204\205\377ptv\377UZ\\\3776<>\377\226.46\377\1[`a\377\371\350\354\340" \
|
||||
"\377\1\225\230\231\377\215.46\377\1\274\276\276\377\247\350\354\340\377" \
|
||||
"\1nrs\377\264.46\377\1[`a\377\232\350\354\340\377\1UZ\\\377\263.46\377" \
|
||||
"\1\231\233\234\377\220\350\354\340\377\1\270\272\272\377\237.46\377\1" \
|
||||
"ost\377\217\350\354\340\377\1\204\210\211\377\264.46\377\2PUW\377\351" \
|
||||
"\354\343\377\370\350\354\340\377\2\350\354\342\3779>@\377\214.46\377" \
|
||||
"\1TYZ\377\251\350\354\340\377\1nrs\377\262.46\377\1bfh\377\234\350\354" \
|
||||
"\340\377\1_de\377\262.46\377\1:@B\377\221\350\354\340\377\1BHJ\377\236" \
|
||||
".46\377\2/57\377\326\327\330\377\217\350\354\340\377\1\177\203\204\377" \
|
||||
"\262.46\377\2SXY\377\351\352\350\377\371\350\354\340\377\1\213\217\220" \
|
||||
"\377\215.46\377\1\271\273\274\377\252\350\354\340\377\1\177\203\204\377" \
|
||||
"\260.46\377\1quw\377\236\350\354\340\377\1rvw\377\262.46\377\1\222\225" \
|
||||
"\226\377\220\350\354\340\377\1\231\234\235\377\237.46\377\1mqs\377\220" \
|
||||
"\350\354\340\377\1\224\227\230\377\260.46\377\1bfh\377\372\350\354\340" \
|
||||
"\377\2\350\352\351\3775:<\377\214.46\377\1QVX\377\254\350\354\340\377" \
|
||||
"\2\231\233\234\377068\377\254.46\377\2/57\377\214\220\221\377\240\350" \
|
||||
"\354\340\377\2\237\242\243\377068\377\260.46\377\2""7=\77\377\352\354" \
|
||||
"\345\377\220\350\354\340\377\1BHJ\377\237.46\377\1\323\324\324\377\220" \
|
||||
"\350\354\340\377\2\253\256\257\3774:<\377\255.46\377\1y|~\377\373\350" \
|
||||
"\354\340\377\1\202\205\206\377\215.46\377\1\266\270\271\377\255\350\354" \
|
||||
"\340\377\2\312\313\314\377CIJ\377\252.46\377\2>CE\377\277\301\302\377" \
|
||||
"\242\350\354\340\377\2\322\323\324\377PUV\377\260.46\377\1\213\216\217" \
|
||||
"\377\220\350\354\340\377\2\307\311\311\377/57\377\236.46\377\1jnp\377" \
|
||||
"\221\350\354\340\377\2\330\331\331\377LQS\377\252.46\377\2""6<>\377\257" \
|
||||
"\262\263\377\373\350\354\340\377\2\342\343\343\377179\377\214.46\377" \
|
||||
"\1NSU\377\257\350\354\340\377\2\351\354\343\377quw\377\250.46\377\2f" \
|
||||
"jl\377\346\347\347\377\245\350\354\340\377\2\224\230\231\3775;=\377\255" \
|
||||
".46\377\2W\\]\377\265\267\270\377\221\350\354\340\377\1\227\232\233\377" \
|
||||
"\237.46\377\1\321\322\323\377\222\350\354\340\377\2\200\204\205\377/" \
|
||||
"57\377\247.46\377\2Y^`\377\335\336\336\377\374\350\354\340\377\1ptu\377" \
|
||||
"\215.46\377\1\264\267\267\377\261\350\354\340\377\2\304\306\306\377L" \
|
||||
"QR\377\244.46\377\2FKM\377\271\273\274\377\250\350\354\340\377\3\346" \
|
||||
"\347\347\377|\200\201\37728:\377\250.46\377\3""28:\377vz{\377\317\321" \
|
||||
"\321\377\224\350\354\340\377\1\235\237\240\377\234.46\377\3/57\377qu" \
|
||||
"w\377\341\342\342\377\223\350\354\340\377\2\321\322\323\377V[]\377\244" \
|
||||
".46\377\2>DF\377\253\256\257\377\375\350\354\340\377\1\306\307\310\377" \
|
||||
"\215.46\377\1MRT\377\264\350\354\340\377\2\242\245\246\377CIJ\377\240" \
|
||||
".46\377\2>CE\377\231\233\234\377\254\350\354\340\377\3\346\346\347\377" \
|
||||
"\207\213\214\377:@B\377\243.46\377\4/57\377Y^`\377\235\240\241\377\352" \
|
||||
"\353\347\377\227\350\354\340\377\2\266\270\271\377>CE\377\230.46\377" \
|
||||
"\3""179\377quw\377\324\326\326\377\227\350\354\340\377\2\255\257\260" \
|
||||
"\377KPR\377\240.46\377\3""9>@\377\215\220\221\377\350\354\342\377\376" \
|
||||
"\350\354\340\377\1OTV\377\215.46\377\1\262\264\265\377\266\350\354\340" \
|
||||
"\377\2\252\254\255\377KPR\377\234.46\377\2DIK\377\242\244\245\377\261" \
|
||||
"\350\354\340\377\3\256\260\261\377dij\377068\377\235.46\377\4""068\377" \
|
||||
"`ef\377\243\246\247\377\346\347\347\377\233\350\354\340\377\3\352\354" \
|
||||
"\345\377z~\177\37728:\377\224.46\377\3HMO\377\224\230\231\377\350\351" \
|
||||
"\351\377\233\350\354\340\377\2\265\267\270\377SXY\377\234.46\377\2>C" \
|
||||
"E\377\226\231\232\377\377\350\354\340\377\2\350\354\340\377\227\232\233" \
|
||||
"\377\215.46\377\1PUW\377\271\350\354\340\377\3\317\320\320\377\210\214" \
|
||||
"\215\377BHJ\377\226.46\377\3>CE\377\201\204\206\377\312\313\314\377\265" \
|
||||
"\350\354\340\377\4\350\354\342\377\257\261\262\377x|}\377BHJ\377\226" \
|
||||
".46\377\5""6<>\377`ef\377\220\223\224\377\277\301\302\377\350\354\342" \
|
||||
"\377\240\350\354\340\377\3\347\350\350\377\220\223\224\377HMO\377\216" \
|
||||
".46\377\4""179\377[`a\377\224\227\230\377\326\327\330\377\240\350\354" \
|
||||
"\340\377\3\330\331\331\377\220\223\224\377HMO\377\226.46\377\3""9>@\377" \
|
||||
"z~\177\377\301\302\303\377\377\350\354\340\377\202\350\354\340\377\2" \
|
||||
"\332\333\334\37739;\377\215.46\377\1\275\277\277\377\274\350\354\340" \
|
||||
"\377\4\326\327\330\377\244\247\250\377swx\377CIJ\377\216.46\377\4@FG" \
|
||||
"\377nrs\377\240\243\244\377\321\322\323\377\274\350\354\340\377\7\350" \
|
||||
"\352\351\377\306\307\310\377\242\244\245\377\177\203\204\377Y^`\377B" \
|
||||
"HJ\3775;=\377\211.46\377\6CIJ\377_de\377z~\177\377\226\231\232\377\262" \
|
||||
"\264\265\377\325\326\327\377\250\350\354\340\377\6\336\337\337\377\246" \
|
||||
"\251\252\377\205\210\212\377fjl\377LQS\377DIK\377\202<BC\377\6GLN\377" \
|
||||
"SXY\377eik\377\204\210\211\377\242\245\246\377\311\312\313\377\247\350" \
|
||||
"\354\340\377\4\333\334\334\377\251\253\254\377x|}\377HMO\377\216.46\377" \
|
||||
"\4;AC\377imo\377\232\235\236\377\314\316\316\377\377\350\354\340\377" \
|
||||
"\205\350\354\340\377\1UZ\\\377\215.46\377\1\\ab\377\302\350\354\340\377" \
|
||||
"\14\330\331\331\377\274\276\276\377\244\247\250\377\235\237\240\377\220" \
|
||||
"\223\224\377\210\214\215\377\207\212\213\377\220\223\224\377\234\237" \
|
||||
"\240\377\243\246\247\377\271\273\273\377\326\327\330\377\311\350\354" \
|
||||
"\340\377\5\352\354\345\377\340\341\341\377\325\326\327\377\341\342\342" \
|
||||
"\377\343\344\344\377\353\350\354\340\377\15\333\334\334\377\276\300\301" \
|
||||
"\377\246\250\251\377\235\240\241\377\220\224\225\377\211\214\215\377" \
|
||||
"\205\210\212\377\220\223\224\377\232\235\236\377\242\244\245\377\265" \
|
||||
"\267\270\377\323\324\324\377\350\354\342\377\377\350\354\340\377\210" \
|
||||
"\350\354\340\377\1\205\210\212\377\216.46\377\1\313\315\315\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\235\350\354\340" \
|
||||
"\377\1\264\267\267\377\216.46\377\1txz\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\235\350\354\340\377\2\322\323\324\377" \
|
||||
"5:<\377\215.46\377\2""9>@\377\350\352\351\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\234\350\354\340\377\2\334\335\335" \
|
||||
"\377\77EG\377\216.46\377\1\243\246\247\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\234\350\354\340\377\2\335\336\337\377" \
|
||||
"@FG\377\216.46\377\1V[]\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\234\350\354\340\377\2\336\337\337\377BGI\377\216.46" \
|
||||
"\377\2""6<>\377\335\336\336\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\233\350\354\340\377\2\333\334\334\377BHJ\377\217" \
|
||||
".46\377\1\252\254\255\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\233\350\354\340\377\2\277\301\302\3779>@\377\217.46" \
|
||||
"\377\1ptu\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\233\350\354\340\377\2\215\220\221\377/57\377\217.46\377\1LQS\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\232\350" \
|
||||
"\354\340\377\2\304\306\306\377PUW\377\220.46\377\2\77EG\377\341\342\343" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\230" \
|
||||
"\350\354\340\377\2\335\336\336\377imo\377\221.46\377\2""5:<\377\322\323" \
|
||||
"\324\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\227\350\354\340\377\3\312\313\314\377vz{\377179\377\221.46\377\2""2" \
|
||||
"8:\377\275\277\277\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\225\350\354\340\377\3\341\342\343\377\237\242\243\377MR" \
|
||||
"T\377\223.46\377\2""068\377\271\273\274\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\223\350\354\340\377\3\310\312\312\377" \
|
||||
"\215\220\221\377OTV\377\225.46\377\2""068\377\264\267\267\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\221\350\354\340" \
|
||||
"\377\3\217\222\223\377Y^`\377179\377\227.46\377\2""5:<\377\275\277\300" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\222" \
|
||||
"\350\354\340\377\1\201\204\206\377\230.46\377\2;AC\377\313\315\315\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\223\350" \
|
||||
"\354\340\377\2\341\342\343\377179\377\226.46\377\2NSU\377\335\336\337" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\225" \
|
||||
"\350\354\340\377\1x|}\377\225.46\377\1ptu\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\227\350\354\340\377\2\333\334\334" \
|
||||
"\377/57\377\222.46\377\2""9>@\377\252\254\255\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\231\350\354\340\377\1ptu\377" \
|
||||
"\221.46\377\2eik\377\344\345\345\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\232\350\354\340\377\1\324\325\325\377\217" \
|
||||
".46\377\2PUW\377\275\277\277\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\235\350\354\340\377\1gkl\377\214.46\377\2LQ" \
|
||||
"S\377\260\263\263\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\237\350\354\340\377\1\313\315\315\377\211.46\377\3""068" \
|
||||
"\377jnp\377\275\277\277\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\242\350\354\340\377\1^ce\377\205.46\377\4""8>\77\377" \
|
||||
"kpq\377\253\255\256\377\350\352\351\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\244\350\354\340\377\6\302\304\305\377.4" \
|
||||
"6\377;AC\377bgh\377\224\230\231\377\314\316\316\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\251\350\354\340\377\1\345\346" \
|
||||
"\346\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\337\350\354\340\377\1\352\354\350\377\210\325\326\327\377\1\341" \
|
||||
"\342\342\377\232\350\354\340\377\1\341\342\343\377\207\325\326\327\377" \
|
||||
"\1\343\344\344\377\244\350\354\340\377\2\314\316\316\377\267\271\272" \
|
||||
"\377\202\244\247\250\377\2\267\271\272\377\315\316\317\377\236\350\354" \
|
||||
"\340\377\1\350\351\351\377\204\343\344\344\377\224\350\354\340\377\1" \
|
||||
"\332\333\334\377\217\325\326\327\377\232\350\354\340\377\3\300\302\302" \
|
||||
"\377\235\237\240\377\206\211\212\377\202\202\205\206\377\3\212\215\216" \
|
||||
"\377\242\245\246\377\307\311\311\377\225\350\354\340\377\1\344\345\345" \
|
||||
"\377\223\325\326\327\377\1\335\336\336\377\377\350\354\340\377\302\350" \
|
||||
"\354\340\377\1\235\237\240\377\212.46\377\3KPR\377\213\216\217\377\335" \
|
||||
"\336\337\377\226\350\354\340\377\1kpq\377\211.46\377\3BGI\377txy\377" \
|
||||
"\271\273\273\377\235\350\354\340\377\3\265\267\270\377lqr\3776<>\377" \
|
||||
"\206.46\377\3""6<>\377nrs\377\270\272\272\377\233\350\354\340\377\1S" \
|
||||
"XY\377\204.46\377\224\350\354\340\377\1GLN\377\217.46\377\1\331\332\333" \
|
||||
"\377\226\350\354\340\377\3\267\271\272\377fjl\377068\377\210.46\377\4" \
|
||||
"068\377aeg\377\246\251\252\377\350\354\342\377\221\350\354\340\377\1" \
|
||||
"x|}\377\223.46\377\1SXY\377\377\350\354\340\377\302\350\354\340\377\1" \
|
||||
"\235\237\240\377\214.46\377\2""179\377\213\217\220\377\225\350\354\340" \
|
||||
"\377\1kpq\377\214.46\377\2PUW\377\326\327\330\377\231\350\354\340\377" \
|
||||
"\2\275\277\300\377PUV\377\214.46\377\2RWY\377\277\301\302\377\231\350" \
|
||||
"\354\340\377\1SXY\377\204.46\377\224\350\354\340\377\1GLN\377\217.46" \
|
||||
"\377\1\332\333\334\377\224\350\354\340\377\2\312\313\314\377QVX\377\216" \
|
||||
".46\377\2""6<>\377\207\213\214\377\220\350\354\340\377\1txz\377\223." \
|
||||
"46\377\1SXY\377\377\350\354\340\377\302\350\354\340\377\1\235\237\240" \
|
||||
"\377\216.46\377\1swx\377\224\350\354\340\377\1kpq\377\215.46\377\2""7" \
|
||||
"=\77\377\317\321\321\377\227\350\354\340\377\1\210\214\215\377\220.4" \
|
||||
"6\377\1\211\214\215\377\230\350\354\340\377\1SXY\377\204.46\377\224\350" \
|
||||
"\354\340\377\1GLN\377\217.46\377\1\334\335\335\377\223\350\354\340\377" \
|
||||
"\2\225\230\231\377068\377\220.46\377\1JOQ\377\220\350\354\340\377\1k" \
|
||||
"pq\377\223.46\377\1SXY\377\377\350\354\340\377\302\350\354\340\377\1" \
|
||||
"\235\237\240\377\204.46\377\1@FG\377\202JOQ\377\2FKM\377068\377\206." \
|
||||
"46\377\1\257\261\262\377\223\350\354\340\377\1kpq\377\204.46\377\1GL" \
|
||||
"N\377\202JOQ\377\1AFH\377\206.46\377\1GMN\377\226\350\354\340\377\1g" \
|
||||
"lm\377\207.46\377\4<BC\377QVX\377RWY\377>CE\377\207.46\377\1glm\377\227" \
|
||||
"\350\354\340\377\1SXY\377\204.46\377\224\350\354\340\377\1GLN\377\203" \
|
||||
".46\377\1/57\377\213<BC\377\1\350\351\351\377\222\350\354\340\377\1\204" \
|
||||
"\210\211\377\207.46\377\6INP\377fjl\377txy\377imo\377QVX\37728:\377\205" \
|
||||
".46\377\1\255\257\260\377\220\350\354\340\377\1uy{\377\206<BC\377\1;" \
|
||||
"AC\377\204.46\377\1""068\377\207<BC\377\1^ce\377\377\350\354\340\377" \
|
||||
"\302\350\354\340\377\1\235\237\240\377\204.46\377\1\265\267\270\377\204" \
|
||||
"\350\354\340\377\2\250\253\253\3776<>\377\204.46\377\1SXY\377\223\350" \
|
||||
"\354\340\377\1kpq\377\204.46\377\1\346\347\347\377\203\350\354\340\377" \
|
||||
"\2\352\354\345\377\207\213\214\377\205.46\377\1\271\273\274\377\224\350" \
|
||||
"\354\340\377\1z~\177\377\205.46\377\3""5;=\377\213\217\220\377\327\330" \
|
||||
"\330\377\204\350\354\340\377\3\334\335\335\377\223\226\227\3778>\77\377" \
|
||||
"\205.46\377\1y|~\377\226\350\354\340\377\1SXY\377\204.46\377\224\350" \
|
||||
"\354\340\377\1GLN\377\203.46\377\1:@B\377\235\350\354\340\377\1\240\243" \
|
||||
"\244\377\205.46\377\3:@B\377\224\230\231\377\344\345\345\377\206\350" \
|
||||
"\354\340\377\5\306\307\310\377\202\205\206\377:@B\377.46\377GMN\377\231" \
|
||||
"\350\354\340\377\204.46\377\1SXY\377\377\350\354\340\377\312\350\354" \
|
||||
"\340\377\1\235\237\240\377\204.46\377\1\265\267\270\377\205\350\354\340" \
|
||||
"\377\1\255\257\260\377\205.46\377\1\351\354\343\377\222\350\354\340\377" \
|
||||
"\1kpq\377\204.46\377\1\346\347\347\377\205\350\354\340\377\1z~\177\377" \
|
||||
"\204.46\377\1\210\214\215\377\223\350\354\340\377\1\257\262\263\377\205" \
|
||||
".46\377\2^bd\377\350\352\351\377\210\350\354\340\377\2\351\354\343\377" \
|
||||
"glm\377\205.46\377\1\253\256\257\377\225\350\354\340\377\1SXY\377\204" \
|
||||
".46\377\224\350\354\340\377\1GLN\377\203.46\377\1:@B\377\234\350\354" \
|
||||
"\340\377\2\332\333\334\37728:\377\204.46\377\2[`a\377\347\350\350\377" \
|
||||
"\213\350\354\340\377\2\237\242\243\377\264\266\266\377\231\350\354\340" \
|
||||
"\377\204.46\377\1SXY\377\377\350\354\340\377\312\350\354\340\377\1\235" \
|
||||
"\237\240\377\204.46\377\1\265\267\270\377\206\350\354\340\377\205.46" \
|
||||
"\377\1\330\331\331\377\222\350\354\340\377\1kpq\377\204.46\377\1\346" \
|
||||
"\347\347\377\205\350\354\340\377\1\310\312\312\377\204.46\377\1quw\377" \
|
||||
"\223\350\354\340\377\1BGI\377\204.46\377\1gkl\377\214\350\354\340\377" \
|
||||
"\1txy\377\204.46\377\1AFH\377\225\350\354\340\377\1SXY\377\204.46\377" \
|
||||
"\224\350\354\340\377\1GLN\377\203.46\377\1:@B\377\234\350\354\340\377" \
|
||||
"\1jnp\377\204.46\377\1UZ\\\377\250\350\354\340\377\204.46\377\1SXY\377" \
|
||||
"\377\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377" \
|
||||
"\1\265\267\270\377\205\350\354\340\377\1\352\354\345\377\205.46\377\1" \
|
||||
"\340\341\341\377\222\350\354\340\377\1kpq\377\204.46\377\1\346\347\347" \
|
||||
"\377\205\350\354\340\377\1\271\273\273\377\204.46\377\1\201\204\206\377" \
|
||||
"\222\350\354\340\377\1\234\237\240\377\204.46\377\1CIJ\377\216\350\354" \
|
||||
"\340\377\1PUV\377\204.46\377\1\233\236\237\377\224\350\354\340\377\1" \
|
||||
"SXY\377\204.46\377\224\350\354\340\377\1GLN\377\203.46\377\1:@B\377\233" \
|
||||
"\350\354\340\377\1\341\342\342\377\204.46\377\2""179\377\335\336\337" \
|
||||
"\377\250\350\354\340\377\204.46\377\1SXY\377\377\350\354\340\377\312" \
|
||||
"\350\354\340\377\1\235\237\240\377\204.46\377\1\265\267\270\377\205\350" \
|
||||
"\354\340\377\1\222\225\226\377\204.46\377\1""068\377\223\350\354\340" \
|
||||
"\377\1kpq\377\204.46\377\1\346\347\347\377\205\350\354\340\377\1bfh\377" \
|
||||
"\204.46\377\1\235\237\240\377\222\350\354\340\377\1V[]\377\204.46\377" \
|
||||
"\1\253\256\257\377\216\350\354\340\377\1\273\275\276\377\204.46\377\1" \
|
||||
"TYZ\377\224\350\354\340\377\1SXY\377\204.46\377\224\350\354\340\377\1" \
|
||||
"GLN\377\203.46\377\1:@B\377\233\350\354\340\377\1\231\233\234\377\204" \
|
||||
".46\377\1y}\177\377\251\350\354\340\377\204.46\377\1SXY\377\377\350\354" \
|
||||
"\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377\1\265\267\270" \
|
||||
"\377\203\350\354\340\377\3\345\346\346\377\206\211\212\377/57\377\204" \
|
||||
".46\377\1[`a\377\223\350\354\340\377\1kpq\377\204.46\377\1\346\347\347" \
|
||||
"\377\203\350\354\340\377\2\323\324\324\377fjl\377\204.46\377\2/57\377" \
|
||||
"\336\337\337\377\221\350\354\340\377\1\345\346\346\377\204.46\377\1""9" \
|
||||
"\77A\377\220\350\354\340\377\1BHJ\377\204.46\377\1\341\342\342\377\223" \
|
||||
"\350\354\340\377\1SXY\377\204.46\377\224\350\354\340\377\1GLN\377\203" \
|
||||
".46\377\1:@B\377\233\350\354\340\377\1gkl\377\204.46\377\1\300\302\302" \
|
||||
"\377\251\350\354\340\377\204.46\377\1SXY\377\377\350\354\340\377\312" \
|
||||
"\350\354\340\377\1\235\237\240\377\204.46\377\1""7=\77\377\203<BC\377" \
|
||||
"\1/57\377\206.46\377\1\257\262\263\377\223\350\354\340\377\1kpq\377\204" \
|
||||
".46\377\1:@B\377\202<BC\377\1""9>@\377\206.46\377\1\200\204\205\377\222" \
|
||||
"\350\354\340\377\1\302\303\304\377\204.46\377\1rvw\377\220\350\354\340" \
|
||||
"\377\1~\202\203\377\204.46\377\1\274\276\276\377\223\350\354\340\377" \
|
||||
"\1SXY\377\204.46\377\224\350\354\340\377\1GLN\377\203.46\377\1""179\377" \
|
||||
"\211fjl\377\1\311\312\313\377\221\350\354\340\377\1@FG\377\204.46\377" \
|
||||
"\1\352\354\345\377\251\350\354\340\377\204.46\377\1SXY\377\377\350\354" \
|
||||
"\340\377\312\350\354\340\377\1\235\237\240\377\216.46\377\1eik\377\224" \
|
||||
"\350\354\340\377\1kpq\377\215.46\377\1ptv\377\223\350\354\340\377\1\256" \
|
||||
"\260\261\377\204.46\377\1\217\222\223\377\220\350\354\340\377\1\235\237" \
|
||||
"\240\377\204.46\377\1\246\250\251\377\223\350\354\340\377\1SXY\377\204" \
|
||||
".46\377\224\350\354\340\377\1GLN\377\215.46\377\1\265\267\270\377\221" \
|
||||
"\350\354\340\377\1""179\377\203.46\377\1""39;\377\252\350\354\340\377" \
|
||||
"\204.46\377\1SXY\377\377\350\354\340\377\312\350\354\340\377\1\235\237" \
|
||||
"\240\377\215.46\377\1ptu\377\225\350\354\340\377\1kpq\377\213.46\377" \
|
||||
"\2:@B\377\255\257\260\377\224\350\354\340\377\1\236\241\242\377\204." \
|
||||
"46\377\1\235\237\240\377\220\350\354\340\377\1\251\253\254\377\204.4" \
|
||||
"6\377\1\231\233\234\377\223\350\354\340\377\1SXY\377\204.46\377\224\350" \
|
||||
"\354\340\377\1GLN\377\215.46\377\1\265\267\270\377\221\350\354\340\377" \
|
||||
"\204.46\377\1:@B\377\252\350\354\340\377\204.46\377\1SXY\377\377\350" \
|
||||
"\354\340\377\312\350\354\340\377\1\235\237\240\377\212.46\377\3""8>\77" \
|
||||
"\377ost\377\310\312\312\377\226\350\354\340\377\1kpq\377\213.46\377\2" \
|
||||
"7=\77\377\352\354\350\377\224\350\354\340\377\1\257\262\263\377\204." \
|
||||
"46\377\1\214\220\221\377\220\350\354\340\377\1\231\234\235\377\204.4" \
|
||||
"6\377\1\251\253\254\377\223\350\354\340\377\1SXY\377\204.46\377\224\350" \
|
||||
"\354\340\377\1GLN\377\215.46\377\1\265\267\270\377\221\350\354\340\377" \
|
||||
"\1""5;=\377\203.46\377\1""068\377\252\350\354\340\377\204.46\377\1SX" \
|
||||
"Y\377\377\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204." \
|
||||
"46\377\1x|}\377\202\253\256\257\377\3\254\257\257\377\300\302\302\377" \
|
||||
"\326\327\330\377\231\350\354\340\377\1kpq\377\204.46\377\1\302\303\304" \
|
||||
"\377\202\325\326\327\377\1\204\210\211\377\204.46\377\1\202\206\207\377" \
|
||||
"\224\350\354\340\377\1\304\306\306\377\204.46\377\1kpq\377\220\350\354" \
|
||||
"\340\377\1z~\177\377\204.46\377\1\275\277\277\377\223\350\354\340\377" \
|
||||
"\1SXY\377\204.46\377\224\350\354\340\377\1GLN\377\203.46\377\1""6<>\377" \
|
||||
"\211\271\273\274\377\1\346\347\347\377\221\350\354\340\377\1INP\377\204" \
|
||||
".46\377\1\331\332\333\377\251\350\354\340\377\204.46\377\1SXY\377\377" \
|
||||
"\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377\1\251" \
|
||||
"\253\254\377\236\350\354\340\377\1kpq\377\204.46\377\1\346\347\347\377" \
|
||||
"\202\350\354\340\377\2\350\354\342\3779\77A\377\203.46\377\2""179\377" \
|
||||
"\336\337\337\377\223\350\354\340\377\2\351\352\350\377068\377\203.46" \
|
||||
"\377\1""5;=\377\220\350\354\340\377\1=BD\377\203.46\377\2/57\377\347" \
|
||||
"\350\350\377\223\350\354\340\377\1SXY\377\204.46\377\224\350\354\340" \
|
||||
"\377\1GLN\377\203.46\377\1:@B\377\233\350\354\340\377\1swx\377\204.4" \
|
||||
"6\377\1\235\240\241\377\251\350\354\340\377\204.46\377\1SXY\377\377\350" \
|
||||
"\354\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377\1\251\253" \
|
||||
"\254\377\236\350\354\340\377\1kpq\377\204.46\377\1\346\347\347\377\203" \
|
||||
"\350\354\340\377\1\224\230\231\377\204.46\377\1ptu\377\224\350\354\340" \
|
||||
"\377\1\\ab\377\204.46\377\1\242\244\245\377\216\350\354\340\377\1\260" \
|
||||
"\263\263\377\204.46\377\1Y^`\377\224\350\354\340\377\1SXY\377\204.46" \
|
||||
"\377\224\350\354\340\377\1GLN\377\203.46\377\1:@B\377\233\350\354\340" \
|
||||
"\377\1\250\253\253\377\204.46\377\1HMO\377\251\350\354\340\377\204.4" \
|
||||
"6\377\1SXY\377\377\350\354\340\377\312\350\354\340\377\1\235\237\240" \
|
||||
"\377\204.46\377\1\251\253\254\377\236\350\354\340\377\1kpq\377\204.4" \
|
||||
"6\377\1\346\347\347\377\204\350\354\340\377\1<BC\377\204.46\377\1\317" \
|
||||
"\320\320\377\223\350\354\340\377\1\245\247\250\377\204.46\377\2<BC\377" \
|
||||
"\346\347\347\377\214\350\354\340\377\2\351\354\343\377FKM\377\204.46" \
|
||||
"\377\1\243\246\247\377\224\350\354\340\377\1SXY\377\204.46\377\224\350" \
|
||||
"\354\340\377\1GLN\377\203.46\377\1:@B\377\234\350\354\340\377\1""5:<" \
|
||||
"\377\204.46\377\1\230\233\234\377\250\350\354\340\377\204.46\377\1SX" \
|
||||
"Y\377\377\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204." \
|
||||
"46\377\1\251\253\254\377\236\350\354\340\377\1kpq\377\204.46\377\1\346" \
|
||||
"\347\347\377\204\350\354\340\377\1\233\236\237\377\204.46\377\1^bd\377" \
|
||||
"\224\350\354\340\377\1INP\377\204.46\377\1W\\]\377\214\350\354\340\377" \
|
||||
"\1chi\377\204.46\377\1HMO\377\225\350\354\340\377\1SXY\377\204.46\377" \
|
||||
"\224\350\354\340\377\1GLN\377\203.46\377\1:@B\377\234\350\354\340\377" \
|
||||
"\1\205\210\212\377\204.46\377\2""068\377\267\271\272\377\215\350\354" \
|
||||
"\340\377\1\330\332\332\377\231\350\354\340\377\204.46\377\1SXY\377\377" \
|
||||
"\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377\1\251" \
|
||||
"\253\254\377\236\350\354\340\377\1kpq\377\204.46\377\1\346\347\347\377" \
|
||||
"\205\350\354\340\377\1@FG\377\204.46\377\1\274\276\276\377\223\350\354" \
|
||||
"\340\377\1\274\276\276\377\205.46\377\2MRT\377\327\330\330\377\210\350" \
|
||||
"\354\340\377\2\335\336\336\377UY[\377\205.46\377\1\272\274\275\377\225" \
|
||||
"\350\354\340\377\1=BD\377\203.46\377\1""6<>\377\224\350\354\340\377\1" \
|
||||
"GLN\377\203.46\377\1:@B\377\235\350\354\340\377\1AFH\377\204.46\377\2" \
|
||||
"/57\377\217\222\223\377\212\350\354\340\377\4\274\276\276\377bgh\377" \
|
||||
".46\377\327\330\330\377\230\350\354\340\377\204.46\377\1SXY\377\377\350" \
|
||||
"\354\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377\1\251\253" \
|
||||
"\254\377\236\350\354\340\377\1kpq\377\204.46\377\1\346\347\347\377\205" \
|
||||
"\350\354\340\377\1\240\243\244\377\204.46\377\1MRT\377\224\350\354\340" \
|
||||
"\377\1\220\224\225\377\205.46\377\3""068\377y}\177\377\302\304\305\377" \
|
||||
"\204\350\354\340\377\3\306\307\310\377\200\204\205\377179\377\205.46" \
|
||||
"\377\1\220\223\224\377\223\350\354\340\377\3\306\307\310\377\257\261" \
|
||||
"\262\377hmn\377\204.46\377\1_de\377\224\350\354\340\377\1GLN\377\203" \
|
||||
".46\377\1""9>@\377\213\343\344\344\377\222\350\354\340\377\2\313\315" \
|
||||
"\315\37739;\377\205.46\377\12@FG\377\212\215\216\377\302\303\304\377" \
|
||||
"\341\342\342\377\350\354\340\377\347\350\350\377\320\322\322\377\253" \
|
||||
"\256\257\377w{|\377=BD\377\203.46\377\1\212\215\216\377\230\350\354\340" \
|
||||
"\377\204.46\377\1SXY\377\377\350\354\340\377\312\350\354\340\377\1\235" \
|
||||
"\237\240\377\204.46\377\1\264\266\266\377\236\350\354\340\377\1kpq\377" \
|
||||
"\204.46\377\1\346\347\347\377\206\350\354\340\377\1BHJ\377\204.46\377" \
|
||||
"\1\251\253\254\377\224\350\354\340\377\1txz\377\210.46\377\2""7=\77\377" \
|
||||
"8>\77\377\210.46\377\1txz\377\224\350\354\340\377\1SXY\377\206.46\377" \
|
||||
"\1\251\253\254\377\224\350\354\340\377\1GLN\377\217.46\377\1\320\322" \
|
||||
"\322\377\222\350\354\340\377\2\276\300\301\3775;=\377\221.46\377\1@F" \
|
||||
"G\377\230\350\354\340\377\204.46\377\1SXY\377\377\350\354\340\377\312" \
|
||||
"\350\354\340\377\1\235\237\240\377\204.46\377\1\265\267\270\377\236\350" \
|
||||
"\354\340\377\1kpq\377\204.46\377\1\346\347\347\377\206\350\354\340\377" \
|
||||
"\1\246\251\252\377\204.46\377\1AFH\377\225\350\354\340\377\2\232\235" \
|
||||
"\236\377068\377\216.46\377\2""068\377\232\235\236\377\225\350\354\340" \
|
||||
"\377\1X]^\377\205.46\377\1LQS\377\225\350\354\340\377\1GLN\377\217.4" \
|
||||
"6\377\1\316\317\320\377\223\350\354\340\377\2\324\325\325\377NSU\377" \
|
||||
"\220.46\377\2""068\377\321\322\323\377\227\350\354\340\377\204.46\377" \
|
||||
"\1SXY\377\377\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204" \
|
||||
".46\377\1\265\267\270\377\236\350\354\340\377\1kpq\377\204.46\377\1\346" \
|
||||
"\347\347\377\207\350\354\340\377\1GLN\377\204.46\377\1\226\231\232\377" \
|
||||
"\225\350\354\340\377\2\317\320\320\377`ef\377\214.46\377\2bgh\377\317" \
|
||||
"\321\321\377\226\350\354\340\377\1_de\377\204.46\377\2:@B\377\332\333" \
|
||||
"\334\377\225\350\354\340\377\1GLN\377\217.46\377\1\316\317\320\377\225" \
|
||||
"\350\354\340\377\2\236\241\242\377BGI\377\214.46\377\3""8>\77\377~\201" \
|
||||
"\202\377\335\336\337\377\230\350\354\340\377\204.46\377\1SXY\377\377" \
|
||||
"\350\354\340\377\312\350\354\340\377\1\235\237\240\377\204.46\377\1\265" \
|
||||
"\267\270\377\236\350\354\340\377\1kpq\377\204.46\377\1\346\347\347\377" \
|
||||
"\207\350\354\340\377\1\254\257\257\377\204.46\377\2""8>\77\377\352\354" \
|
||||
"\350\377\226\350\354\340\377\3\311\312\313\377\200\204\205\377EJL\377" \
|
||||
"\206.46\377\3EJL\377\203\207\210\377\313\314\315\377\230\350\354\340" \
|
||||
"\377\1_de\377\202.46\377\3/57\377fjl\377\342\343\343\377\226\350\354" \
|
||||
"\340\377\1SXY\377\217<BC\377\1\307\311\311\377\227\350\354\340\377\4" \
|
||||
"\275\277\300\377~\201\202\377OTV\377068\377\204.46\377\4""39;\377QVX" \
|
||||
"\377\201\204\206\377\270\272\272\377\233\350\354\340\377\204.46\377\1" \
|
||||
"SXY\377\377\350\354\340\377\377\350\354\340\377\234\350\354\340\377\2" \
|
||||
"\345\346\346\377\317\321\321\377\202\275\277\300\377\2\317\321\321\377" \
|
||||
"\345\346\346\377\233\350\354\340\377\4\302\304\305\377\255\257\260\377" \
|
||||
"\301\302\303\377\346\346\347\377\304\350\354\340\377\4\346\347\347\377" \
|
||||
"\327\330\330\377\335\336\337\377\347\350\350\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354" \
|
||||
"\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377" \
|
||||
"\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350" \
|
||||
"\354\340\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340" \
|
||||
"\377\377\350\354\340\377\377\350\354\340\377\377\350\354\340\377\377" \
|
||||
"\350\354\340\377\377\350\354\340\377\246\350\354\340\377")
|
||||
|
||||
|
||||
4
meta-yocto/recipes-core/psplash/psplash_git.bbappend
Normal file
@@ -0,0 +1,4 @@
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
|
||||
|
||||
PRINC = "1"
|
||||
|
||||
@@ -4,13 +4,13 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
COMPATIBLE_MACHINE_atom-pc = "atom-pc"
|
||||
KMACHINE_atom-pc = "atom-pc"
|
||||
KBRANCH_atom-pc = "yocto/standard/preempt-rt/base"
|
||||
SRCREV_machine_pn-linux-yocto-rt_atom-pc = "0b805cce57f61a244eb3b8fce460b14f1be442b3"
|
||||
SRCREV_machine_pn-linux-yocto-rt_atom-pc = "2f9d925f5681eaae7f341cc1270c739e8b329c03"
|
||||
|
||||
# mpc8315e-rdb support
|
||||
COMPATIBLE_MACHINE_mpc8315e-rdb = "mpc8315e-rdb"
|
||||
KMACHINE_mpc8315e-rdb = "fsl-mpc8315e-rdb"
|
||||
KBRANCH_mpc8315e-rdb = "yocto/standard/preempt-rt/base"
|
||||
SRCREV_machine_pn-linux-yocto-rt_mpc8315e-rdb = "0b805cce57f61a244eb3b8fce460b14f1be442b3"
|
||||
SRCREV_machine_pn-linux-yocto-rt_mpc8315e-rdb = "2f9d925f5681eaae7f341cc1270c739e8b329c03"
|
||||
|
||||
# beagleboard support - 3.0 support has not yet been completed, build failure
|
||||
#COMPATIBLE_MACHINE_beagleboard = "beagleboard"
|
||||
@@ -22,4 +22,4 @@ SRCREV_machine_pn-linux-yocto-rt_mpc8315e-rdb = "0b805cce57f61a244eb3b8fce460b14
|
||||
COMPATIBLE_MACHINE_routerstationpro = "routerstationpro"
|
||||
KMACHINE_routerstationpro = "routerstationpro"
|
||||
KBRANCH_routerstationpro = "yocto/standard/preempt-rt/routerstationpro"
|
||||
SRCREV_machine_pn-linux-yocto-rt_routerstationpro = "43dcdffebb64d9ce2f5cdcb18bb74bd9c301133f"
|
||||
SRCREV_machine_pn-linux-yocto-rt_routerstationpro = "ac9de3df165099542c26a5c0a60cac4fb9965cb2"
|
||||
|
||||
@@ -4,10 +4,10 @@ KMACHINE_mpc8315e-rdb = "yocto/standard/fsl-mpc8315e-rdb"
|
||||
KMACHINE_beagleboard = "yocto/standard/beagleboard"
|
||||
|
||||
|
||||
SRCREV_machine_atom-pc ?= "1e18e44adbe79b846e382370eb29bc4b8cd5a1a0"
|
||||
SRCREV_machine_routerstationpro ?= "8f38705810634a84326d3a3ebe9653951aa4bf61"
|
||||
SRCREV_machine_mpc8315e-rdb ?= "58ffdb8000e34d2ba7c3ef278b26680b0886e8b5"
|
||||
SRCREV_machine_beagleboard ?= "6b4bf6173b0bd2d1619a8218bac66ebc4681dd35"
|
||||
SRCREV_machine_atom-pc ?= "9a49e496c5e01bf4265e6adcd98f9ab177041ed1"
|
||||
SRCREV_machine_routerstationpro ?= "3bce4d3144c0501efedb6de61599d81acc0946d6"
|
||||
SRCREV_machine_mpc8315e-rdb ?= "6ee43f85afcd4499b441ff8aa0a54a0706eabf00"
|
||||
SRCREV_machine_beagleboard ?= "368e38c673ffac8b37fc2a2d4c1e4a1e6f8abf19"
|
||||
|
||||
COMPATIBLE_MACHINE_mpc8315e-rdb = "mpc8315e-rdb"
|
||||
COMPATIBLE_MACHINE_routerstationpro = "routerstationpro"
|
||||
|
||||
19
meta-yocto/recipes-kernel/linux/linux-yocto_3.2.bbappend
Normal file
@@ -0,0 +1,19 @@
|
||||
KMACHINE_atom-pc = "atom-pc"
|
||||
KMACHINE_routerstationpro = "routerstationpro"
|
||||
KMACHINE_mpc8315e-rdb = "fsl-mpc8315e-rdb"
|
||||
KMACHINE_beagleboard = "beagleboard"
|
||||
|
||||
KBRANCH_atom-pc = "standard/default/common-pc/atom-pc"
|
||||
KBRANCH_routerstationpro = "standard/default/routerstationpro"
|
||||
KBRANCH_mpc8315e-rdb = "standard/default/fsl-mpc8315e-rdb"
|
||||
KBRANCH_beagleboard = "standard/default/beagleboard"
|
||||
|
||||
SRCREV_machine_atom-pc ?= "417fc778a86e81303bab5883b919ee422ec51c04"
|
||||
SRCREV_machine_routerstationpro ?= "e015d29f374cd986e15f636b6b84b514d95d76ed"
|
||||
SRCREV_machine_mpc8315e-rdb ?= "2349967f408cc60db2b1c89fcefffc81428f9341"
|
||||
SRCREV_machine_beagleboard ?= "417fc778a86e81303bab5883b919ee422ec51c04"
|
||||
|
||||
COMPATIBLE_MACHINE_mpc8315e-rdb = "mpc8315e-rdb"
|
||||
COMPATIBLE_MACHINE_routerstationpro = "routerstationpro"
|
||||
COMPATIBLE_MACHINE_beagleboard = "beagleboard"
|
||||
COMPATIBLE_MACHINE_atom-pc = "atom-pc"
|
||||
@@ -102,6 +102,8 @@ autotools_do_configure() {
|
||||
if [ -e ${S}/configure.in -o -e ${S}/configure.ac ]; then
|
||||
olddir=`pwd`
|
||||
cd ${S}
|
||||
# Remove any previous copy of the m4 macros
|
||||
rm -rf ${B}/aclocal-copy/
|
||||
if [ x"${acpaths}" = xdefault ]; then
|
||||
acpaths=
|
||||
for i in `find ${S} -maxdepth 2 -name \*.m4|grep -v 'aclocal.m4'| \
|
||||
@@ -149,7 +151,7 @@ autotools_do_configure() {
|
||||
else if grep "^[[:space:]]*AM_GNU_GETTEXT" $CONFIGURE_AC >/dev/null; then
|
||||
# We'd call gettextize here if it wasn't so broken...
|
||||
cp ${STAGING_DATADIR}/gettext/config.rpath ${AUTOTOOLS_AUXDIR}/
|
||||
if [ ! -e ${S}/po/Makefile.in.in ]; then
|
||||
if [ -d ${S}/po/ -a ! -e ${S}/po/Makefile.in.in ]; then
|
||||
cp ${STAGING_DATADIR}/gettext/po/Makefile.in.in ${S}/po/
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -9,7 +9,7 @@ inherit utility-tasks
|
||||
inherit metadata_scm
|
||||
inherit logging
|
||||
|
||||
OE_IMPORTS += "os sys time oe.path oe.utils oe.data oe.packagegroup"
|
||||
OE_IMPORTS += "os sys time oe.path oe.utils oe.data oe.packagegroup oe.sstatesig"
|
||||
OE_IMPORTS[type] = "list"
|
||||
|
||||
def oe_import(d):
|
||||
@@ -349,12 +349,12 @@ python () {
|
||||
if license == "INVALID":
|
||||
bb.fatal('This recipe does not have the LICENSE field set (%s)' % pn)
|
||||
|
||||
commercial_license = " %s " % d.getVar('COMMERCIAL_LICENSE', 1)
|
||||
import re
|
||||
pnr = "[ \t]%s[ \t]" % pn.replace('+', "\+")
|
||||
if commercial_license and re.search(pnr, commercial_license):
|
||||
bb.debug(1, "Skipping %s because it's commercially licensed" % pn)
|
||||
raise bb.parse.SkipPackage("because it may require a commercial license to ship in a product (listed in COMMERCIAL_LICENSE)")
|
||||
unmatched_license_flag = check_license_flags(d)
|
||||
if unmatched_license_flag:
|
||||
bb.debug(1, "Skipping %s because it has a restricted license not"
|
||||
" whitelisted in LICENSE_FLAGS_WHITELIST" % pn)
|
||||
raise bb.parse.SkipPackage("because it has a restricted license not"
|
||||
" whitelisted in LICENSE_FLAGS_WHITELIST")
|
||||
|
||||
# If we're building a target package we need to use fakeroot (pseudo)
|
||||
# in order to capture permissions, owners, groups and special files
|
||||
@@ -379,7 +379,7 @@ python () {
|
||||
import re
|
||||
this_host = d.getVar('HOST_SYS', 1)
|
||||
if not re.match(need_host, this_host):
|
||||
raise bb.parse.SkipPackage("incompatible with host %s" % this_host)
|
||||
raise bb.parse.SkipPackage("incompatible with host %s (not in COMPATIBLE_HOST)" % this_host)
|
||||
|
||||
need_machine = d.getVar('COMPATIBLE_MACHINE', 1)
|
||||
if need_machine:
|
||||
@@ -388,7 +388,7 @@ python () {
|
||||
if this_machine and not re.match(need_machine, this_machine):
|
||||
this_soc_family = d.getVar('SOC_FAMILY', 1)
|
||||
if (this_soc_family and not re.match(need_machine, this_soc_family)) or not this_soc_family:
|
||||
raise bb.parse.SkipPackage("incompatible with machine %s" % this_machine)
|
||||
raise bb.parse.SkipPackage("incompatible with machine %s (not in COMPATIBLE_MACHINE)" % this_machine)
|
||||
|
||||
|
||||
dont_want_license = d.getVar('INCOMPATIBLE_LICENSE', 1)
|
||||
@@ -453,13 +453,15 @@ python () {
|
||||
# We always try to scan SRC_URI for urls with machine overrides
|
||||
# unless the package sets SRC_URI_OVERRIDES_PACKAGE_ARCH=0
|
||||
#
|
||||
override = d.getVar('SRC_URI_OVERRIDES_PACKAGE_ARCH', 1)
|
||||
override = d.getVar('SRC_URI_OVERRIDES_PACKAGE_ARCH', True)
|
||||
if override != '0':
|
||||
paths = []
|
||||
for p in [ "${PF}", "${P}", "${PN}", "files", "" ]:
|
||||
path = bb.data.expand(os.path.join("${FILE_DIRNAME}", p, "${MACHINE}"), d)
|
||||
if os.path.isdir(path):
|
||||
paths.append(path)
|
||||
fpaths = (d.getVar('FILESPATH', True) or '').split(':')
|
||||
machine = d.getVar('MACHINE', True)
|
||||
for p in fpaths:
|
||||
if os.path.basename(p) == machine and os.path.isdir(p):
|
||||
paths.append(p)
|
||||
|
||||
if len(paths) != 0:
|
||||
for s in srcuri.split():
|
||||
if not s.startswith("file://"):
|
||||
@@ -468,7 +470,7 @@ python () {
|
||||
local = fetcher.localpath(s)
|
||||
for mp in paths:
|
||||
if local.startswith(mp):
|
||||
#bb.note("overriding PACKAGE_ARCH from %s to %s" % (pkg_arch, mach_arch))
|
||||
#bb.note("overriding PACKAGE_ARCH from %s to %s for %s" % (pkg_arch, mach_arch, pn))
|
||||
d.setVar('PACKAGE_ARCH', "${MACHINE_ARCH}")
|
||||
return
|
||||
|
||||
|
||||
@@ -38,8 +38,9 @@ BOOTDD_EXTRA_SPACE ?= "16384"
|
||||
|
||||
AUTO_SYSLINUXCFG = "1"
|
||||
LABELS = "boot"
|
||||
APPEND = "root=/dev/sda2"
|
||||
TIMEOUT = "10"
|
||||
SYSLINUX_ROOT ?= "root=/dev/sda2"
|
||||
SYSLINUX_TIMEOUT = "10" # 1 second
|
||||
|
||||
SYSLINUXCFG = "${HDDDIR}/syslinux.cfg"
|
||||
SYSLINUXMENU = "${HDDDIR}/menu"
|
||||
|
||||
@@ -50,6 +51,7 @@ build_boot_dd() {
|
||||
|
||||
install -d ${HDDDIR}
|
||||
install -m 0644 ${STAGING_DIR_HOST}/kernel/bzImage ${HDDDIR}/vmlinuz
|
||||
install -m 0644 ${S}/syslinux.cfg ${HDDDIR}/syslinux.cfg
|
||||
install -m 444 ${STAGING_LIBDIR}/syslinux/ldlinux.sys ${HDDDIR}/ldlinux.sys
|
||||
|
||||
BLOCKS=`du -bks ${HDDDIR} | cut -f 1`
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
# End result is two things:
|
||||
#
|
||||
# 1. A .hddimg file which is an msdos filesystem containing syslinux, a kernel,
|
||||
# an initrd and a rootfs image. These can be written to harddisks directly and
|
||||
# an initrd and a rootfs image. These can be written to harddisks directly and
|
||||
# also booted on USB flash disks (write them there with dd).
|
||||
#
|
||||
# 2. A CD .iso image
|
||||
|
||||
# Boot process is that the initrd will boot and process which label was selected
|
||||
# in syslinux. Actions based on the label are then performed (e.g. installing to
|
||||
# Boot process is that the initrd will boot and process which label was selected
|
||||
# in syslinux. Actions based on the label are then performed (e.g. installing to
|
||||
# an hdd)
|
||||
|
||||
# External variables (also used by syslinux.bbclass)
|
||||
@@ -29,14 +29,14 @@ do_bootimg[depends] += "dosfstools-native:do_populate_sysroot \
|
||||
PACKAGES = " "
|
||||
EXCLUDE_FROM_WORLD = "1"
|
||||
|
||||
HDDDIR = "${S}/hdd/boot"
|
||||
ISODIR = "${S}/cd"
|
||||
HDDDIR = "${S}/hddimg"
|
||||
ISODIR = "${S}/iso"
|
||||
|
||||
BOOTIMG_VOLUME_ID ?= "boot"
|
||||
BOOTIMG_EXTRA_SPACE ?= "512"
|
||||
|
||||
EFI = ${@base_contains("MACHINE_FEATURES", "efi", "1", "0", d)}
|
||||
EFI_CLASS = ${@base_contains("MACHINE_FEATURES", "efi", "grub-efi", "dummy", d)}
|
||||
EFI = "${@base_contains("MACHINE_FEATURES", "efi", "1", "0", d)}"
|
||||
EFI_CLASS = "${@base_contains("MACHINE_FEATURES", "efi", "grub-efi", "dummy", d)}"
|
||||
|
||||
# Include legacy boot if MACHINE_FEATURES includes "pcbios" or if it does not
|
||||
# contain "efi". This way legacy is supported by default if neither is
|
||||
@@ -52,12 +52,28 @@ def pcbios_class(d):
|
||||
return "syslinux"
|
||||
return "dummy"
|
||||
|
||||
PCBIOS = ${@pcbios(d)}
|
||||
PCBIOS_CLASS = ${@pcbios_class(d)}
|
||||
PCBIOS = "${@pcbios(d)}"
|
||||
PCBIOS_CLASS = "${@pcbios_class(d)}"
|
||||
|
||||
inherit ${PCBIOS_CLASS}
|
||||
inherit ${EFI_CLASS}
|
||||
|
||||
populate() {
|
||||
DEST=$1
|
||||
install -d ${DEST}
|
||||
|
||||
# Install bzImage, initrd, and rootfs.img in DEST for all loaders to use.
|
||||
install -m 0644 ${STAGING_DIR_HOST}/kernel/bzImage ${DEST}/vmlinuz
|
||||
|
||||
if [ -n "${INITRD}" ] && [ -s "${INITRD}" ]; then
|
||||
install -m 0644 ${INITRD} ${DEST}/initrd
|
||||
fi
|
||||
|
||||
if [ -n "${ROOTFS}" ] && [ -s "${ROOTFS}" ]; then
|
||||
install -m 0644 ${ROOTFS} ${DEST}/rootfs.img
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
build_iso() {
|
||||
# Only create an ISO if we have an INITRD and NOISO was not set
|
||||
@@ -66,7 +82,7 @@ build_iso() {
|
||||
return
|
||||
fi
|
||||
|
||||
install -d ${ISODIR}
|
||||
populate ${ISODIR}
|
||||
|
||||
if [ "${PCBIOS}" = "1" ]; then
|
||||
syslinux_iso_populate
|
||||
@@ -95,7 +111,8 @@ build_iso() {
|
||||
build_hddimg() {
|
||||
# Create an HDD image
|
||||
if [ "${NOHDD}" != "1" ] ; then
|
||||
install -d ${HDDDIR}
|
||||
populate ${HDDDIR}
|
||||
|
||||
if [ "${PCBIOS}" = "1" ]; then
|
||||
syslinux_hddimg_populate
|
||||
fi
|
||||
@@ -103,19 +120,49 @@ build_hddimg() {
|
||||
grubefi_hddimg_populate
|
||||
fi
|
||||
|
||||
# Determine the 1024 byte block count for the final image.
|
||||
BLOCKS=`du --apparent-size -ks ${HDDDIR} | cut -f 1`
|
||||
SIZE=`expr $BLOCKS + ${BOOTIMG_EXTRA_SPACE}`
|
||||
# Calculate the size required for the final image including the
|
||||
# data and filesystem overhead.
|
||||
# Sectors: 512 bytes
|
||||
# Blocks: 1024 bytes
|
||||
|
||||
# Determine the sector count just for the data
|
||||
SECTORS=$(expr $(du --apparent-size -ks ${HDDDIR} | cut -f 1) \* 2)
|
||||
|
||||
# Account for the filesystem overhead. This includes directory
|
||||
# entries in the clusters as well as the FAT itself.
|
||||
# Assumptions:
|
||||
# FAT32 (12 or 16 may be selected by mkdosfs, but the extra
|
||||
# padding will be minimal on those smaller images and not
|
||||
# worth the logic here to caclulate the smaller FAT sizes)
|
||||
# < 16 entries per directory
|
||||
# 8.3 filenames only
|
||||
|
||||
# 32 bytes per dir entry
|
||||
DIR_BYTES=$(expr $(find ${HDDDIR} | tail -n +2 | wc -l) \* 32)
|
||||
# 32 bytes for every end-of-directory dir entry
|
||||
DIR_BYTES=$(expr $DIR_BYTES + $(expr $(find ${HDDDIR} -type d | tail -n +2 | wc -l) \* 32))
|
||||
# 4 bytes per FAT entry per sector of data
|
||||
FAT_BYTES=$(expr $SECTORS \* 4)
|
||||
# 4 bytes per FAT entry per end-of-cluster list
|
||||
FAT_BYTES=$(expr $FAT_BYTES + $(expr $(find ${HDDDIR} -type d | tail -n +2 | wc -l) \* 4))
|
||||
|
||||
# Use a ceiling function to determine FS overhead in sectors
|
||||
DIR_SECTORS=$(expr $(expr $DIR_BYTES + 511) / 512)
|
||||
# There are two FATs on the image
|
||||
FAT_SECTORS=$(expr $(expr $(expr $FAT_BYTES + 511) / 512) \* 2)
|
||||
SECTORS=$(expr $SECTORS + $(expr $DIR_SECTORS + $FAT_SECTORS))
|
||||
|
||||
# Determine the final size in blocks accounting for some padding
|
||||
BLOCKS=$(expr $(expr $SECTORS / 2) + ${BOOTIMG_EXTRA_SPACE})
|
||||
|
||||
# Ensure total sectors is an integral number of sectors per
|
||||
# track or mcopy will complain. Sectors are 512 bytes, and and
|
||||
# we generate images with 32 sectors per track. This calculation
|
||||
# is done in blocks, which are twice the size of sectors, thus
|
||||
# the 16 instead of 32.
|
||||
SIZE=$(expr $SIZE + $(expr 16 - $(expr $SIZE % 16)))
|
||||
# track or mcopy will complain. Sectors are 512 bytes, and we
|
||||
# generate images with 32 sectors per track. This calculation is
|
||||
# done in blocks, thus the mod by 16 instead of 32.
|
||||
BLOCKS=$(expr $BLOCKS + $(expr 16 - $(expr $BLOCKS % 16)))
|
||||
|
||||
IMG=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.hddimg
|
||||
mkdosfs -n ${BOOTIMG_VOLUME_ID} -S 512 -C ${IMG} ${SIZE}
|
||||
mkdosfs -n ${BOOTIMG_VOLUME_ID} -S 512 -C ${IMG} ${BLOCKS}
|
||||
# Copy HDDDIR recursively into the image file directly
|
||||
mcopy -i ${IMG} -s ${HDDDIR}/* ::/
|
||||
|
||||
|
||||
@@ -123,8 +123,16 @@ python buildhistory_emit_pkghistory() {
|
||||
except EnvironmentError:
|
||||
return None
|
||||
|
||||
def squashspaces(string):
|
||||
return re.sub("\s+", " ", string)
|
||||
def sortpkglist(string):
|
||||
pkgiter = re.finditer(r'[a-zA-Z0-9.+-]+( \([><=]+ [^ )]+\))?', string, 0)
|
||||
pkglist = [p.group(0) for p in pkgiter]
|
||||
pkglist.sort()
|
||||
return ' '.join(pkglist)
|
||||
|
||||
def sortlist(string):
|
||||
items = string.split(' ')
|
||||
items.sort()
|
||||
return ' '.join(items)
|
||||
|
||||
pn = d.getVar('PN', True)
|
||||
pe = d.getVar('PE', True) or "0"
|
||||
@@ -136,7 +144,7 @@ python buildhistory_emit_pkghistory() {
|
||||
rcpinfo.pe = pe
|
||||
rcpinfo.pv = pv
|
||||
rcpinfo.pr = pr
|
||||
rcpinfo.depends = squashspaces(d.getVar('DEPENDS', True) or "")
|
||||
rcpinfo.depends = sortlist(squashspaces(d.getVar('DEPENDS', True) or ""))
|
||||
rcpinfo.packages = packages
|
||||
write_recipehistory(rcpinfo, d)
|
||||
write_latestlink(None, pe, pv, pr, d)
|
||||
@@ -164,8 +172,8 @@ python buildhistory_emit_pkghistory() {
|
||||
pkginfo.pe = pe
|
||||
pkginfo.pv = pv
|
||||
pkginfo.pr = pr
|
||||
pkginfo.rdepends = squashspaces(getpkgvar(pkg, 'RDEPENDS') or "")
|
||||
pkginfo.rrecommends = squashspaces(getpkgvar(pkg, 'RRECOMMENDS') or "")
|
||||
pkginfo.rdepends = sortpkglist(squashspaces(getpkgvar(pkg, 'RDEPENDS') or ""))
|
||||
pkginfo.rrecommends = sortpkglist(squashspaces(getpkgvar(pkg, 'RRECOMMENDS') or ""))
|
||||
pkginfo.files = squashspaces(getpkgvar(pkg, 'FILES') or "")
|
||||
|
||||
# Gather information about packaged files
|
||||
@@ -178,6 +186,7 @@ python buildhistory_emit_pkghistory() {
|
||||
fstat = os.lstat(os.path.join(root, f))
|
||||
pkginfo.size += fstat.st_size
|
||||
filelist.append(os.sep + os.path.join(relpth, f))
|
||||
filelist.sort()
|
||||
pkginfo.filelist = " ".join(filelist)
|
||||
|
||||
write_pkghistory(pkginfo, d)
|
||||
@@ -278,12 +287,12 @@ buildhistory_get_image_installed() {
|
||||
echo $pkgsize $pkg >> ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp
|
||||
fi
|
||||
|
||||
deps=`list_package_depends $pkg`
|
||||
deps=`list_package_depends $pkg | sort | uniq`
|
||||
for dep in $deps ; do
|
||||
echo "$pkg OPP $dep;" | sed -e 's:-:_:g' -e 's:\.:_:g' -e 's:+::g' | sed 's:OPP:->:g' >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
|
||||
done
|
||||
|
||||
recs=`list_package_recommends $pkg`
|
||||
recs=`list_package_recommends $pkg | sort | uniq`
|
||||
for rec in $recs ; do
|
||||
echo "$pkg OPP $rec [style=dotted];" | sed -e 's:-:_:g' -e 's:\.:_:g' -e 's:+::g' | sed 's:OPP:->:g' >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
|
||||
done
|
||||
@@ -310,7 +319,15 @@ buildhistory_get_image_installed() {
|
||||
buildhistory_get_imageinfo() {
|
||||
# List the files in the image, but exclude date/time etc.
|
||||
# This awk script is somewhat messy, but handles where the size is not printed for device files under pseudo
|
||||
( cd ${IMAGE_ROOTFS} && find . -ls | awk '{ if ( $7 ~ /[0-9]/ ) printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, $7, $11, $12, $13 ; else printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, 0, $10, $11, $12 }' > ${BUILDHISTORY_DIR_IMAGE}/files-in-image.txt )
|
||||
( cd ${IMAGE_ROOTFS} && find . -ls | awk '{ if ( $7 ~ /[0-9]/ ) printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, $7, $11, $12, $13 ; else printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, 0, $10, $11, $12 }' | sort -k5 > ${BUILDHISTORY_DIR_IMAGE}/files-in-image.txt )
|
||||
|
||||
# Record some machine-readable meta-information about the image
|
||||
echo -n > ${BUILDHISTORY_DIR_IMAGE}/image-info.txt
|
||||
cat >> ${BUILDHISTORY_DIR_IMAGE}/image-info.txt <<END
|
||||
${@buildhistory_get_imagevars(d)}
|
||||
END
|
||||
imagesize=`du -ks ${IMAGE_ROOTFS} | awk '{ print $1 }'`
|
||||
echo "IMAGESIZE = $imagesize" >> ${BUILDHISTORY_DIR_IMAGE}/image-info.txt
|
||||
|
||||
# Add some configuration information
|
||||
echo "${MACHINE}: ${IMAGE_BASENAME} configured for ${DISTRO} ${DISTRO_VERSION}" > ${BUILDHISTORY_DIR_IMAGE}/build-id
|
||||
@@ -330,6 +347,27 @@ def buildhistory_get_layers(d):
|
||||
return layertext
|
||||
|
||||
|
||||
def squashspaces(string):
|
||||
import re
|
||||
return re.sub("\s+", " ", string).strip()
|
||||
|
||||
|
||||
def buildhistory_get_imagevars(d):
|
||||
imagevars = "DISTRO DISTRO_VERSION USER_CLASSES IMAGE_CLASSES IMAGE_FEATURES IMAGE_LINGUAS IMAGE_INSTALL BAD_RECOMMENDATIONS ROOTFS_POSTPROCESS_COMMAND IMAGE_POSTPROCESS_COMMAND"
|
||||
listvars = "USER_CLASSES IMAGE_CLASSES IMAGE_FEATURES IMAGE_LINGUAS IMAGE_INSTALL BAD_RECOMMENDATIONS"
|
||||
|
||||
imagevars = imagevars.split()
|
||||
listvars = listvars.split()
|
||||
ret = ""
|
||||
for var in imagevars:
|
||||
value = d.getVar(var, True) or ""
|
||||
if var in listvars:
|
||||
# Squash out spaces
|
||||
value = squashspaces(value)
|
||||
ret += "%s = %s\n" % (var, value)
|
||||
return ret.rstrip('\n')
|
||||
|
||||
|
||||
buildhistory_commit() {
|
||||
if [ ! -d ${BUILDHISTORY_DIR} ] ; then
|
||||
# Code above that creates this dir never executed, so there can't be anything to commit
|
||||
@@ -345,7 +383,7 @@ buildhistory_commit() {
|
||||
repostatus=`git status --porcelain`
|
||||
if [ "$repostatus" != "" ] ; then
|
||||
git add ${BUILDHISTORY_DIR}/*
|
||||
HOSTNAME=`cat /etc/hostname 2>/dev/null || echo unknown`
|
||||
HOSTNAME=`hostname 2>/dev/null || echo unknown`
|
||||
git commit ${BUILDHISTORY_DIR}/ -m "Build ${BUILDNAME} of ${DISTRO} ${DISTRO_VERSION} for machine ${MACHINE} on $HOSTNAME" --author "${BUILDHISTORY_COMMIT_AUTHOR}" > /dev/null
|
||||
if [ "${BUILDHISTORY_PUSH_REPO}" != "" ] ; then
|
||||
git push -q ${BUILDHISTORY_PUSH_REPO}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
BUILDSTATS_BASE = ${TMPDIR}/buildstats/
|
||||
BNFILE = ${BUILDSTATS_BASE}/.buildname
|
||||
DEVFILE = ${BUILDSTATS_BASE}/.device
|
||||
BUILDSTATS_BASE = "${TMPDIR}/buildstats/"
|
||||
BNFILE = "${BUILDSTATS_BASE}/.buildname"
|
||||
DEVFILE = "${BUILDSTATS_BASE}/.device"
|
||||
|
||||
################################################################################
|
||||
# Build statistics gathering.
|
||||
@@ -61,11 +61,13 @@ def set_device(e):
|
||||
# we do not collect diskstats as the method to collect meaningful statistics
|
||||
# for these fs types requires a bit more research.
|
||||
############################################################################
|
||||
for line in open("/proc/diskstats", "r"):
|
||||
if majordev == int(line.split()[0]) and minordev == int(line.split()[1]):
|
||||
rdev=line.split()[2]
|
||||
else:
|
||||
rdev="NoLogicalDevice"
|
||||
rdev="NoLogicalDevice"
|
||||
try:
|
||||
for line in open("/proc/diskstats", "r"):
|
||||
if majordev == int(line.split()[0]) and minordev == int(line.split()[1]):
|
||||
rdev=line.split()[2]
|
||||
except:
|
||||
pass
|
||||
file = open(e.data.getVar('DEVFILE', True), "w")
|
||||
file.write(rdev)
|
||||
file.close()
|
||||
@@ -82,12 +84,15 @@ def get_diskstats(dev):
|
||||
# For info on what these are, see kernel doc file iostats.txt
|
||||
############################################################################
|
||||
DSTAT_KEYS = ['ReadsComp', 'ReadsMerged', 'SectRead', 'TimeReads', 'WritesComp', 'SectWrite', 'TimeWrite', 'IOinProgress', 'TimeIO', 'WTimeIO']
|
||||
for x in open("/proc/diskstats", "r"):
|
||||
if dev in x:
|
||||
diskstats_val = x.rstrip().split()[4:]
|
||||
diskstats = dict(itertools.izip(DSTAT_KEYS, diskstats_val))
|
||||
try:
|
||||
for x in open("/proc/diskstats", "r"):
|
||||
if dev in x:
|
||||
diskstats_val = x.rstrip().split()[4:]
|
||||
except IOError as e:
|
||||
return
|
||||
diskstats = dict(itertools.izip(DSTAT_KEYS, diskstats_val))
|
||||
return diskstats
|
||||
|
||||
|
||||
def set_diskdata(var, dev, data):
|
||||
data.setVar(var, get_diskstats(dev))
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ set( CMAKE_CXX_FLAGS_RELEASE "${OECMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "CXXFLA
|
||||
|
||||
# only search in the paths provided so cmake doesnt pick
|
||||
# up libraries and tools from the native build machine
|
||||
set( CMAKE_FIND_ROOT_PATH ${STAGING_DIR_HOST} ${STAGING_DIR_NATIVE} ${CROSS_DIR} ${OECMAKE_PERLNATIVE_DIR} ${OECMAKE_EXTRA_ROOT_PATH} )
|
||||
set( CMAKE_FIND_ROOT_PATH ${STAGING_DIR_HOST} ${STAGING_DIR_NATIVE} ${CROSS_DIR} ${OECMAKE_PERLNATIVE_DIR} ${OECMAKE_EXTRA_ROOT_PATH} ${EXTERNAL_TOOLCHAIN})
|
||||
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
|
||||
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
|
||||
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
|
||||
|
||||