source: Jenkinsfile @ e70e54e

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since e70e54e was e70e54e, checked in by Thierry Delisle <tdelisle@…>, 2 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.