source: Jenkinsfile@ 32ab519

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

Jenkins now generates a setup.sh script when archiving test failures.
The script can be run to ease reproduction in gdb.

  • Property mode set to 100644
File size: 15.0 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 Tools = null
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 Tools.Clean()
33
34 Tools.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 // Store the result of the build log
57 currentBuild.result = "FAILURE"
58
59 // An error has occured, the build log is relevent
60 log_needed = true
61
62 // rethrow error later
63 err = caughtError
64
65 // print the error so it shows in the log
66 echo err.toString()
67 }
68
69 finally {
70 //Send email with final results if this is not a full build
71 email(log_needed)
72
73 echo 'Build Completed'
74
75 /* Must re-throw exception to propagate error */
76 if (err) {
77 throw err
78 }
79 }
80}
81//===========================================================================================================
82// Main compilation routines
83//===========================================================================================================
84def build() {
85 debug = true
86 release = Settings.RunAllTests || Settings.RunBenchmark
87 Tools.BuildStage('Build : configure', true) {
88 // Configure must be run inside the tree
89 dir (SrcDir) {
90 // Generate the necessary build files
91 sh './autogen.sh'
92 }
93
94 // Build outside of the src tree to ease cleaning
95 dir (BuildDir) {
96 //Configure the compilation (Output is not relevant)
97 //Use the current directory as the installation target so nothing escapes the sandbox
98 //Also specify the compiler by hand
99 targets=""
100 if( Settings.RunAllTests || Settings.RunBenchmark ) {
101 targets="--with-target-hosts='host:debug,host:nodebug'"
102 } else {
103 targets="--with-target-hosts='host:debug'"
104 }
105
106 ast = Settings.NewAST ? "--enable-new-ast" : "--disable-new-ast"
107
108 sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib ${targets} ${ast} --quiet --prefix=${BuildDir}"
109
110 // Configure libcfa
111 sh 'make -j 8 --no-print-directory configure-libcfa'
112 }
113 }
114
115 Tools.BuildStage('Build : cfa-cpp', true) {
116 // Build outside of the src tree to ease cleaning
117 dir (BuildDir) {
118 // Build driver
119 sh 'make -j 8 --no-print-directory -C driver'
120
121 // Build translator
122 sh 'make -j 8 --no-print-directory -C src'
123 }
124 }
125
126 Tools.BuildStage('Build : libcfa(debug)', debug) {
127 // Build outside of the src tree to ease cleaning
128 dir (BuildDir) {
129 sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
130 }
131 }
132
133 Tools.BuildStage('Build : libcfa(nodebug)', release) {
134 // Build outside of the src tree to ease cleaning
135 dir (BuildDir) {
136 sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
137 }
138 }
139
140 Tools.BuildStage('Build : install', true) {
141 // Build outside of the src tree to ease cleaning
142 dir (BuildDir) {
143 sh "make -j 8 --no-print-directory install"
144 }
145 }
146}
147
148def test() {
149 try {
150 // Print potential limits before testing
151 // in case jenkins messes with them
152 sh 'free -h'
153 sh 'ulimit -a'
154
155 Tools.BuildStage('Test: short', !Settings.RunAllTests) {
156 dir (BuildDir) {
157 //Run the tests from the tests directory
158 sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
159 }
160 }
161
162 Tools.BuildStage('Test: full', Settings.RunAllTests) {
163 dir (BuildDir) {
164 //Run the tests from the tests directory
165 sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
166 sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
167 }
168 }
169 }
170 catch (Exception err) {
171 echo "Archiving core dumps"
172 dir (BuildDir) {
173 sh """${SrcDir}/tools/jenkins/archive-gen.sh"""
174 archiveArtifacts artifacts: "tests/crashes/**/*,lib/**/lib*.so*,setup.sh", fingerprint: true
175 }
176 throw err
177 }
178}
179
180def benchmark() {
181 Tools.BuildStage('Benchmark', Settings.RunBenchmark) {
182 dir (BuildDir) {
183 //Append bench results
184 sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
185 }
186 }
187}
188
189def build_doc() {
190 Tools.BuildStage('Documentation', Settings.BuildDocumentation) {
191 dir ('doc/user') {
192 make_doc()
193 }
194
195 dir ('doc/refrat') {
196 make_doc()
197 }
198 }
199}
200
201def publish() {
202 Tools.BuildStage('Publish', true) {
203
204 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
205
206 def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
207 def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
208
209 //Then publish the results
210 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , false, 'Compilation')
211 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff' , groupCompile , true , 'Compilation (relative)')
212 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch' , groupConcurrency, false, 'Context Switching')
213 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff' , groupConcurrency, true , 'Context Switching (relative)')
214 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, false, 'Mutual Exclusion')
215 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff' , groupConcurrency, true , 'Mutual Exclusion (relative)')
216 do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling' , groupConcurrency, false, 'Internal and External Scheduling')
217 do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling.diff', groupConcurrency, true , 'Internal and External Scheduling (relative)')
218 }
219}
220
221//===========================================================================================================
222//Routine responsible of sending the email notification once the build is completed
223//===========================================================================================================
224//Standard build email notification
225def email(boolean log) {
226 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
227 //Configurations for email format
228 echo 'Notifying users of result'
229
230 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
231 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
232 def email_body = """<p>This is an automated email from the Jenkins build machine. It was
233generated because of a git hooks/post-receive script following
234a ref change which was pushed to the C\u2200 repository.</p>
235""" + Tools.GitLogMessage()
236
237 def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
238
239 if( Settings && !Settings.Silent ) {
240 //send email notification
241 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
242 } else {
243 echo "Would send email to: ${email_to}"
244 echo "With title: ${email_subject}"
245 echo "Content: \n${email_body}"
246 }
247}
248
249//===========================================================================================================
250// Helper classes/variables/routines
251//===========================================================================================================
252//Description of a compiler (Must be serializable since pipelines are persistent)
253class CC_Desc implements Serializable {
254 public String name
255 public String CXX
256 public String CC
257 public String lto
258
259 CC_Desc(String name, String CXX, String CC, String lto) {
260 this.name = name
261 this.CXX = CXX
262 this.CC = CC
263 this.lto = lto
264 }
265}
266
267//Description of an architecture (Must be serializable since pipelines are persistent)
268class Arch_Desc implements Serializable {
269 public String name
270 public String flags
271 public String node
272
273 Arch_Desc(String name, String flags, String node) {
274 this.name = name
275 this.flags = flags
276 this.node = node
277 }
278}
279
280class BuildSettings implements Serializable {
281 public final CC_Desc Compiler
282 public final Arch_Desc Architecture
283 public final Boolean NewAST
284 public final Boolean RunAllTests
285 public final Boolean RunBenchmark
286 public final Boolean BuildDocumentation
287 public final Boolean Publish
288 public final Boolean Silent
289 public final Boolean IsSandbox
290 public final String DescLong
291 public final String DescShort
292
293 public String GitNewRef
294 public String GitOldRef
295
296 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
297 switch( param.Compiler ) {
298 case 'gcc-9':
299 this.Compiler = new CC_Desc('gcc-9', 'g++-9', 'gcc-9', '-flto=auto')
300 break
301 case 'gcc-8':
302 this.Compiler = new CC_Desc('gcc-8', 'g++-8', 'gcc-8', '-flto=auto')
303 break
304 case 'gcc-7':
305 this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7', '-flto=auto')
306 break
307 case 'gcc-6':
308 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')
309 break
310 case 'gcc-5':
311 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')
312 break
313 case 'gcc-4.9':
314 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')
315 break
316 case 'clang':
317 this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-9', '-flto=thin -flto-jobs=0')
318 break
319 default :
320 error "Unhandled compiler : ${cc}"
321 }
322
323 switch( param.Architecture ) {
324 case 'x64':
325 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
326 break
327 case 'x86':
328 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
329 break
330 default :
331 error "Unhandled architecture : ${arch}"
332 }
333
334 this.IsSandbox = (branch == "jenkins-sandbox")
335 this.NewAST = param.NewAST
336 this.RunAllTests = param.RunAllTests
337 this.RunBenchmark = param.RunBenchmark
338 this.BuildDocumentation = param.BuildDocumentation
339 this.Publish = param.Publish
340 this.Silent = param.Silent
341
342 def full = param.RunAllTests ? " (Full)" : ""
343 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
344
345 final ast = this.NewAST ? "New AST" : "Old AST"
346 this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
347AST Version : ${ ast.toString() }
348Architecture : ${ this.Architecture.name }
349Arc Flags : ${ this.Architecture.flags }
350Run All Tests : ${ this.RunAllTests.toString() }
351Run Benchmark : ${ this.RunBenchmark.toString() }
352Build Documentation : ${ this.BuildDocumentation.toString() }
353Publish : ${ this.Publish.toString() }
354Silent : ${ this.Silent.toString() }
355"""
356
357 this.GitNewRef = ''
358 this.GitOldRef = ''
359 }
360}
361
362class PlotGroup implements Serializable {
363 public String name
364 public String unit
365 public boolean log
366
367 PlotGroup(String name, String unit, boolean log) {
368 this.name = name
369 this.unit = unit
370 this.log = log
371 }
372}
373
374def prepare_build() {
375 // prepare the properties
376 properties ([ \
377 buildDiscarder(logRotator( \
378 artifactDaysToKeepStr: '', \
379 artifactNumToKeepStr: '', \
380 daysToKeepStr: '730', \
381 numToKeepStr: '1000' \
382 )), \
383 [$class: 'ParametersDefinitionProperty', \
384 parameterDefinitions: [ \
385 [$class: 'ChoiceParameterDefinition', \
386 description: 'Which compiler to use', \
387 name: 'Compiler', \
388 choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang', \
389 defaultValue: 'gcc-8', \
390 ], \
391 [$class: 'ChoiceParameterDefinition', \
392 description: 'The target architecture', \
393 name: 'Architecture', \
394 choices: 'x64\nx86', \
395 defaultValue: 'x64', \
396 ], \
397 [$class: 'BooleanParameterDefinition', \
398 description: 'If true, build compiler using new AST', \
399 name: 'NewAST', \
400 defaultValue: true, \
401 ], \
402 [$class: 'BooleanParameterDefinition', \
403 description: 'If false, only the quick test suite is ran', \
404 name: 'RunAllTests', \
405 defaultValue: false, \
406 ], \
407 [$class: 'BooleanParameterDefinition', \
408 description: 'If true, jenkins also runs benchmarks', \
409 name: 'RunBenchmark', \
410 defaultValue: false, \
411 ], \
412 [$class: 'BooleanParameterDefinition', \
413 description: 'If true, jenkins also builds documentation', \
414 name: 'BuildDocumentation', \
415 defaultValue: true, \
416 ], \
417 [$class: 'BooleanParameterDefinition', \
418 description: 'If true, jenkins also publishes results', \
419 name: 'Publish', \
420 defaultValue: false, \
421 ], \
422 [$class: 'BooleanParameterDefinition', \
423 description: 'If true, jenkins will not send emails', \
424 name: 'Silent', \
425 defaultValue: false, \
426 ], \
427 ],
428 ]])
429
430 // It's unfortunate but it looks like we need to checkout the entire repo just to get
431 // - the pretty git printer
432 // - Jenkins.tools
433 checkout scm
434
435 Tools = load "Jenkins/tools.groovy"
436
437 final settings = new BuildSettings(params, env.BRANCH_NAME)
438
439 currentBuild.description = settings.DescShort
440 echo settings.DescLong
441
442 return settings
443}
444
445def make_doc() {
446 def err = null
447 try {
448 sh 'make clean > /dev/null'
449 sh 'make > /dev/null 2>&1'
450 }
451 catch (Exception caughtError) {
452 err = caughtError //rethrow error later
453 sh 'cat build/*.log'
454 }
455 finally {
456 if (err) throw err // Must re-throw exception to propagate error
457 }
458}
459
460def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
461
462 if(new_data) {
463 echo "Publishing new data"
464 }
465
466 def series = new_data ? [[
467 file: "${file}.csv",
468 exclusionValues: '',
469 displayTableFlag: false,
470 inclusionFlag: 'OFF',
471 url: ''
472 ]] : [];
473
474 echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
475 dir("${BuildDir}/benchmark/") {
476 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
477 csvSeries: series,
478 group: "${group.name}",
479 title: "${title}",
480 style: 'lineSimple',
481 exclZero: false,
482 keepRecords: false,
483 logarithmic: !relative && group.log,
484 numBuilds: '120',
485 useDescr: true,
486 yaxis: group.unit,
487 yaxisMaximum: '',
488 yaxisMinimum: ''
489 }
490}
Note: See TracBrowser for help on using the repository browser.