source: Jenkinsfile@ bf22bc6

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

Disable lto since it remove necessary side effects

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