source: Jenkinsfile@ 7a230fd

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 7a230fd was 7a230fd, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Tentative fix for global variable usage

  • Property mode set to 100644
File size: 12.6 KB
Line 
1#!groovy
2
3import groovy.transform.Field
4
5//===========================================================================================================
6// Main loop of the compilation
7//===========================================================================================================
8
9node('master') {
10 // Globals
11 BuildDir = pwd tmp: true
12 SrcDir = pwd tmp: false
13 Settings = null
14 StageName = ''
15
16 // Local variables
17 def err = null
18 def log_needed = false
19
20 currentBuild.result = "SUCCESS"
21
22 try {
23 //Wrap build to add timestamp to command line
24 wrap([$class: 'TimestamperBuildWrapper']) {
25
26 Settings = prepare_build()
27
28 node(Settings.Architecture.node) {
29 BuildDir = pwd tmp: true
30 SrcDir = pwd tmp: false
31
32 clean()
33
34 checkout()
35
36 build()
37
38 test()
39
40 benchmark()
41
42 build_doc()
43
44 publish()
45 }
46
47 // Update the build directories when exiting the node
48 BuildDir = pwd tmp: true
49 SrcDir = pwd tmp: false
50 }
51 }
52
53 //If an exception is caught we need to change the status and remember to
54 //attach the build log to the email
55 catch (Exception caughtError) {
56 //rethrow error later
57 err = caughtError
58
59 echo err.toString()
60
61 //An error has occured, the build log is relevent
62 log_needed = true
63
64 //Store the result of the build log
65 currentBuild.result = "${StageName} FAILURE".trim()
66 }
67
68 finally {
69 //Send email with final results if this is not a full build
70 email(log_needed)
71
72 echo 'Build Completed'
73
74 /* Must re-throw exception to propagate error */
75 if (err) {
76 throw err
77 }
78 }
79}
80//===========================================================================================================
81// Main compilation routines
82//===========================================================================================================
83def clean() {
84 build_stage('Cleanup') {
85 // clean the build by wipping the build directory
86 dir(BuildDir) {
87 deleteDir()
88 }
89 }
90}
91
92//Compilation script is done here but environnement set-up and error handling is done in main loop
93def checkout() {
94 build_stage('Checkout') {
95 //checkout the source code and clean the repo
96 final scmVars = checkout scm
97 Settings.GitNewRef = scmVars.GIT_COMMIT
98 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
99
100 echo GitLogMessage()
101 }
102}
103
104def build() {
105 build_stage('Build') {
106 // Build outside of the src tree to ease cleaning
107 dir (BuildDir) {
108 //Configure the conpilation (Output is not relevant)
109 //Use the current directory as the installation target so nothing escapes the sandbox
110 //Also specify the compiler by hand
111 targets=""
112 if( Settings.RunAllTests || Settings.RunBenchmark ) {
113 targets="--with-target-hosts='host:debug,host:nodebug'"
114 } else {
115 targets="--with-target-hosts='host:debug'"
116 }
117
118 sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
119
120 //Compile the project
121 sh 'make -j 8 --no-print-directory'
122 }
123 }
124}
125
126def test() {
127 build_stage('Test') {
128
129 dir (BuildDir) {
130 //Run the tests from the tests directory
131 if ( Settings.RunAllTests ) {
132 sh 'make --no-print-directory -C tests timeouts="--timeout=600" all-tests debug=yes'
133 sh 'make --no-print-directory -C tests timeouts="--timeout=600" all-tests debug=no '
134 }
135 else {
136 sh 'make --no-print-directory -C tests'
137 }
138 }
139 }
140}
141
142def benchmark() {
143 build_stage('Benchmark') {
144
145 if( !Settings.RunBenchmark ) return
146
147 dir (BuildDir) {
148 //Append bench results
149 sh "make --no-print-directory -C benchmark jenkins"
150 }
151 }
152}
153
154def build_doc() {
155 build_stage('Documentation') {
156
157 if( !Settings.BuildDocumentation ) return
158
159 dir ('doc/user') {
160 make_doc()
161 }
162
163 dir ('doc/refrat') {
164 make_doc()
165 }
166 }
167}
168
169@Field PlotGroup CompileGroup = new PlotGroup('Compilation', 'seconds', true)
170@Field PlotGroup ConcurrencyGroup = new PlotGroup('Concurrency', 'nanoseconds', false)
171
172def publish() {
173 build_stage('Publish') {
174
175 if( !Settings.Publish ) return
176 if( !Settings.RunBenchmark ) {
177 echo 'No results to publish!!!'
178 return
179 }
180
181 //Then publish the results
182 do_plot('compile', CompilationGroup, 'Compilation')
183
184 do_plot('ctxswitch', ConcurrencyGroup, 'Context Switching')
185
186 do_plot('mutex', ConcurrencyGroup, 'Mutual Exclusion')
187
188 do_plot('signal', ConcurrencyGroup, 'Internal and External Scheduling')
189 }
190}
191
192//===========================================================================================================
193//Routine responsible of sending the email notification once the build is completed
194//===========================================================================================================
195def GitLogMessage() {
196 if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
197
198 sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
199
200 def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
201 def gitLog = readFile("${BuildDir}/GIT_LOG")
202 def gitDiff = readFile("${BuildDir}/GIT_DIFF")
203
204 return """
205<pre>
206The branch ${env.BRANCH_NAME} has been updated.
207${gitUpdate}
208</pre>
209
210<p>Check console output at ${env.BUILD_URL} to view the results.</p>
211
212<p>- Status --------------------------------------------------------------</p>
213
214<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
215
216<p>- Log -----------------------------------------------------------------</p>
217
218<pre>
219${gitLog}
220</pre>
221
222<p>-----------------------------------------------------------------------</p>
223<pre>
224Summary of changes:
225${gitDiff}
226</pre>
227"""
228}
229
230//Standard build email notification
231def email(boolean log) {
232 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
233 //Configurations for email format
234 echo 'Notifying users of result'
235
236 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
237 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
238 def email_body = """<p>This is an automated email from the Jenkins build machine. It was
239generated because of a git hooks/post-receive script following
240a ref change which was pushed to the C∀ repository.</p>
241""" + GitLogMessage()
242
243 def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
244
245 if( Settings && !Settings.Silent ) {
246 //send email notification
247 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
248 } else {
249 echo "Would send email to: ${email_to}"
250 echo "With title: ${email_subject}"
251 echo "Content: \n${email_body}"
252 }
253}
254
255//===========================================================================================================
256// Helper classes/variables/routines
257//===========================================================================================================
258//Description of a compiler (Must be serializable since pipelines are persistent)
259class CC_Desc implements Serializable {
260 public String name
261 public String CXX
262 public String CC
263
264 CC_Desc(String name, String CXX, String CC) {
265 this.name = name
266 this.CXX = CXX
267 this.CC = CC
268 }
269}
270
271//Description of an architecture (Must be serializable since pipelines are persistent)
272class Arch_Desc implements Serializable {
273 public String name
274 public String flags
275 public String node
276
277 Arch_Desc(String name, String flags, String node) {
278 this.name = name
279 this.flags = flags
280 this.node = node
281 }
282}
283
284class BuildSettings implements Serializable {
285 public final CC_Desc Compiler
286 public final Arch_Desc Architecture
287 public final Boolean RunAllTests
288 public final Boolean RunBenchmark
289 public final Boolean BuildDocumentation
290 public final Boolean Publish
291 public final Boolean Silent
292 public final Boolean IsSandbox
293 public final String DescLong
294 public final String DescShort
295
296 public String GitNewRef
297 public String GitOldRef
298
299 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
300 switch( param.Compiler ) {
301 case 'gcc-6':
302 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
303 break
304 case 'gcc-5':
305 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
306 break
307 case 'gcc-4.9':
308 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
309 break
310 case 'clang':
311 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
312 break
313 default :
314 error "Unhandled compiler : ${cc}"
315 }
316
317 switch( param.Architecture ) {
318 case 'x64':
319 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
320 break
321 case 'x86':
322 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
323 break
324 default :
325 error "Unhandled architecture : ${arch}"
326 }
327
328 this.IsSandbox = (branch == "jenkins-sandbox")
329 this.RunAllTests = param.RunAllTests
330 this.RunBenchmark = param.RunBenchmark
331 this.BuildDocumentation = param.BuildDocumentation
332 this.Publish = param.Publish
333 this.Silent = param.Silent
334
335 def full = param.RunAllTests ? " (Full)" : ""
336 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
337
338 this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
339Architecture : ${ this.Architecture.name }
340Arc Flags : ${ this.Architecture.flags }
341Run All Tests : ${ this.RunAllTests.toString() }
342Run Benchmark : ${ this.RunBenchmark.toString() }
343Build Documentation : ${ this.BuildDocumentation.toString() }
344Publish : ${ this.Publish.toString() }
345Silent : ${ this.Silent.toString() }
346"""
347
348 this.GitNewRef = ''
349 this.GitOldRef = ''
350 }
351}
352
353class PlotGroup implements Serializable {
354 public String name
355 public String unit
356 public boolean log
357
358 PlotGroup(String name, String unit, boolean log) {
359 this.name = name
360 this.unit = unit
361 this.log = log
362 }
363}
364
365def prepare_build() {
366 // prepare the properties
367 properties ([ \
368 [$class: 'ParametersDefinitionProperty', \
369 parameterDefinitions: [ \
370 [$class: 'ChoiceParameterDefinition', \
371 description: 'Which compiler to use', \
372 name: 'Compiler', \
373 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
374 defaultValue: 'gcc-6', \
375 ], \
376 [$class: 'ChoiceParameterDefinition', \
377 description: 'The target architecture', \
378 name: 'Architecture', \
379 choices: 'x64\nx86', \
380 defaultValue: 'x64', \
381 ], \
382 [$class: 'BooleanParameterDefinition', \
383 description: 'If false, only the quick test suite is ran', \
384 name: 'RunAllTests', \
385 defaultValue: false, \
386 ], \
387 [$class: 'BooleanParameterDefinition', \
388 description: 'If true, jenkins also runs benchmarks', \
389 name: 'RunBenchmark', \
390 defaultValue: false, \
391 ], \
392 [$class: 'BooleanParameterDefinition', \
393 description: 'If true, jenkins also builds documentation', \
394 name: 'BuildDocumentation', \
395 defaultValue: true, \
396 ], \
397 [$class: 'BooleanParameterDefinition', \
398 description: 'If true, jenkins also publishes results', \
399 name: 'Publish', \
400 defaultValue: false, \
401 ], \
402 [$class: 'BooleanParameterDefinition', \
403 description: 'If true, jenkins will not send emails', \
404 name: 'Silent', \
405 defaultValue: false, \
406 ], \
407 ],
408 ]])
409
410 // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
411 checkout scm
412
413 final settings = new BuildSettings(params, env.BRANCH_NAME)
414
415 currentBuild.description = settings.DescShort
416 echo settings.DescLong
417
418 return settings
419}
420
421def build_stage(String name, Closure block ) {
422 StageName = name
423 echo " -------- ${StageName} -------- "
424 stage(name, block)
425}
426
427def make_doc() {
428 def err = null
429 try {
430 sh 'make clean > /dev/null'
431 sh 'make > /dev/null 2>&1'
432 }
433 catch (Exception caughtError) {
434 err = caughtError //rethrow error later
435 sh 'cat build/*.log'
436 }
437 finally {
438 if (err) throw err // Must re-throw exception to propagate error
439 }
440}
441
442def do_plot(String file, PlotGroup group, String title) {
443 echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
444 dir("${BuildDir}/benchmark/") {
445 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
446 csvSeries: [[
447 file: "${file}.csv",
448 exclusionValues: '',
449 displayTableFlag: false,
450 inclusionFlag: 'OFF',
451 url: ''
452 ]],
453 group: "${group.name}",
454 title: "${title}",
455 style: 'lineSimple',
456 exclZero: false,
457 keepRecords: false,
458 logarithmic: group.log,
459 numBuilds: '120',
460 useDescr: true,
461 yaxis: group.unit,
462 yaxisMaximum: '',
463 yaxisMinimum: ''
464 }
465}
Note: See TracBrowser for help on using the repository browser.