4 # Copyright (c) 2017 Vojtech Horky
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
11 # - Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # - Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # - The name of the author may not be used to endorse or promote products
17 # derived from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 from hbuild
.scheduler
import Task
, TaskException
, RunCommandException
36 list = os
.listdir(root
)
40 def create_hsct_conf(dir, profile
, repo_dir
, archive_format
, sources
= None):
41 with
open(dir + '/hsct.conf', 'w') as f
:
42 if profile
== 'mips32/malta-be':
43 profile
= 'mips32eb/malta-be'
45 profile_parts
= ( profile
+ '/').split('/')
47 f
.write("root = %s\n" % repo_dir
)
48 f
.write("arch = %s\n" % profile_parts
[0])
49 f
.write("machine = %s\n" % profile_parts
[1])
50 f
.write("parallel = 1\n")
51 f
.write("archive_format = %s\n" % archive_format
)
52 if not sources
is None:
53 f
.write("sources = %s\n" % sources
)
56 class CoastlineGetHarboursTask(Task
):
57 def __init__(self
, harbour_filter
):
58 self
.harbour_filter
= harbour_filter
59 Task
.__init
__(self
, None)
61 def get_harbour_dependencies(self
, harbour_file
):
63 cmd
= '. %s; echo $shiptugs;' % harbour_file
64 res
= self
.ctl
.run_command([ 'sh', '-c', cmd
], needs_output
=True)
65 return res
['stdout'].split()
66 except RunCommandException
as e
:
70 root
= self
.ctl
.get_dependency_data('dir')
71 self
.ctl
.dprint("Looking into %s", root
)
74 for name
in sorted_dir(root
):
75 path
= os
.path
.join(root
, name
)
76 canon
= os
.path
.join(path
, 'HARBOUR')
77 if os
.path
.isdir(path
) and os
.path
.exists(canon
) and os
.path
.isfile(canon
):
79 dependencies
[name
] = self
.get_harbour_dependencies(canon
)
81 # Clean-up the dependencies
83 deps
= dependencies
[h
]
87 dependencies
[h
].append(d
)
89 # Filter which harbours should be actually built
90 if 'ALL' in self
.harbour_filter
:
91 self
.harbour_filter
= dependencies
.keys()
93 harbours_to_build
= {}
95 if h
in self
.harbour_filter
:
96 harbours_to_build
[h
] = True
97 dependency_added
= True
98 while dependency_added
:
99 dependency_added
= False
100 so_far
= list(harbours_to_build
.keys())
102 for d
in dependencies
[h
]:
103 if not d
in harbours_to_build
:
104 harbours_to_build
[d
] = True
105 dependency_added
= True
107 self
.ctl
.dprint("harbours_to_build = %s", list(harbours_to_build
.keys()))
109 # Sort harbours in buildable order
111 remaining_dependencies
= dependencies
.copy()
112 while len(remaining_dependencies
) > 0:
113 self
.ctl
.dprint("remaining = %s", remaining_dependencies
)
115 for d
in remaining_dependencies
:
116 if len(remaining_dependencies
[d
]) == 0:
117 if d
in harbours_to_build
:
118 build_order
.append(d
)
120 # In every step we have to find (at least) one element to
123 raise TaskException("Circular dependency found!")
125 del remaining_dependencies
[l
]
126 for d
in remaining_dependencies
:
127 remaining_dependencies
[d
] = [x
for x
in remaining_dependencies
[d
] if x
!= l
]
130 self
.ctl
.dprint("harbours = %s", build_order
)
131 self
.ctl
.dprint("deps = %s" , dependencies
)
134 'harbours': build_order
,
135 'harbour_deps': dependencies
,
136 'coastline_root': root
139 class CoastlineFetchTask(Task
):
140 def __init__(self
, harbour
, root
, mirror
):
141 self
.harbour
= harbour
144 Task
.__init
__(self
, 'harbour-fetch', package
=harbour
)
147 self
.ctl
.run_command([ self
.root
+ '/hsct.sh', 'fetch', self
.harbour
], cwd
=self
.mirror
)
150 class CoastlineScheduleFetchesTask(Task
):
151 def __init__(self
, scheduler
):
152 self
.scheduler
= scheduler
153 Task
.__init
__(self
, None)
156 harbours
= self
.ctl
.get_dependency_data('harbours')
157 coastline_root
= self
.ctl
.make_temp_dir('repo/coastline')
159 mirror
= self
.ctl
.make_temp_dir('mirror')
160 create_hsct_conf(mirror
, 'mirror', 'not-really-needed', '')
164 task_name
= "coastline-fetch-%s" % h
165 self
.scheduler
.submit("Fetching tarballs for %s" % h
,
167 CoastlineFetchTask(h
, coastline_root
, mirror
))
168 tasks
[ h
] = task_name
173 class CoastlinePrebuildTask(Task
):
174 def __init__(self
, profile
, build_dir_basename
, archive_format
):
175 self
.profile
= profile
176 self
.build_dir_basename
= build_dir_basename
177 self
.archive_format
= archive_format
178 Task
.__init
__(self
, None)
181 root
= self
.ctl
.make_temp_dir('repo/coastline')
183 my_dir
= self
.ctl
.make_temp_dir('build/%s/coast' % self
.build_dir_basename
)
184 create_hsct_conf(my_dir
, self
.profile
,
185 self
.ctl
.make_temp_dir('build/%s/helenos' % self
.build_dir_basename
),
187 self
.ctl
.make_temp_dir('mirror/sources'))
189 self
.ctl
.run_command([ root
+ '/hsct.sh', 'update' ], cwd
=my_dir
)
191 create_hsct_conf(my_dir
, self
.profile
,
192 self
.ctl
.make_temp_dir('build/%s/helenos-nonexistent' % self
.build_dir_basename
),
194 self
.ctl
.make_temp_dir('mirror/sources'))
200 class CoastlineBuildTask(Task
):
201 def __init__(self
, harbour
, profile
, archive_format
):
202 self
.harbour
= harbour
203 self
.profile
= profile
204 self
.archive_format
= archive_format
205 Task
.__init
__(self
, 'harbour-build', package
=harbour
, arch
=profile
)
208 my_dir
= self
.ctl
.get_dependency_data('dir')
210 root
= self
.ctl
.make_temp_dir('repo/coastline')
212 res
= self
.ctl
.run_command([ root
+ '/hsct.sh', 'archive', self
.harbour
], cwd
=my_dir
)
216 # Add downloadable archive
217 profile_flat
= self
.profile
.replace("/", "-")
218 title
= "%s for %s" % ( self
.harbour
, self
.profile
)
219 target_filename
= '%s/%s-for-helenos-%s.%s' % ( profile_flat
, self
.harbour
, profile_flat
, self
.archive_format
)
220 current_filename
= '%s/archives/%s.%s' % ( my_dir
, self
.harbour
, self
.archive_format
)
221 self
.ctl
.add_downloadable_file(title
, target_filename
, current_filename
)
224 'harbour-{}'.format(self
.harbour
): current_filename
228 class CoastlineScheduleBuildsTask(Task
):
229 def __init__(self
, scheduler
, archive_format
):
230 self
.scheduler
= scheduler
231 self
.archive_format
=archive_format
232 Task
.__init
__(self
, None)
235 profiles
= self
.ctl
.get_dependency_data('profiles')
236 harbours
= self
.ctl
.get_dependency_data('harbours')
237 harbour_deps
= self
.ctl
.get_dependency_data('harbour_deps')
242 if p
== 'special/abs32le':
247 p_flat
= p
.replace("/", "-")
249 self
.scheduler
.submit("Preparing coastline for %s" % p
,
250 "coastline-prepare-for-%s" % p_flat
,
251 CoastlinePrebuildTask(p
, p_flat
, self
.archive_format
),
252 [ "helenos-build-%s" % p_flat
])
255 task_name
= "coastline-build-%s-for-%s" % (h
, p_flat
)
257 "coastline-prepare-for-%s" % p_flat
,
258 "coastline-fetch-%s" % h
260 for d
in harbour_deps
[ h
]:
261 deps
.append( "coastline-build-%s-for-%s" % (d
, p_flat
) )
262 self
.scheduler
.submit("Building %s for %s" % (h
, p
),
264 CoastlineBuildTask(h
, p
, self
.archive_format
),
267 ret
[p
][h
] = task_name
270 'harbour_tasks' : ret