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 class CoastlineGetHarboursTask(Task
):
41 def __init__(self
, harbour_filter
):
42 self
.harbour_filter
= harbour_filter
43 Task
.__init
__(self
, None)
45 def get_harbour_dependencies(self
, harbour_file
):
47 cmd
= '. %s; echo $shiptugs;' % harbour_file
48 res
= self
.ctl
.run_command([ 'sh', '-c', cmd
], needs_output
=True)
49 return res
['stdout'].split()
50 except RunCommandException
as e
:
54 root
= self
.ctl
.get_dependency_data('dir')
55 self
.ctl
.dprint("Looking into %s", root
)
58 for name
in sorted_dir(root
):
59 path
= os
.path
.join(root
, name
)
60 canon
= os
.path
.join(path
, 'HARBOUR')
61 if os
.path
.isdir(path
) and os
.path
.exists(canon
) and os
.path
.isfile(canon
):
63 dependencies
[name
] = self
.get_harbour_dependencies(canon
)
65 # Clean-up the dependencies
67 deps
= dependencies
[h
]
71 dependencies
[h
].append(d
)
73 # Filter which harbours should be actually built
74 if 'ALL' in self
.harbour_filter
:
75 self
.harbour_filter
= dependencies
.keys()
77 harbours_to_build
= {}
79 if h
in self
.harbour_filter
:
80 harbours_to_build
[h
] = True
81 dependency_added
= True
82 while dependency_added
:
83 dependency_added
= False
84 so_far
= list(harbours_to_build
.keys())
86 for d
in dependencies
[h
]:
87 if not d
in harbours_to_build
:
88 harbours_to_build
[d
] = True
89 dependency_added
= True
91 self
.ctl
.dprint("harbours_to_build = %s", list(harbours_to_build
.keys()))
93 # Sort harbours in buildable order
95 remaining_dependencies
= dependencies
.copy()
96 while len(remaining_dependencies
) > 0:
97 self
.ctl
.dprint("remaining = %s", remaining_dependencies
)
99 for d
in remaining_dependencies
:
100 if len(remaining_dependencies
[d
]) == 0:
101 if d
in harbours_to_build
:
102 build_order
.append(d
)
104 # In every step we have to find (at least) one element to
107 raise TaskException("Circular dependency found!")
109 del remaining_dependencies
[l
]
110 for d
in remaining_dependencies
:
111 remaining_dependencies
[d
] = [x
for x
in remaining_dependencies
[d
] if x
!= l
]
114 self
.ctl
.dprint("harbours = %s", build_order
)
115 self
.ctl
.dprint("deps = %s" , dependencies
)
118 'harbours': build_order
,
119 'harbour_deps': dependencies
,
120 'coastline_root': root
123 class CoastlineFetchTask(Task
):
124 def __init__(self
, harbour
, root
, mirror
):
125 self
.harbour
= harbour
128 Task
.__init
__(self
, 'harbour-fetch', package
=harbour
)
131 self
.ctl
.run_command([ self
.root
+ '/hsct.sh', 'fetch', self
.harbour
], cwd
=self
.mirror
)
134 class CoastlineScheduleFetchesTask(Task
):
135 def __init__(self
, scheduler
):
136 self
.scheduler
= scheduler
137 Task
.__init
__(self
, None)
140 harbours
= self
.ctl
.get_dependency_data('harbours')
141 coastline_root
= self
.ctl
.make_temp_dir('repo/coastline')
143 mirror
= self
.ctl
.make_temp_dir('mirror')
147 task_name
= "coastline-fetch-%s" % h
148 self
.scheduler
.submit("Fetching tarballs for %s" % h
,
150 CoastlineFetchTask(h
, coastline_root
, mirror
))
151 tasks
[ h
] = task_name
156 class CoastlinePrebuildTask(Task
):
157 def __init__(self
, profile
, build_dir_basename
, archive_format
):
158 self
.profile
= profile
159 self
.build_dir_basename
= build_dir_basename
160 self
.archive_format
= archive_format
161 Task
.__init
__(self
, None)
164 root
= self
.ctl
.make_temp_dir('repo/coastline')
166 my_dir
= self
.ctl
.make_temp_dir('build/%s/coast' % self
.build_dir_basename
)
167 hsrootdir
= self
.ctl
.make_temp_dir('build/%s/helenos' % self
.build_dir_basename
)
168 self
.ctl
.run_command([ root
+ '/hsct.sh', 'init', hsrootdir
], cwd
=my_dir
)
169 with
open('%s/config.sh' % my_dir
, 'a') as cfg
:
170 cfg
.write("HSCT_FORMAT=\"%s\"\n" % self
.archive_format
)
171 cfg
.write("HSCT_SOURCES_DIR=\"%s\"\n" % self
.ctl
.make_temp_dir('mirror/sources'))
172 cfg
.write("HSCT_PARALLELISM=1\n")
178 class CoastlineBuildTask(Task
):
179 def __init__(self
, harbour
, profile
, archive_format
):
180 self
.harbour
= harbour
181 self
.profile
= profile
182 self
.archive_format
= archive_format
183 Task
.__init
__(self
, 'harbour-build', package
=harbour
, arch
=profile
)
186 my_dir
= self
.ctl
.get_dependency_data('dir')
188 root
= self
.ctl
.make_temp_dir('repo/coastline')
190 res
= self
.ctl
.run_command([ root
+ '/hsct.sh', 'archive', self
.harbour
], cwd
=my_dir
)
194 # Add downloadable archive
195 profile_flat
= self
.profile
.replace("/", "-")
196 title
= "%s for %s" % ( self
.harbour
, self
.profile
)
197 target_filename
= '%s/%s-for-helenos-%s.%s' % ( profile_flat
, self
.harbour
, profile_flat
, self
.archive_format
)
198 current_filename
= '%s/archives/%s.%s' % ( my_dir
, self
.harbour
, self
.archive_format
)
199 self
.ctl
.add_downloadable_file(title
, target_filename
, current_filename
)
202 'harbour-{}'.format(self
.harbour
): current_filename
206 class CoastlineScheduleBuildsTask(Task
):
207 def __init__(self
, scheduler
, archive_format
):
208 self
.scheduler
= scheduler
209 self
.archive_format
=archive_format
210 Task
.__init
__(self
, None)
213 profiles
= self
.ctl
.get_dependency_data('profiles')
214 harbours
= self
.ctl
.get_dependency_data('harbours')
215 harbour_deps
= self
.ctl
.get_dependency_data('harbour_deps')
220 if p
== 'special/abs32le':
225 p_flat
= p
.replace("/", "-")
227 self
.scheduler
.submit("Preparing coastline for %s" % p
,
228 "coastline-prepare-for-%s" % p_flat
,
229 CoastlinePrebuildTask(p
, p_flat
, self
.archive_format
),
230 [ "helenos-build-%s" % p_flat
])
233 task_name
= "coastline-build-%s-for-%s" % (h
, p_flat
)
235 "coastline-prepare-for-%s" % p_flat
,
236 "coastline-fetch-%s" % h
238 for d
in harbour_deps
[ h
]:
239 deps
.append( "coastline-build-%s-for-%s" % (d
, p_flat
) )
240 self
.scheduler
.submit("Building %s for %s" % (h
, p
),
242 CoastlineBuildTask(h
, p
, self
.archive_format
),
245 ret
[p
][h
] = task_name
248 'harbour_tasks' : ret