source: Jenkinsfile@ aff7e86

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 aff7e86 was a33dcd5, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Forgot to stage som stuff

  • Property mode set to 100644
File size: 14.9 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 archiveArtifacts artifacts: "tests/crashes/**/*,lib/**/lib*.so*", fingerprint: true
174 }
175 throw err
176 }
177}
178
179def benchmark() {
180 Tools.BuildStage('Benchmark', Settings.RunBenchmark) {
181 dir (BuildDir) {
182 //Append bench results
183 sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
184 }
185 }
186}
187
188def build_doc() {
189 Tools.BuildStage('Documentation', Settings.BuildDocumentation) {
190 dir ('doc/user') {
191 make_doc()
192 }
193
194 dir ('doc/refrat') {
195 make_doc()
196 }
197 }
198}
199
200def publish() {
201 Tools.BuildStage('Publish', true) {
202
203 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
204
205 def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
206 def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
207
208 //Then publish the results
209 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , false, 'Compilation')
210 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff' , groupCompile , true , 'Compilation (relative)')
211 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch' , groupConcurrency, false, 'Context Switching')
212 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff' , groupConcurrency, true , 'Context Switching (relative)')
213 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, false, 'Mutual Exclusion')
214 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff' , groupConcurrency, true , 'Mutual Exclusion (relative)')
215 do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling' , groupConcurrency, false, 'Internal and External Scheduling')
216 do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling.diff', groupConcurrency, true , 'Internal and External Scheduling (relative)')
217 }
218}
219
220//===========================================================================================================
221//Routine responsible of sending the email notification once the build is completed
222//===========================================================================================================
223//Standard build email notification
224def email(boolean log) {
225 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
226 //Configurations for email format
227 echo 'Notifying users of result'
228
229 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
230 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
231 def email_body = """<p>This is an automated email from the Jenkins build machine. It was
232generated because of a git hooks/post-receive script following
233a ref change which was pushed to the C\u2200 repository.</p>
234""" + Tools.GitLogMessage()
235
236 def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
237
238 if( Settings && !Settings.Silent ) {
239 //send email notification
240 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
241 } else {
242 echo "Would send email to: ${email_to}"
243 echo "With title: ${email_subject}"
244 echo "Content: \n${email_body}"
245 }
246}
247
248//===========================================================================================================
249// Helper classes/variables/routines
250//===========================================================================================================
251//Description of a compiler (Must be serializable since pipelines are persistent)
252class CC_Desc implements Serializable {
253 public String name
254 public String CXX
255 public String CC
256 public String lto
257
258 CC_Desc(String name, String CXX, String CC, String lto) {
259 this.name = name
260 this.CXX = CXX
261 this.CC = CC
262 this.lto = lto
263 }
264}
265
266//Description of an architecture (Must be serializable since pipelines are persistent)
267class Arch_Desc implements Serializable {
268 public String name
269 public String flags
270 public String node
271
272 Arch_Desc(String name, String flags, String node) {
273 this.name = name
274 this.flags = flags
275 this.node = node
276 }
277}
278
279class BuildSettings implements Serializable {
280 public final CC_Desc Compiler
281 public final Arch_Desc Architecture
282 public final Boolean NewAST
283 public final Boolean RunAllTests
284 public final Boolean RunBenchmark
285 public final Boolean BuildDocumentation
286 public final Boolean Publish
287 public final Boolean Silent
288 public final Boolean IsSandbox
289 public final String DescLong
290 public final String DescShort
291
292 public String GitNewRef
293 public String GitOldRef
294
295 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
296 switch( param.Compiler ) {
297 case 'gcc-9':
298 this.Compiler = new CC_Desc('gcc-9', 'g++-9', 'gcc-9', '-flto=auto')
299 break
300 case 'gcc-8':
301 this.Compiler = new CC_Desc('gcc-8', 'g++-8', 'gcc-8', '-flto=auto')
302 break
303 case 'gcc-7':
304 this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7', '-flto=auto')
305 break
306 case 'gcc-6':
307 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')
308 break
309 case 'gcc-5':
310 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')
311 break
312 case 'gcc-4.9':
313 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')
314 break
315 case 'clang':
316 this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-9', '-flto=thin -flto-jobs=0')
317 break
318 default :
319 error "Unhandled compiler : ${cc}"
320 }
321
322 switch( param.Architecture ) {
323 case 'x64':
324 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
325 break
326 case 'x86':
327 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
328 break
329 default :
330 error "Unhandled architecture : ${arch}"
331 }
332
333 this.IsSandbox = (branch == "jenkins-sandbox")
334 this.NewAST = param.NewAST
335 this.RunAllTests = param.RunAllTests
336 this.RunBenchmark = param.RunBenchmark
337 this.BuildDocumentation = param.BuildDocumentation
338 this.Publish = param.Publish
339 this.Silent = param.Silent
340
341 def full = param.RunAllTests ? " (Full)" : ""
342 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
343
344 final ast = this.NewAST ? "New AST" : "Old AST"
345 this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
346AST Version : ${ ast.toString() }
347Architecture : ${ this.Architecture.name }
348Arc Flags : ${ this.Architecture.flags }
349Run All Tests : ${ this.RunAllTests.toString() }
350Run Benchmark : ${ this.RunBenchmark.toString() }
351Build Documentation : ${ this.BuildDocumentation.toString() }
352Publish : ${ this.Publish.toString() }
353Silent : ${ this.Silent.toString() }
354"""
355
356 this.GitNewRef = ''
357 this.GitOldRef = ''
358 }
359}
360
361class PlotGroup implements Serializable {
362 public String name
363 public String unit
364 public boolean log
365
366 PlotGroup(String name, String unit, boolean log) {
367 this.name = name
368 this.unit = unit
369 this.log = log
370 }
371}
372
373def prepare_build() {
374 // prepare the properties
375 properties ([ \
376 buildDiscarder(logRotator( \
377 artifactDaysToKeepStr: '', \
378 artifactNumToKeepStr: '', \
379 daysToKeepStr: '730', \
380 numToKeepStr: '1000' \
381 )), \
382 [$class: 'ParametersDefinitionProperty', \
383 parameterDefinitions: [ \
384 [$class: 'ChoiceParameterDefinition', \
385 description: 'Which compiler to use', \
386 name: 'Compiler', \
387 choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang', \
388 defaultValue: 'gcc-8', \
389 ], \
390 [$class: 'ChoiceParameterDefinition', \
391 description: 'The target architecture', \
392 name: 'Architecture', \
393 choices: 'x64\nx86', \
394 defaultValue: 'x64', \
395 ], \
396 [$class: 'BooleanParameterDefinition', \
397 description: 'If true, build compiler using new AST', \
398 name: 'NewAST', \
399 defaultValue: true, \
400 ], \
401 [$class: 'BooleanParameterDefinition', \
402 description: 'If false, only the quick test suite is ran', \
403 name: 'RunAllTests', \
404 defaultValue: false, \
405 ], \
406 [$class: 'BooleanParameterDefinition', \
407 description: 'If true, jenkins also runs benchmarks', \
408 name: 'RunBenchmark', \
409 defaultValue: false, \
410 ], \
411 [$class: 'BooleanParameterDefinition', \
412 description: 'If true, jenkins also builds documentation', \
413 name: 'BuildDocumentation', \
414 defaultValue: true, \
415 ], \
416 [$class: 'BooleanParameterDefinition', \
417 description: 'If true, jenkins also publishes results', \
418 name: 'Publish', \
419 defaultValue: false, \
420 ], \
421 [$class: 'BooleanParameterDefinition', \
422 description: 'If true, jenkins will not send emails', \
423 name: 'Silent', \
424 defaultValue: false, \
425 ], \
426 ],
427 ]])
428
429 // It's unfortunate but it looks like we need to checkout the entire repo just to get
430 // - the pretty git printer
431 // - Jenkins.tools
432 checkout scm
433
434 Tools = load "Jenkins/tools.groovy"
435
436 final settings = new BuildSettings(params, env.BRANCH_NAME)
437
438 currentBuild.description = settings.DescShort
439 echo settings.DescLong
440
441 return settings
442}
443
444def make_doc() {
445 def err = null
446 try {
447 sh 'make clean > /dev/null'
448 sh 'make > /dev/null 2>&1'
449 }
450 catch (Exception caughtError) {
451 err = caughtError //rethrow error later
452 sh 'cat build/*.log'
453 }
454 finally {
455 if (err) throw err // Must re-throw exception to propagate error
456 }
457}
458
459def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
460
461 if(new_data) {
462 echo "Publishing new data"
463 }
464
465 def series = new_data ? [[
466 file: "${file}.csv",
467 exclusionValues: '',
468 displayTableFlag: false,
469 inclusionFlag: 'OFF',
470 url: ''
471 ]] : [];
472
473 echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
474 dir("${BuildDir}/benchmark/") {
475 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
476 csvSeries: series,
477 group: "${group.name}",
478 title: "${title}",
479 style: 'lineSimple',
480 exclZero: false,
481 keepRecords: false,
482 logarithmic: !relative && group.log,
483 numBuilds: '120',
484 useDescr: true,
485 yaxis: group.unit,
486 yaxisMaximum: '',
487 yaxisMinimum: ''
488 }
489}
Note: See TracBrowser for help on using the repository browser.