source: Jenkinsfile@ 6f096d2

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

Added configure-libcfa target to help jenkins build in steps

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