source: Jenkinsfile@ 47bfefd

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 47bfefd was 47bfefd, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Removed extra curly brace

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