source: Jenkinsfile @ 7a230fd

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 7a230fd was 7a230fd, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Tentative fix for global variable usage

  • Property mode set to 100644
File size: 12.6 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
169@Field PlotGroup CompileGroup = new PlotGroup('Compilation', 'seconds', true)
170@Field PlotGroup ConcurrencyGroup = new PlotGroup('Concurrency', 'nanoseconds', false)
171
172def publish() {
173        build_stage('Publish') {
174
175                if( !Settings.Publish ) return
176                if( !Settings.RunBenchmark ) {
177                        echo 'No results to publish!!!'
178                        return
179                }
180
181                //Then publish the results
182                do_plot('compile', CompilationGroup, 'Compilation')
183
184                do_plot('ctxswitch', ConcurrencyGroup, 'Context Switching')
185
186                do_plot('mutex', ConcurrencyGroup, 'Mutual Exclusion')
187
188                do_plot('signal', ConcurrencyGroup, 'Internal and External Scheduling')
189        }
190}
191
192//===========================================================================================================
193//Routine responsible of sending the email notification once the build is completed
194//===========================================================================================================
195def GitLogMessage() {
196        if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
197
198        sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
199
200        def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
201        def gitLog    = readFile("${BuildDir}/GIT_LOG")
202        def gitDiff   = readFile("${BuildDir}/GIT_DIFF")
203
204        return """
205<pre>
206The branch ${env.BRANCH_NAME} has been updated.
207${gitUpdate}
208</pre>
209
210<p>Check console output at ${env.BUILD_URL} to view the results.</p>
211
212<p>- Status --------------------------------------------------------------</p>
213
214<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
215
216<p>- Log -----------------------------------------------------------------</p>
217
218<pre>
219${gitLog}
220</pre>
221
222<p>-----------------------------------------------------------------------</p>
223<pre>
224Summary of changes:
225${gitDiff}
226</pre>
227"""
228}
229
230//Standard build email notification
231def email(boolean log) {
232        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
233        //Configurations for email format
234        echo 'Notifying users of result'
235
236        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
237        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
238        def email_body = """<p>This is an automated email from the Jenkins build machine. It was
239generated because of a git hooks/post-receive script following
240a ref change which was pushed to the C repository.</p>
241""" + GitLogMessage()
242
243        def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
244
245        if( Settings && !Settings.Silent ) {
246                //send email notification
247                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
248        } else {
249                echo "Would send email to: ${email_to}"
250                echo "With title: ${email_subject}"
251                echo "Content: \n${email_body}"
252        }
253}
254
255//===========================================================================================================
256// Helper classes/variables/routines
257//===========================================================================================================
258//Description of a compiler (Must be serializable since pipelines are persistent)
259class CC_Desc implements Serializable {
260        public String name
261        public String CXX
262        public String CC
263
264        CC_Desc(String name, String CXX, String CC) {
265                this.name = name
266                this.CXX = CXX
267                this.CC = CC
268        }
269}
270
271//Description of an architecture (Must be serializable since pipelines are persistent)
272class Arch_Desc implements Serializable {
273        public String name
274        public String flags
275        public String node
276
277        Arch_Desc(String name, String flags, String node) {
278                this.name  = name
279                this.flags = flags
280                this.node  = node
281        }
282}
283
284class BuildSettings implements Serializable {
285        public final CC_Desc Compiler
286        public final Arch_Desc Architecture
287        public final Boolean RunAllTests
288        public final Boolean RunBenchmark
289        public final Boolean BuildDocumentation
290        public final Boolean Publish
291        public final Boolean Silent
292        public final Boolean IsSandbox
293        public final String DescLong
294        public final String DescShort
295
296        public String GitNewRef
297        public String GitOldRef
298
299        BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
300                switch( param.Compiler ) {
301                        case 'gcc-6':
302                                this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
303                        break
304                        case 'gcc-5':
305                                this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
306                        break
307                        case 'gcc-4.9':
308                                this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
309                        break
310                        case 'clang':
311                                this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
312                        break
313                        default :
314                                error "Unhandled compiler : ${cc}"
315                }
316
317                switch( param.Architecture ) {
318                        case 'x64':
319                                this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
320                        break
321                        case 'x86':
322                                this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
323                        break
324                        default :
325                                error "Unhandled architecture : ${arch}"
326                }
327
328                this.IsSandbox          = (branch == "jenkins-sandbox")
329                this.RunAllTests        = param.RunAllTests
330                this.RunBenchmark       = param.RunBenchmark
331                this.BuildDocumentation = param.BuildDocumentation
332                this.Publish            = param.Publish
333                this.Silent             = param.Silent
334
335                def full = param.RunAllTests ? " (Full)" : ""
336                this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
337
338                this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
339Architecture            : ${ this.Architecture.name }
340Arc Flags               : ${ this.Architecture.flags }
341Run All Tests           : ${ this.RunAllTests.toString() }
342Run Benchmark           : ${ this.RunBenchmark.toString() }
343Build Documentation     : ${ this.BuildDocumentation.toString() }
344Publish                 : ${ this.Publish.toString() }
345Silent                  : ${ this.Silent.toString() }
346"""
347
348                this.GitNewRef = ''
349                this.GitOldRef = ''
350        }
351}
352
353class PlotGroup implements Serializable {
354        public String name
355        public String unit
356        public boolean log
357
358        PlotGroup(String name, String unit, boolean log) {
359                this.name = name
360                this.unit = unit
361                this.log = log
362        }
363}
364
365def prepare_build() {
366        // prepare the properties
367        properties ([                                                                                                   \
368                [$class: 'ParametersDefinitionProperty',                                                                \
369                        parameterDefinitions: [                                                                         \
370                                [$class: 'ChoiceParameterDefinition',                                           \
371                                        description: 'Which compiler to use',                                   \
372                                        name: 'Compiler',                                                                       \
373                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
374                                        defaultValue: 'gcc-6',                                                          \
375                                ],                                                                                              \
376                                [$class: 'ChoiceParameterDefinition',                                           \
377                                        description: 'The target architecture',                                 \
378                                        name: 'Architecture',                                                           \
379                                        choices: 'x64\nx86',                                                            \
380                                        defaultValue: 'x64',                                                            \
381                                ],                                                                                              \
382                                [$class: 'BooleanParameterDefinition',                                                  \
383                                        description: 'If false, only the quick test suite is ran',              \
384                                        name: 'RunAllTests',                                                            \
385                                        defaultValue: false,                                                            \
386                                ],                                                                                              \
387                                [$class: 'BooleanParameterDefinition',                                                  \
388                                        description: 'If true, jenkins also runs benchmarks',           \
389                                        name: 'RunBenchmark',                                                           \
390                                        defaultValue: false,                                                            \
391                                ],                                                                                              \
392                                [$class: 'BooleanParameterDefinition',                                                  \
393                                        description: 'If true, jenkins also builds documentation',              \
394                                        name: 'BuildDocumentation',                                                     \
395                                        defaultValue: true,                                                             \
396                                ],                                                                                              \
397                                [$class: 'BooleanParameterDefinition',                                                  \
398                                        description: 'If true, jenkins also publishes results',                 \
399                                        name: 'Publish',                                                                        \
400                                        defaultValue: false,                                                            \
401                                ],                                                                                              \
402                                [$class: 'BooleanParameterDefinition',                                                  \
403                                        description: 'If true, jenkins will not send emails',           \
404                                        name: 'Silent',                                                                         \
405                                        defaultValue: false,                                                            \
406                                ],                                                                                              \
407                        ],
408                ]])
409
410        // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
411        checkout scm
412
413        final settings = new BuildSettings(params, env.BRANCH_NAME)
414
415        currentBuild.description = settings.DescShort
416        echo                       settings.DescLong
417
418        return settings
419}
420
421def build_stage(String name, Closure block ) {
422        StageName = name
423        echo " -------- ${StageName} -------- "
424        stage(name, block)
425}
426
427def make_doc() {
428        def err = null
429        try {
430                sh 'make clean > /dev/null'
431                sh 'make > /dev/null 2>&1'
432        }
433        catch (Exception caughtError) {
434                err = caughtError //rethrow error later
435                sh 'cat build/*.log'
436        }
437        finally {
438                if (err) throw err // Must re-throw exception to propagate error
439        }
440}
441
442def do_plot(String file, PlotGroup group, String title) {
443        echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
444        dir("${BuildDir}/benchmark/") {
445                plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
446                        csvSeries: [[
447                                file: "${file}.csv",
448                                exclusionValues: '',
449                                displayTableFlag: false,
450                                inclusionFlag: 'OFF',
451                                url: ''
452                        ]],
453                        group: "${group.name}",
454                        title: "${title}",
455                        style: 'lineSimple',
456                        exclZero: false,
457                        keepRecords: false,
458                        logarithmic: group.log,
459                        numBuilds: '120',
460                        useDescr: true,
461                        yaxis: group.unit,
462                        yaxisMaximum: '',
463                        yaxisMinimum: ''
464        }
465}
Note: See TracBrowser for help on using the repository browser.