source: Jenkinsfile @ 7bd23ce

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 7bd23ce was 7684557, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Build description now cotains node name

  • Property mode set to 100644
File size: 15.1 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        Tools     = null
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                                currentBuild.description = "${currentBuild.description} on ${env.NODE_NAME}"
32
33                                Tools.Clean()
34
35                                Tools.Checkout()
36
37                                build()
38
39                                test()
40
41                                benchmark()
42
43                                build_doc()
44
45                                publish()
46                        }
47
48                        // Update the build directories when exiting the node
49                        BuildDir  = pwd tmp: true
50                        SrcDir    = pwd tmp: false
51                }
52        }
53
54        //If an exception is caught we need to change the status and remember to
55        //attach the build log to the email
56        catch (Exception caughtError) {
57                // Store the result of the build log
58                currentBuild.result = "FAILURE"
59
60                // An error has occured, the build log is relevent
61                log_needed = true
62
63                // rethrow error later
64                err = caughtError
65
66                // print the error so it shows in the log
67                echo err.toString()
68        }
69
70        finally {
71                //Send email with final results if this is not a full build
72                email(log_needed)
73
74                echo 'Build Completed'
75
76                /* Must re-throw exception to propagate error */
77                if (err) {
78                        throw err
79                }
80        }
81}
82//===========================================================================================================
83// Main compilation routines
84//===========================================================================================================
85def build() {
86        debug = true
87        release = Settings.RunAllTests || Settings.RunBenchmark
88        Tools.BuildStage('Build : configure', true) {
89                // Configure must be run inside the tree
90                dir (SrcDir) {
91                        // Generate the necessary build files
92                        sh './autogen.sh'
93                }
94
95                // Build outside of the src tree to ease cleaning
96                dir (BuildDir) {
97                        //Configure the compilation (Output is not relevant)
98                        //Use the current directory as the installation target so nothing escapes the sandbox
99                        //Also specify the compiler by hand
100                        targets=""
101                        if( Settings.RunAllTests || Settings.RunBenchmark ) {
102                                targets="--with-target-hosts='host:debug,host:nodebug'"
103                        } else {
104                                targets="--with-target-hosts='host:debug'"
105                        }
106
107                        ast = Settings.NewAST ? "--enable-new-ast" : "--disable-new-ast"
108
109                        sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib ${targets} ${ast} --quiet --prefix=${BuildDir}"
110
111                        // Configure libcfa
112                        sh 'make -j 8 --no-print-directory configure-libcfa'
113                }
114        }
115
116        Tools.BuildStage('Build : cfa-cpp', true) {
117                // Build outside of the src tree to ease cleaning
118                dir (BuildDir) {
119                        // Build driver
120                        sh 'make -j 8 --no-print-directory -C driver'
121
122                        // Build translator
123                        sh 'make -j 8 --no-print-directory -C src'
124                }
125        }
126
127        Tools.BuildStage('Build : libcfa(debug)', debug) {
128                // Build outside of the src tree to ease cleaning
129                dir (BuildDir) {
130                        sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
131                }
132        }
133
134        Tools.BuildStage('Build : libcfa(nodebug)', release) {
135                // Build outside of the src tree to ease cleaning
136                dir (BuildDir) {
137                        sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
138                }
139        }
140
141        Tools.BuildStage('Build : install', true) {
142                // Build outside of the src tree to ease cleaning
143                dir (BuildDir) {
144                        sh "make -j 8 --no-print-directory install"
145                }
146        }
147}
148
149def test() {
150        try {
151                // Print potential limits before testing
152                // in case jenkins messes with them
153                sh 'free -h'
154                sh 'ulimit -a'
155
156                Tools.BuildStage('Test: short', !Settings.RunAllTests) {
157                        dir (BuildDir) {
158                                //Run the tests from the tests directory
159                                sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
160                        }
161                }
162
163                Tools.BuildStage('Test: full', Settings.RunAllTests) {
164                        dir (BuildDir) {
165                                        //Run the tests from the tests directory
166                                        sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
167                                        sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
168                        }
169                }
170        }
171        catch (Exception err) {
172                echo "Archiving core dumps"
173                dir (BuildDir) {
174                        sh """${SrcDir}/tools/jenkins/archive-gen.sh"""
175                        archiveArtifacts artifacts: "tests/crashes/**/*,lib/**/lib*.so*,setup.sh", fingerprint: true
176                }
177                throw err
178        }
179}
180
181def benchmark() {
182        Tools.BuildStage('Benchmark', Settings.RunBenchmark) {
183                dir (BuildDir) {
184                        //Append bench results
185                        sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
186                }
187        }
188}
189
190def build_doc() {
191        Tools.BuildStage('Documentation', Settings.BuildDocumentation) {
192                dir ('doc/user') {
193                        make_doc()
194                }
195
196                dir ('doc/refrat') {
197                        make_doc()
198                }
199        }
200}
201
202def publish() {
203        Tools.BuildStage('Publish', true) {
204
205                if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
206
207                def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
208                def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
209
210                //Then publish the results
211                do_plot(Settings.RunBenchmark && Settings.Publish, 'compile'        , groupCompile    , false, 'Compilation')
212                do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff'   , groupCompile    , true , 'Compilation (relative)')
213                do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch'      , groupConcurrency, false, 'Context Switching')
214                do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff' , groupConcurrency, true , 'Context Switching (relative)')
215                do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex'          , groupConcurrency, false, 'Mutual Exclusion')
216                do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff'     , groupConcurrency, true , 'Mutual Exclusion (relative)')
217                do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling'     , groupConcurrency, false, 'Internal and External Scheduling')
218                do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling.diff', groupConcurrency, true , 'Internal and External Scheduling (relative)')
219        }
220}
221
222//===========================================================================================================
223//Routine responsible of sending the email notification once the build is completed
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\u2200 repository.</p>
236""" + Tools.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        public String lto
259
260        CC_Desc(String name, String CXX, String CC, String lto) {
261                this.name = name
262                this.CXX = CXX
263                this.CC  = CC
264                this.lto = lto
265        }
266}
267
268//Description of an architecture (Must be serializable since pipelines are persistent)
269class Arch_Desc implements Serializable {
270        public String name
271        public String flags
272        public String node
273
274        Arch_Desc(String name, String flags, String node) {
275                this.name  = name
276                this.flags = flags
277                this.node  = node
278        }
279}
280
281class BuildSettings implements Serializable {
282        public final CC_Desc Compiler
283        public final Arch_Desc Architecture
284        public final Boolean NewAST
285        public final Boolean RunAllTests
286        public final Boolean RunBenchmark
287        public final Boolean BuildDocumentation
288        public final Boolean Publish
289        public final Boolean Silent
290        public final Boolean IsSandbox
291        public final String DescLong
292        public final String DescShort
293
294        public String GitNewRef
295        public String GitOldRef
296
297        BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
298                switch( param.Compiler ) {
299                        case 'gcc-9':
300                                this.Compiler = new CC_Desc('gcc-9', 'g++-9', 'gcc-9', '-flto=auto')
301                        break
302                        case 'gcc-8':
303                                this.Compiler = new CC_Desc('gcc-8', 'g++-8', 'gcc-8', '-flto=auto')
304                        break
305                        case 'gcc-7':
306                                this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7', '-flto=auto')
307                        break
308                        case 'gcc-6':
309                                this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')
310                        break
311                        case 'gcc-5':
312                                this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')
313                        break
314                        case 'gcc-4.9':
315                                this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')
316                        break
317                        case 'clang':
318                                this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-9', '-flto=thin -flto-jobs=0')
319                        break
320                        default :
321                                error "Unhandled compiler : ${cc}"
322                }
323
324                switch( param.Architecture ) {
325                        case 'x64':
326                                this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
327                        break
328                        case 'x86':
329                                this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
330                        break
331                        default :
332                                error "Unhandled architecture : ${arch}"
333                }
334
335                this.IsSandbox          = (branch == "jenkins-sandbox")
336                this.NewAST             = param.NewAST
337                this.RunAllTests        = param.RunAllTests
338                this.RunBenchmark       = param.RunBenchmark
339                this.BuildDocumentation = param.BuildDocumentation
340                this.Publish            = param.Publish
341                this.Silent             = param.Silent
342
343                def full = param.RunAllTests ? " (Full)" : ""
344                this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
345
346                final ast = this.NewAST ? "New AST" : "Old AST"
347                this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
348AST Version             : ${ ast.toString() }
349Architecture            : ${ this.Architecture.name }
350Arc Flags               : ${ this.Architecture.flags }
351Run All Tests           : ${ this.RunAllTests.toString() }
352Run Benchmark           : ${ this.RunBenchmark.toString() }
353Build Documentation     : ${ this.BuildDocumentation.toString() }
354Publish                 : ${ this.Publish.toString() }
355Silent                  : ${ this.Silent.toString() }
356"""
357
358                this.GitNewRef = ''
359                this.GitOldRef = ''
360        }
361}
362
363class PlotGroup implements Serializable {
364        public String name
365        public String unit
366        public boolean log
367
368        PlotGroup(String name, String unit, boolean log) {
369                this.name = name
370                this.unit = unit
371                this.log = log
372        }
373}
374
375def prepare_build() {
376        // prepare the properties
377        properties ([                                                                                                   \
378                buildDiscarder(logRotator(                                                                              \
379                        artifactDaysToKeepStr: '',                                                                      \
380                        artifactNumToKeepStr: '',                                                                       \
381                        daysToKeepStr: '730',                                                                           \
382                        numToKeepStr: '1000'                                                                            \
383                )),                                                                                                             \
384                [$class: 'ParametersDefinitionProperty',                                                                \
385                        parameterDefinitions: [                                                                         \
386                                [$class: 'ChoiceParameterDefinition',                                           \
387                                        description: 'Which compiler to use',                                   \
388                                        name: 'Compiler',                                                                       \
389                                        choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang',   \
390                                        defaultValue: 'gcc-8',                                                          \
391                                ],                                                                                              \
392                                [$class: 'ChoiceParameterDefinition',                                           \
393                                        description: 'The target architecture',                                 \
394                                        name: 'Architecture',                                                           \
395                                        choices: 'x64\nx86',                                                            \
396                                        defaultValue: 'x64',                                                            \
397                                ],                                                                                              \
398                                [$class: 'BooleanParameterDefinition',                                                  \
399                                        description: 'If true, build compiler using new AST',           \
400                                        name: 'NewAST',                                                                         \
401                                        defaultValue: true,                                                             \
402                                ],                                                                                              \
403                                [$class: 'BooleanParameterDefinition',                                                  \
404                                        description: 'If false, only the quick test suite is ran',              \
405                                        name: 'RunAllTests',                                                            \
406                                        defaultValue: false,                                                            \
407                                ],                                                                                              \
408                                [$class: 'BooleanParameterDefinition',                                                  \
409                                        description: 'If true, jenkins also runs benchmarks',           \
410                                        name: 'RunBenchmark',                                                           \
411                                        defaultValue: false,                                                            \
412                                ],                                                                                              \
413                                [$class: 'BooleanParameterDefinition',                                                  \
414                                        description: 'If true, jenkins also builds documentation',              \
415                                        name: 'BuildDocumentation',                                                     \
416                                        defaultValue: true,                                                             \
417                                ],                                                                                              \
418                                [$class: 'BooleanParameterDefinition',                                                  \
419                                        description: 'If true, jenkins also publishes results',                 \
420                                        name: 'Publish',                                                                        \
421                                        defaultValue: false,                                                            \
422                                ],                                                                                              \
423                                [$class: 'BooleanParameterDefinition',                                                  \
424                                        description: 'If true, jenkins will not send emails',           \
425                                        name: 'Silent',                                                                         \
426                                        defaultValue: false,                                                            \
427                                ],                                                                                              \
428                        ],
429                ]])
430
431        // It's unfortunate but it looks like we need to checkout the entire repo just to get
432        // - the pretty git printer
433        // - Jenkins.tools
434        checkout scm
435
436        Tools = load "Jenkins/tools.groovy"
437
438        final settings = new BuildSettings(params, env.BRANCH_NAME)
439
440        currentBuild.description = settings.DescShort
441        echo                       settings.DescLong
442
443        return settings
444}
445
446def make_doc() {
447        def err = null
448        try {
449                sh 'make clean > /dev/null'
450                sh 'make > /dev/null 2>&1'
451        }
452        catch (Exception caughtError) {
453                err = caughtError //rethrow error later
454                sh 'cat build/*.log'
455        }
456        finally {
457                if (err) throw err // Must re-throw exception to propagate error
458        }
459}
460
461def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
462
463        if(new_data) {
464                echo "Publishing new data"
465        }
466
467        def series = new_data ? [[
468                                file: "${file}.csv",
469                                exclusionValues: '',
470                                displayTableFlag: false,
471                                inclusionFlag: 'OFF',
472                                url: ''
473                        ]] : [];
474
475        echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
476        dir("${BuildDir}/benchmark/") {
477                plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
478                        csvSeries: series,
479                        group: "${group.name}",
480                        title: "${title}",
481                        style: 'lineSimple',
482                        exclZero: false,
483                        keepRecords: false,
484                        logarithmic: !relative && group.log,
485                        numBuilds: '120',
486                        useDescr: true,
487                        yaxis: group.unit,
488                        yaxisMaximum: '',
489                        yaxisMinimum: ''
490        }
491}
Note: See TracBrowser for help on using the repository browser.