source: Jenkinsfile@ 1690778

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

Removed utf-8 character in groovy files and replaced with unicode escape

  • Property mode set to 100644
File size: 12.8 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 StageName = ''
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 clean()
33
34 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 //rethrow error later
57 err = caughtError
58
59 echo err.toString()
60
61 //An error has occured, the build log is relevent
62 log_needed = true
63
64 //Store the result of the build log
65 currentBuild.result = "${StageName} FAILURE".trim()
66 }
67
68 finally {
69 //Send email with final results if this is not a full build
70 email(log_needed)
71
72 echo 'Build Completed'
73
74 /* Must re-throw exception to propagate error */
75 if (err) {
76 throw err
77 }
78 }
79}
80//===========================================================================================================
81// Main compilation routines
82//===========================================================================================================
83def clean() {
84 build_stage('Cleanup') {
85 // clean the build by wipping the build directory
86 dir(BuildDir) {
87 deleteDir()
88 }
89 }
90}
91
92//Compilation script is done here but environnement set-up and error handling is done in main loop
93def checkout() {
94 build_stage('Checkout') {
95 //checkout the source code and clean the repo
96 final scmVars = checkout scm
97 Settings.GitNewRef = scmVars.GIT_COMMIT
98 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
99
100 echo GitLogMessage()
101 }
102}
103
104def build() {
105 build_stage('Build') {
106 // Build outside of the src tree to ease cleaning
107 dir (BuildDir) {
108 //Configure the conpilation (Output is not relevant)
109 //Use the current directory as the installation target so nothing escapes the sandbox
110 //Also specify the compiler by hand
111 targets=""
112 if( Settings.RunAllTests || Settings.RunBenchmark ) {
113 targets="--with-target-hosts='host:debug,host:nodebug'"
114 } else {
115 targets="--with-target-hosts='host:debug'"
116 }
117
118 sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
119
120 //Compile the project
121 sh 'make -j 8 --no-print-directory'
122 }
123 }
124}
125
126def test() {
127 build_stage('Test') {
128
129 dir (BuildDir) {
130 //Run the tests from the tests directory
131 if ( Settings.RunAllTests ) {
132 sh 'make --no-print-directory -C tests timeouts="--timeout=600" all-tests debug=yes'
133 sh 'make --no-print-directory -C tests timeouts="--timeout=600" all-tests debug=no '
134 }
135 else {
136 sh 'make --no-print-directory -C tests'
137 }
138 }
139 }
140}
141
142def benchmark() {
143 build_stage('Benchmark') {
144
145 if( !Settings.RunBenchmark ) return
146
147 dir (BuildDir) {
148 //Append bench results
149 sh "make --no-print-directory -C benchmark jenkins"
150 }
151 }
152}
153
154def build_doc() {
155 build_stage('Documentation') {
156
157 if( !Settings.BuildDocumentation ) return
158
159 dir ('doc/user') {
160 make_doc()
161 }
162
163 dir ('doc/refrat') {
164 make_doc()
165 }
166 }
167}
168
169def publish() {
170 build_stage('Publish') {
171
172 if( !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
173
174 def groupCompile = new PlotGroup('Compilation', 'seconds', true)
175 def groupConcurrency = new PlotGroup('Concurrency', 'nanoseconds', false)
176
177 //Then publish the results
178 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , 'Compilation')
179 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch', groupConcurrency, 'Context Switching')
180 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, 'Mutual Exclusion')
181 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal' , groupConcurrency, 'Internal and External Scheduling')
182 }
183}
184
185//===========================================================================================================
186//Routine responsible of sending the email notification once the build is completed
187//===========================================================================================================
188def GitLogMessage() {
189 if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
190
191 sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
192
193 def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
194 def gitLog = readFile("${BuildDir}/GIT_LOG")
195 def gitDiff = readFile("${BuildDir}/GIT_DIFF")
196
197 return """
198<pre>
199The branch ${env.BRANCH_NAME} has been updated.
200${gitUpdate}
201</pre>
202
203<p>Check console output at ${env.BUILD_URL} to view the results.</p>
204
205<p>- Status --------------------------------------------------------------</p>
206
207<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
208
209<p>- Log -----------------------------------------------------------------</p>
210
211<pre>
212${gitLog}
213</pre>
214
215<p>-----------------------------------------------------------------------</p>
216<pre>
217Summary of changes:
218${gitDiff}
219</pre>
220"""
221}
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""" + 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
257 CC_Desc(String name, String CXX, String CC) {
258 this.name = name
259 this.CXX = CXX
260 this.CC = CC
261 }
262}
263
264//Description of an architecture (Must be serializable since pipelines are persistent)
265class Arch_Desc implements Serializable {
266 public String name
267 public String flags
268 public String node
269
270 Arch_Desc(String name, String flags, String node) {
271 this.name = name
272 this.flags = flags
273 this.node = node
274 }
275}
276
277class BuildSettings implements Serializable {
278 public final CC_Desc Compiler
279 public final Arch_Desc Architecture
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-6':
295 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
296 break
297 case 'gcc-5':
298 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
299 break
300 case 'gcc-4.9':
301 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
302 break
303 case 'clang':
304 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
305 break
306 default :
307 error "Unhandled compiler : ${cc}"
308 }
309
310 switch( param.Architecture ) {
311 case 'x64':
312 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
313 break
314 case 'x86':
315 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
316 break
317 default :
318 error "Unhandled architecture : ${arch}"
319 }
320
321 this.IsSandbox = (branch == "jenkins-sandbox")
322 this.RunAllTests = param.RunAllTests
323 this.RunBenchmark = param.RunBenchmark
324 this.BuildDocumentation = param.BuildDocumentation
325 this.Publish = param.Publish
326 this.Silent = param.Silent
327
328 def full = param.RunAllTests ? " (Full)" : ""
329 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
330
331 this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
332Architecture : ${ this.Architecture.name }
333Arc Flags : ${ this.Architecture.flags }
334Run All Tests : ${ this.RunAllTests.toString() }
335Run Benchmark : ${ this.RunBenchmark.toString() }
336Build Documentation : ${ this.BuildDocumentation.toString() }
337Publish : ${ this.Publish.toString() }
338Silent : ${ this.Silent.toString() }
339"""
340
341 this.GitNewRef = ''
342 this.GitOldRef = ''
343 }
344}
345
346class PlotGroup implements Serializable {
347 public String name
348 public String unit
349 public boolean log
350
351 PlotGroup(String name, String unit, boolean log) {
352 this.name = name
353 this.unit = unit
354 this.log = log
355 }
356}
357
358def prepare_build() {
359 // prepare the properties
360 properties ([ \
361 [$class: 'ParametersDefinitionProperty', \
362 parameterDefinitions: [ \
363 [$class: 'ChoiceParameterDefinition', \
364 description: 'Which compiler to use', \
365 name: 'Compiler', \
366 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
367 defaultValue: 'gcc-6', \
368 ], \
369 [$class: 'ChoiceParameterDefinition', \
370 description: 'The target architecture', \
371 name: 'Architecture', \
372 choices: 'x64\nx86', \
373 defaultValue: 'x64', \
374 ], \
375 [$class: 'BooleanParameterDefinition', \
376 description: 'If false, only the quick test suite is ran', \
377 name: 'RunAllTests', \
378 defaultValue: false, \
379 ], \
380 [$class: 'BooleanParameterDefinition', \
381 description: 'If true, jenkins also runs benchmarks', \
382 name: 'RunBenchmark', \
383 defaultValue: false, \
384 ], \
385 [$class: 'BooleanParameterDefinition', \
386 description: 'If true, jenkins also builds documentation', \
387 name: 'BuildDocumentation', \
388 defaultValue: true, \
389 ], \
390 [$class: 'BooleanParameterDefinition', \
391 description: 'If true, jenkins also publishes results', \
392 name: 'Publish', \
393 defaultValue: false, \
394 ], \
395 [$class: 'BooleanParameterDefinition', \
396 description: 'If true, jenkins will not send emails', \
397 name: 'Silent', \
398 defaultValue: false, \
399 ], \
400 ],
401 ]])
402
403 // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
404 checkout scm
405
406 final settings = new BuildSettings(params, env.BRANCH_NAME)
407
408 currentBuild.description = settings.DescShort
409 echo settings.DescLong
410
411 return settings
412}
413
414def build_stage(String name, Closure block ) {
415 StageName = name
416 echo " -------- ${StageName} -------- "
417 stage(name, block)
418}
419
420def make_doc() {
421 def err = null
422 try {
423 sh 'make clean > /dev/null'
424 sh 'make > /dev/null 2>&1'
425 }
426 catch (Exception caughtError) {
427 err = caughtError //rethrow error later
428 sh 'cat build/*.log'
429 }
430 finally {
431 if (err) throw err // Must re-throw exception to propagate error
432 }
433}
434
435def do_plot(boolean silent, String file, PlotGroup group, String title) {
436
437 def series = silent ? [] : [[
438 file: "${file}.csv",
439 exclusionValues: '',
440 displayTableFlag: false,
441 inclusionFlag: 'OFF',
442 url: ''
443 ]];
444
445 echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
446 dir("${BuildDir}/benchmark/") {
447 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
448 csvSeries: series,
449 group: "${group.name}",
450 title: "${title}",
451 style: 'lineSimple',
452 exclZero: false,
453 keepRecords: false,
454 logarithmic: group.log,
455 numBuilds: '120',
456 useDescr: true,
457 yaxis: group.unit,
458 yaxisMaximum: '',
459 yaxisMinimum: ''
460 }
461}
Note: See TracBrowser for help on using the repository browser.