source: Jenkinsfile@ 74b0de43

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

Tentative to lint FullBuild on fast compile

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