source: Jenkinsfile@ a8d8547

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

Fix error in previous commit

  • 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
9// Globals
10BuildDir = ""
11SrcDir = ""
12Settings = null
13Tools = null
14
15// Local variables
16def err = null
17def log_needed = false
18
19currentBuild.result = "SUCCESS"
20
21try {
22 //Wrap build to add timestamp to command line
23 wrap([$class: 'TimestamperBuildWrapper']) {
24
25 node {
26 Settings = prepare_build()
27 }
28
29 node(Settings.Architecture.node) {
30 BuildDir = pwd tmp: true
31 SrcDir = pwd tmp: false
32 currentBuild.description = "${currentBuild.description} on ${env.NODE_NAME}"
33
34 Tools.Clean()
35
36 Tools.Checkout()
37
38 build()
39
40 test()
41
42 benchmark()
43
44 build_doc()
45
46 publish()
47 }
48 }
49}
50
51//If an exception is caught we need to change the status and remember to
52//attach the build log to the email
53catch (Exception caughtError) {
54 // Store the result of the build log
55 currentBuild.result = "FAILURE"
56
57 // An error has occured, the build log is relevent
58 log_needed = true
59
60 // rethrow error later
61 err = caughtError
62
63 // print the error so it shows in the log
64 echo err.toString()
65}
66
67finally {
68 //Send email with final results if this is not a full build
69 email(log_needed)
70
71 echo 'Build Completed'
72
73 /* Must re-throw exception to propagate error */
74 if (err) {
75 throw err
76 }
77}
78//===========================================================================================================
79// Main compilation routines
80//===========================================================================================================
81def build() {
82 debug = true
83 release = Settings.RunAllTests || Settings.RunBenchmark
84 Tools.BuildStage('Build : configure', true) {
85 // Configure must be run inside the tree
86 dir (SrcDir) {
87 // Generate the necessary build files
88 sh './autogen.sh'
89 }
90
91 // Build outside of the src tree to ease cleaning
92 dir (BuildDir) {
93 //Configure the compilation (Output is not relevant)
94 //Use the current directory as the installation target so nothing escapes the sandbox
95 //Also specify the compiler by hand
96 targets=""
97 if( Settings.RunAllTests || Settings.RunBenchmark ) {
98 targets="--with-target-hosts='host:debug,host:nodebug'"
99 } else {
100 targets="--with-target-hosts='host:debug'"
101 }
102
103 ast = Settings.NewAST ? "--enable-new-ast" : "--disable-new-ast"
104
105 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}"
106
107 // Configure libcfa
108 sh 'make -j 8 --no-print-directory configure-libcfa'
109 }
110 }
111
112 Tools.BuildStage('Build : cfa-cpp', true) {
113 // Build outside of the src tree to ease cleaning
114 dir (BuildDir) {
115 // Build driver
116 sh 'make -j 8 --no-print-directory -C driver'
117
118 // Build translator
119 sh 'make -j 8 --no-print-directory -C src'
120 }
121 }
122
123 Tools.BuildStage('Build : libcfa(debug)', debug) {
124 // Build outside of the src tree to ease cleaning
125 dir (BuildDir) {
126 sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
127 }
128 }
129
130 Tools.BuildStage('Build : libcfa(nodebug)', release) {
131 // Build outside of the src tree to ease cleaning
132 dir (BuildDir) {
133 sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
134 }
135 }
136
137 Tools.BuildStage('Build : install', true) {
138 // Build outside of the src tree to ease cleaning
139 dir (BuildDir) {
140 sh "make -j 8 --no-print-directory install"
141 }
142 }
143}
144
145def test() {
146 try {
147 // Print potential limits before testing
148 // in case jenkins messes with them
149 sh 'free -h'
150 sh 'ulimit -a'
151
152 Tools.BuildStage('Test: short', !Settings.RunAllTests) {
153 dir (BuildDir) {
154 //Run the tests from the tests directory
155 sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
156 }
157 }
158
159 Tools.BuildStage('Test: full', Settings.RunAllTests) {
160 dir (BuildDir) {
161 //Run the tests from the tests directory
162 sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
163 sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
164 }
165 }
166 }
167 catch (Exception err) {
168 echo "Archiving core dumps"
169 dir (BuildDir) {
170 def exists = fileExists 'tests/crashes'
171 if( exists ) {
172 sh """${SrcDir}/tools/jenkins/archive-gen.sh"""
173 archiveArtifacts artifacts: "tests/crashes/**/*,lib/**/lib*.so*,setup.sh", fingerprint: true
174 }
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.