source: Jenkinsfile @ a254fa56

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

fixed scheduling benchmarks in jenkins to use consistent file naming

  • Property mode set to 100644
File size: 16.3 KB
RevLine 
[a63ad80]1#!groovy
2
[7a230fd]3import groovy.transform.Field
4
[8ecb590]5// For skipping stages
6import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
7
[29f4fe62]8//===========================================================================================================
[9beae23]9// Main loop of the compilation
[29f4fe62]10//===========================================================================================================
[56a9ce6]11
[85142648]12node('master') {
13        // Globals
14        BuildDir  = pwd tmp: true
15        SrcDir    = pwd tmp: false
16        Settings  = null
17        StageName = ''
[4f9e706]18
[85142648]19        // Local variables
20        def err = null
21        def log_needed = false
[5b8413b4]22
[85142648]23        currentBuild.result = "SUCCESS"
[4f9e706]24
[85142648]25        try {
26                //Wrap build to add timestamp to command line
27                wrap([$class: 'TimestamperBuildWrapper']) {
[0ef06b6]28
[85142648]29                        Settings = prepare_build()
[952ee7a]30
[85142648]31                        node(Settings.Architecture.node) {
32                                BuildDir  = pwd tmp: true
33                                SrcDir    = pwd tmp: false
[23a14d86]34
[85142648]35                                clean()
[7aebc62]36
[85142648]37                                checkout()
[fde808df]38
[85142648]39                                build()
[95fdb0a]40
[85142648]41                                test()
[95fdb0a]42
[85142648]43                                benchmark()
[95fdb0a]44
[85142648]45                                build_doc()
[7359098]46
[85142648]47                                publish()
48                        }
[9beae23]49
[85142648]50                        // Update the build directories when exiting the node
51                        BuildDir  = pwd tmp: true
52                        SrcDir    = pwd tmp: false
[9beae23]53                }
[738cf8f]54        }
55
[85142648]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
[738cf8f]61
[85142648]62                echo err.toString()
[e966ec0]63
[85142648]64                //An error has occured, the build log is relevent
65                log_needed = true
[9beae23]66
[85142648]67                //Store the result of the build log
68                currentBuild.result = "${StageName} FAILURE".trim()
69        }
[738cf8f]70
[85142648]71        finally {
72                //Send email with final results if this is not a full build
73                email(log_needed)
[9beae23]74
[85142648]75                echo 'Build Completed'
[734891d]76
[85142648]77                /* Must re-throw exception to propagate error */
78                if (err) {
79                        throw err
80                }
[738cf8f]81        }
82}
[29f4fe62]83//===========================================================================================================
[9beae23]84// Main compilation routines
[29f4fe62]85//===========================================================================================================
[0dc3ac3]86def clean() {
[6c55a3d]87        build_stage('Cleanup', true) {
[0dc3ac3]88                // clean the build by wipping the build directory
[5b8413b4]89                dir(BuildDir) {
[d4cd491]90                        deleteDir()
[ece8a80]91                }
[620dd2b]92        }
[95fdb0a]93}
[29f4fe62]94
[0dc3ac3]95//Compilation script is done here but environnement set-up and error handling is done in main loop
96def checkout() {
[6c55a3d]97        build_stage('Checkout', true) {
[0dc3ac3]98                //checkout the source code and clean the repo
[a336d46]99                final scmVars = checkout scm
100                Settings.GitNewRef = scmVars.GIT_COMMIT
101                Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
[d3a4564a]102
[a336d46]103                echo GitLogMessage()
[e11957e]104
105                // This is a complete hack but it solves problems with automake thinking it needs to regenerate makefiles
106                // We fudged automake/missing to handle that but automake stills bakes prints inside the makefiles
107                // and these cause more problems.
108                sh 'find . -name Makefile.in -exec touch {} +'
[0dc3ac3]109        }
110}
111
[95fdb0a]112def build() {
[e507c11]113        debug = true
114        release = Settings.RunAllTests || Settings.RunBenchmark
115        build_stage('Build : configure', true) {
[50f2cfc]116                // Build outside of the src tree to ease cleaning
[5b8413b4]117                dir (BuildDir) {
[50f2cfc]118                        //Configure the conpilation (Output is not relevant)
119                        //Use the current directory as the installation target so nothing escapes the sandbox
120                        //Also specify the compiler by hand
[3fc5f010]121                        targets=""
[d4510ea]122                        if( Settings.RunAllTests || Settings.RunBenchmark ) {
[6bde81d]123                                targets="--with-target-hosts='host:debug,host:nodebug'"
[3fc5f010]124                        } else {
[6bde81d]125                                targets="--with-target-hosts='host:debug'"
[3fc5f010]126                        }
127
[93fe3154]128                        sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
[f253e4a]129
130                        // Configure libcfa
[e70e54e]131                        sh 'make -j 8 --no-print-directory configure-libcfa'
[e507c11]132                }
133        }
134
135        build_stage('Build : cfa-cpp', true) {
136                // Build outside of the src tree to ease cleaning
137                dir (BuildDir) {
138                        // Build driver
139                        sh 'make -j 8 --no-print-directory -C driver'
140
141                        // Build translator
142                        sh 'make -j 8 --no-print-directory -C src'
143                }
144        }
[1752d0e]145
[e507c11]146        build_stage('Build : libcfa(debug)', debug) {
147                // Build outside of the src tree to ease cleaning
148                dir (BuildDir) {
149                        sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
150                }
151        }
152
153        build_stage('Build : libcfa(nodebug)', release) {
154                // Build outside of the src tree to ease cleaning
155                dir (BuildDir) {
156                        sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
[50f2cfc]157                }
[620dd2b]158        }
[95fdb0a]159}
[24eecab]160
[95fdb0a]161def test() {
[4c1b9ea8]162        try {
163                build_stage('Test: short', !Settings.RunAllTests) {
164                        dir (BuildDir) {
[3e93c00]165                                //Run the tests from the tests directory
[4c51aca]166                                sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
[3e93c00]167                        }
[4c1b9ea8]168                }
169
170                build_stage('Test: full', Settings.RunAllTests) {
171                        dir (BuildDir) {
172                                        //Run the tests from the tests directory
[4c51aca]173                                        sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
174                                        sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
[143e6f3]175                        }
[9beae23]176                }
[620dd2b]177        }
[4c1b9ea8]178        catch (Exception err) {
179                echo "Archiving core dumps"
[c95fdc9]180                dir (BuildDir) {
181                        archiveArtifacts artifacts: "tests/crashes/**/*", fingerprint: true
182                }
[4c1b9ea8]183                throw err
184        }
[95fdb0a]185}
186
187def benchmark() {
[6c55a3d]188        build_stage('Benchmark', Settings.RunBenchmark) {
[5b8413b4]189                dir (BuildDir) {
[0dc3ac3]190                        //Append bench results
[c6f1f3e]191                        sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
[0dc3ac3]192                }
[620dd2b]193        }
[9beae23]194}
[efd60d67]195
[95fdb0a]196def build_doc() {
[6c55a3d]197        build_stage('Documentation', Settings.BuildDocumentation) {
[9beae23]198                dir ('doc/user') {
199                        make_doc()
200                }
201
202                dir ('doc/refrat') {
203                        make_doc()
204                }
[620dd2b]205        }
[9beae23]206}
207
[95fdb0a]208def publish() {
[6c55a3d]209        build_stage('Publish', true) {
[95fdb0a]210
[1b3eef8]211                if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
[95fdb0a]212
[3221a2b]213                def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
214                def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
[a2a0065]215
[3898392]216                //Then publish the results
[13d2dac]217                do_plot(Settings.RunBenchmark && Settings.Publish, 'compile'        , groupCompile    , false, 'Compilation')
218                do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff'   , groupCompile    , true , 'Compilation (relative)')
219                do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch'      , groupConcurrency, false, 'Context Switching')
220                do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff' , groupConcurrency, true , 'Context Switching (relative)')
221                do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex'          , groupConcurrency, false, 'Mutual Exclusion')
222                do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff'     , groupConcurrency, true , 'Mutual Exclusion (relative)')
223                do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling'     , groupConcurrency, false, 'Internal and External Scheduling')
224                do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling.diff', groupConcurrency, true , 'Internal and External Scheduling (relative)')
[620dd2b]225        }
[95fdb0a]226}
227
[29f4fe62]228//===========================================================================================================
229//Routine responsible of sending the email notification once the build is completed
230//===========================================================================================================
[6b6c26e]231@NonCPS
232def SplitLines(String text) {
233        def list = []
234
235        text.eachLine {
236                list += it
237        }
238
239        return list
240}
241
[a336d46]242def GitLogMessage() {
243        if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
[e8a22a7]244
[fce01e7]245        def oldRef = Settings.GitOldRef
246        def newRef = Settings.GitNewRef
[6badd87]247
[fdb6ac6]248        def revText = sh(returnStdout: true, script: "git rev-list ${oldRef}..${newRef}").trim()
[6b6c26e]249        def revList = SplitLines( revText )
[6e31c43]250
[fdb6ac6]251        def gitUpdate = ""
252        revList.each { rev ->
[249091f]253                def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
[fce01e7]254                gitUpdate = gitUpdate + "       via  ${rev} (${type})"
255        }
256
257        def rev = oldRef
[249091f]258        def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
259        gitUpdate = gitUpdate + "      from  ${rev} (${type})"
[fce01e7]260
[249091f]261        def gitLog    = sh(returnStdout: true, script: "git rev-list --format=short ${oldRef}...${newRef}").trim()
[fce01e7]262
[249091f]263        def gitDiff   = sh(returnStdout: true, script: "git diff --stat --color ${newRef} ${oldRef}").trim()
[fce01e7]264        gitDiff = gitDiff.replace('[32m', '<span style="color: #00AA00;">')
265        gitDiff = gitDiff.replace('[31m', '<span style="color: #AA0000;">')
266        gitDiff = gitDiff.replace('[m', '</span>')
[7a927ed0]267
[a336d46]268        return """
[13c98a4]269<pre>
[848fb00]270The branch ${env.BRANCH_NAME} has been updated.
[7a927ed0]271${gitUpdate}
[13c98a4]272</pre>
273
274<p>Check console output at ${env.BUILD_URL} to view the results.</p>
[7b1a604]275
[13c98a4]276<p>- Status --------------------------------------------------------------</p>
[7b1a604]277
[13c98a4]278<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
[7b1a604]279
[13c98a4]280<p>- Log -----------------------------------------------------------------</p>
[e8a22a7]281
[13c98a4]282<pre>
[7a927ed0]283${gitLog}
[13c98a4]284</pre>
285
286<p>-----------------------------------------------------------------------</p>
287<pre>
[7b1a604]288Summary of changes:
[7a927ed0]289${gitDiff}
[13c98a4]290</pre>
[7b1a604]291"""
[a336d46]292}
293
294//Standard build email notification
[13c98a4]295def email(boolean log) {
[a336d46]296        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
297        //Configurations for email format
298        echo 'Notifying users of result'
299
300        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
301        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
[13c98a4]302        def email_body = """<p>This is an automated email from the Jenkins build machine. It was
[a336d46]303generated because of a git hooks/post-receive script following
[986e260]304a ref change which was pushed to the C\u2200 repository.</p>
[a336d46]305""" + GitLogMessage()
[e8a22a7]306
[13c98a4]307        def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
[e8a22a7]308
[13c98a4]309        if( Settings && !Settings.Silent ) {
[094a42c]310                //send email notification
311                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
312        } else {
313                echo "Would send email to: ${email_to}"
314                echo "With title: ${email_subject}"
315                echo "Content: \n${email_body}"
316        }
[e8a22a7]317}
[5b8413b4]318
319//===========================================================================================================
320// Helper classes/variables/routines
321//===========================================================================================================
322//Description of a compiler (Must be serializable since pipelines are persistent)
323class CC_Desc implements Serializable {
[93fe3154]324        public String name
325        public String CXX
[6ebc13f]326        public String CC
[93fe3154]327
[6ebc13f]328        CC_Desc(String name, String CXX, String CC) {
[93fe3154]329                this.name = name
330                this.CXX = CXX
[6ebc13f]331                this.CC = CC
[5b8413b4]332        }
333}
334
335//Description of an architecture (Must be serializable since pipelines are persistent)
336class Arch_Desc implements Serializable {
337        public String name
338        public String flags
[5307c33]339        public String node
[5b8413b4]340
[5307c33]341        Arch_Desc(String name, String flags, String node) {
[5b8413b4]342                this.name  = name
343                this.flags = flags
[5307c33]344                this.node  = node
[5b8413b4]345        }
346}
347
348class BuildSettings implements Serializable {
349        public final CC_Desc Compiler
350        public final Arch_Desc Architecture
351        public final Boolean RunAllTests
352        public final Boolean RunBenchmark
353        public final Boolean BuildDocumentation
354        public final Boolean Publish
355        public final Boolean Silent
356        public final Boolean IsSandbox
357        public final String DescLong
358        public final String DescShort
359
[a336d46]360        public String GitNewRef
361        public String GitOldRef
362
[490cb3c]363        BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
[5b8413b4]364                switch( param.Compiler ) {
[099f5bd]365                        case 'gcc-9':
366                                this.Compiler = new CC_Desc('gcc-9', 'g++-9', 'gcc-9')
367                        break
368                        case 'gcc-8':
369                                this.Compiler = new CC_Desc('gcc-8', 'g++-8', 'gcc-8')
370                        break
371                        case 'gcc-7':
372                                this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7')
373                        break
[5b8413b4]374                        case 'gcc-6':
375                                this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
376                        break
377                        case 'gcc-5':
378                                this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
379                        break
380                        case 'gcc-4.9':
381                                this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
382                        break
383                        case 'clang':
[099f5bd]384                                this.Compiler = new CC_Desc('clang', 'clang++-6.0', 'gcc-6')
[5b8413b4]385                        break
386                        default :
387                                error "Unhandled compiler : ${cc}"
388                }
389
390                switch( param.Architecture ) {
391                        case 'x64':
[a3e8281]392                                this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
[5b8413b4]393                        break
394                        case 'x86':
[a3e8281]395                                this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
[5b8413b4]396                        break
397                        default :
398                                error "Unhandled architecture : ${arch}"
399                }
400
[f95e8f0]401                this.IsSandbox          = (branch == "jenkins-sandbox")
[5b8413b4]402                this.RunAllTests        = param.RunAllTests
[7a230fd]403                this.RunBenchmark       = param.RunBenchmark
[5b8413b4]404                this.BuildDocumentation = param.BuildDocumentation
[7a230fd]405                this.Publish            = param.Publish
[5b8413b4]406                this.Silent             = param.Silent
407
408                def full = param.RunAllTests ? " (Full)" : ""
[490cb3c]409                this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
[5b8413b4]410
[93fe3154]411                this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
[5b8413b4]412Architecture            : ${ this.Architecture.name }
413Arc Flags               : ${ this.Architecture.flags }
414Run All Tests           : ${ this.RunAllTests.toString() }
415Run Benchmark           : ${ this.RunBenchmark.toString() }
416Build Documentation     : ${ this.BuildDocumentation.toString() }
417Publish                 : ${ this.Publish.toString() }
418Silent                  : ${ this.Silent.toString() }
419"""
[a336d46]420
421                this.GitNewRef = ''
422                this.GitOldRef = ''
[5b8413b4]423        }
424}
425
[490cb3c]426class PlotGroup implements Serializable {
427        public String name
428        public String unit
429        public boolean log
430
431        PlotGroup(String name, String unit, boolean log) {
432                this.name = name
433                this.unit = unit
434                this.log = log
435        }
436}
437
[5b8413b4]438def prepare_build() {
439        // prepare the properties
440        properties ([                                                                                                   \
441                [$class: 'ParametersDefinitionProperty',                                                                \
442                        parameterDefinitions: [                                                                         \
443                                [$class: 'ChoiceParameterDefinition',                                           \
444                                        description: 'Which compiler to use',                                   \
445                                        name: 'Compiler',                                                                       \
[fe27d99]446                                        choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang',                                   \
447                                        defaultValue: 'gcc-8',                                                          \
[5b8413b4]448                                ],                                                                                              \
449                                [$class: 'ChoiceParameterDefinition',                                           \
450                                        description: 'The target architecture',                                 \
451                                        name: 'Architecture',                                                           \
452                                        choices: 'x64\nx86',                                                            \
453                                        defaultValue: 'x64',                                                            \
454                                ],                                                                                              \
455                                [$class: 'BooleanParameterDefinition',                                                  \
456                                        description: 'If false, only the quick test suite is ran',              \
457                                        name: 'RunAllTests',                                                            \
458                                        defaultValue: false,                                                            \
459                                ],                                                                                              \
460                                [$class: 'BooleanParameterDefinition',                                                  \
461                                        description: 'If true, jenkins also runs benchmarks',           \
462                                        name: 'RunBenchmark',                                                           \
463                                        defaultValue: false,                                                            \
464                                ],                                                                                              \
465                                [$class: 'BooleanParameterDefinition',                                                  \
466                                        description: 'If true, jenkins also builds documentation',              \
467                                        name: 'BuildDocumentation',                                                     \
468                                        defaultValue: true,                                                             \
469                                ],                                                                                              \
470                                [$class: 'BooleanParameterDefinition',                                                  \
471                                        description: 'If true, jenkins also publishes results',                 \
472                                        name: 'Publish',                                                                        \
473                                        defaultValue: false,                                                            \
474                                ],                                                                                              \
475                                [$class: 'BooleanParameterDefinition',                                                  \
476                                        description: 'If true, jenkins will not send emails',           \
477                                        name: 'Silent',                                                                         \
478                                        defaultValue: false,                                                            \
479                                ],                                                                                              \
480                        ],
481                ]])
482
[4c55047]483        // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
484        checkout scm
[2407853]485
[490cb3c]486        final settings = new BuildSettings(params, env.BRANCH_NAME)
[5b8413b4]487
488        currentBuild.description = settings.DescShort
489        echo                       settings.DescLong
490
491        return settings
492}
493
[6c55a3d]494def build_stage(String name, boolean run, Closure block ) {
[5b8413b4]495        StageName = name
496        echo " -------- ${StageName} -------- "
[8ecb590]497        if(run) {
498                stage(name, block)
499        } else {
500                stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
501        }
[5b8413b4]502}
503
504def make_doc() {
505        def err = null
506        try {
507                sh 'make clean > /dev/null'
508                sh 'make > /dev/null 2>&1'
509        }
510        catch (Exception caughtError) {
511                err = caughtError //rethrow error later
[65f4a51]512                sh 'cat build/*.log'
[5b8413b4]513        }
514        finally {
515                if (err) throw err // Must re-throw exception to propagate error
516        }
[a2a0065]517}
518
[3221a2b]519def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
[8d63649]520
[1b3eef8]521        if(new_data) {
522                echo "Publishing new data"
523        }
524
[cdcd53dc]525        def series = new_data ? [[
[df57a84]526                                file: "${file}.csv",
[3c40dc2a]527                                exclusionValues: '',
528                                displayTableFlag: false,
529                                inclusionFlag: 'OFF',
530                                url: ''
[cdcd53dc]531                        ]] : [];
[8d63649]532
533        echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
534        dir("${BuildDir}/benchmark/") {
535                plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
536                        csvSeries: series,
[490cb3c]537                        group: "${group.name}",
[3c40dc2a]538                        title: "${title}",
539                        style: 'lineSimple',
540                        exclZero: false,
541                        keepRecords: false,
[3221a2b]542                        logarithmic: !relative && group.log,
[3c40dc2a]543                        numBuilds: '120',
544                        useDescr: true,
[490cb3c]545                        yaxis: group.unit,
[3c40dc2a]546                        yaxisMaximum: '',
547                        yaxisMinimum: ''
[df57a84]548        }
549}
Note: See TracBrowser for help on using the repository browser.