source: Jenkinsfile@ 5a076837

ADT ast-experimental pthread-emulation qualifiedEnum
Last change on this file since 5a076837 was 14d5461, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Fixed incorrect used of $ in jenkins file

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