Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    r85142648 rda60c631  
    11#!groovy
    22
    3 import groovy.transform.Field
    4 
    5 // For skipping stages
    6 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
    7 
    83//===========================================================================================================
    94// Main loop of the compilation
    105//===========================================================================================================
    11 
    12 node('master') {
    13         // Globals
    14         BuildDir  = pwd tmp: true
    15         SrcDir    = pwd tmp: false
    16         Settings  = null
    17         StageName = ''
    18 
    19         // Local variables
     6node ('master'){
     7
     8        boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox"
    209        def err = null
    2110        def log_needed = false
     11
     12        stage_name              = ''
     13
     14        compiler                = null
     15        arch_name               = ''
     16        architecture    = ''
     17
     18        do_alltests             = false
     19        do_benchmark    = false
     20        do_doc          = false
     21        do_publish              = false
     22        do_sendemail    = true
    2223
    2324        currentBuild.result = "SUCCESS"
     
    2728                wrap([$class: 'TimestamperBuildWrapper']) {
    2829
    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
     30                        notify_server(0)
     31
     32                        prepare_build()
     33
     34                        checkout()
     35
     36                        notify_server(0)
     37
     38                        build()
     39
     40                        test()
     41
     42                        benchmark()
     43
     44                        clean()
     45
     46                        build_doc()
     47
     48                        publish()
     49
     50                        notify_server(45)
    5351                }
    5452        }
     
    6058                err = caughtError
    6159
    62                 echo err.toString()
    63 
    6460                //An error has occured, the build log is relevent
    6561                log_needed = true
    6662
    6763                //Store the result of the build log
    68                 currentBuild.result = "${StageName} FAILURE".trim()
     64                currentBuild.result = "${stage_name} FAILURE".trim()
    6965        }
    7066
    7167        finally {
    7268                //Send email with final results if this is not a full build
    73                 email(log_needed)
     69                if( do_sendemail && !bIsSandbox ) {
     70                        echo 'Notifying users of result'
     71                        email(currentBuild.result, log_needed)
     72                }
    7473
    7574                echo 'Build Completed'
     
    8180        }
    8281}
    83 //===========================================================================================================
    84 // Main compilation routines
    85 //===========================================================================================================
    86 def 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
    96 def 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 
    107 def build() {
    108         debug = true
    109         release = Settings.RunAllTests || Settings.RunBenchmark
    110         build_stage('Build : configure', true) {
    111                 // Build outside of the src tree to ease cleaning
    112                 dir (BuildDir) {
    113                         //Configure the conpilation (Output is not relevant)
    114                         //Use the current directory as the installation target so nothing escapes the sandbox
    115                         //Also specify the compiler by hand
    116                         targets=""
    117                         if( Settings.RunAllTests || Settings.RunBenchmark ) {
    118                                 targets="--with-target-hosts='host:debug,host:nodebug'"
    119                         } else {
    120                                 targets="--with-target-hosts='host:debug'"
    121                         }
    122 
    123                         sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
    124 
    125                         // Configure libcfa
    126                         sh 'make -j 8 --no-print-directory configure-libcfa'
    127                 }
    128         }
    129 
    130         build_stage('Build : cfa-cpp', true) {
    131                 // Build outside of the src tree to ease cleaning
    132                 dir (BuildDir) {
    133                         // Build driver
    134                         sh 'make -j 8 --no-print-directory -C driver'
    135 
    136                         // Build translator
    137                         sh 'make -j 8 --no-print-directory -C src'
    138                 }
    139         }
    140 
    141         build_stage('Build : libcfa(debug)', debug) {
    142                 // Build outside of the src tree to ease cleaning
    143                 dir (BuildDir) {
    144                         sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
    145                 }
    146         }
    147 
    148         build_stage('Build : libcfa(nodebug)', release) {
    149                 // Build outside of the src tree to ease cleaning
    150                 dir (BuildDir) {
    151                         sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
    152                 }
    153         }
    154 }
    155 
    156 def test() {
    157         try {
    158                 build_stage('Test: short', !Settings.RunAllTests) {
    159                         dir (BuildDir) {
    160                                 //Run the tests from the tests directory
    161                                 sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
    162                         }
    163                 }
    164 
    165                 build_stage('Test: full', Settings.RunAllTests) {
    166                         dir (BuildDir) {
    167                                         //Run the tests from the tests directory
    168                                         sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
    169                                         sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
    170                         }
    171                 }
    172         }
    173         catch (Exception err) {
    174                 echo "Archiving core dumps"
    175                 dir (BuildDir) {
    176                         archiveArtifacts artifacts: "tests/crashes/**/*", fingerprint: true
    177                 }
    178                 throw err
    179         }
    180 }
    181 
    182 def benchmark() {
    183         build_stage('Benchmark', Settings.RunBenchmark) {
    184                 dir (BuildDir) {
    185                         //Append bench results
    186                         sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
    187                 }
    188         }
    189 }
    190 
    191 def build_doc() {
    192         build_stage('Documentation', Settings.BuildDocumentation) {
    193                 dir ('doc/user') {
    194                         make_doc()
    195                 }
    196 
    197                 dir ('doc/refrat') {
    198                         make_doc()
    199                 }
    200         }
    201 }
    202 
    203 def publish() {
    204         build_stage('Publish', true) {
    205 
    206                 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
    207 
    208                 def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
    209                 def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
    210 
    211                 //Then publish the results
    212                 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile'       , groupCompile    , false, 'Compilation')
    213                 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff'  , groupCompile    , true , 'Compilation (relative)')
    214                 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch'     , groupConcurrency, false, 'Context Switching')
    215                 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff', groupConcurrency, true , 'Context Switching (relative)')
    216                 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex'         , groupConcurrency, false, 'Mutual Exclusion')
    217                 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff'    , groupConcurrency, true , 'Mutual Exclusion (relative)')
    218                 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal'        , groupConcurrency, false, 'Internal and External Scheduling')
    219                 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal.diff'   , groupConcurrency, true , 'Internal and External Scheduling (relative)')
    220         }
    221 }
    222 
    223 //===========================================================================================================
    224 //Routine responsible of sending the email notification once the build is completed
    225 //===========================================================================================================
    226 @NonCPS
    227 def SplitLines(String text) {
    228         def list = []
    229 
    230         text.eachLine {
    231                 list += it
    232         }
    233 
    234         return list
    235 }
    236 
    237 def GitLogMessage() {
    238         if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
    239 
    240         def oldRef = Settings.GitOldRef
    241         def newRef = Settings.GitNewRef
    242 
    243         def revText = sh(returnStdout: true, script: "git rev-list ${oldRef}..${newRef}").trim()
    244         def revList = SplitLines( revText )
    245 
    246         def gitUpdate = ""
    247         revList.each { rev ->
    248                 def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
    249                 gitUpdate = gitUpdate + "       via  ${rev} (${type})"
    250         }
    251 
    252         def rev = oldRef
    253         def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
    254         gitUpdate = gitUpdate + "      from  ${rev} (${type})"
    255 
    256         def gitLog    = sh(returnStdout: true, script: "git rev-list --format=short ${oldRef}...${newRef}").trim()
    257 
    258         def gitDiff   = sh(returnStdout: true, script: "git diff --stat --color ${newRef} ${oldRef}").trim()
    259         gitDiff = gitDiff.replace('[32m', '<span style="color: #00AA00;">')
    260         gitDiff = gitDiff.replace('[31m', '<span style="color: #AA0000;">')
    261         gitDiff = gitDiff.replace('[m', '</span>')
    262 
    263         return """
    264 <pre>
    265 The branch ${env.BRANCH_NAME} has been updated.
    266 ${gitUpdate}
    267 </pre>
    268 
    269 <p>Check console output at ${env.BUILD_URL} to view the results.</p>
    270 
    271 <p>- Status --------------------------------------------------------------</p>
    272 
    273 <p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
    274 
    275 <p>- Log -----------------------------------------------------------------</p>
    276 
    277 <pre>
    278 ${gitLog}
    279 </pre>
    280 
    281 <p>-----------------------------------------------------------------------</p>
    282 <pre>
    283 Summary of changes:
    284 ${gitDiff}
    285 </pre>
    286 """
    287 }
    288 
    289 //Standard build email notification
    290 def email(boolean log) {
    291         //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
    292         //Configurations for email format
    293         echo 'Notifying users of result'
    294 
    295         def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
    296         def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
    297         def email_body = """<p>This is an automated email from the Jenkins build machine. It was
    298 generated because of a git hooks/post-receive script following
    299 a ref change which was pushed to the C\u2200 repository.</p>
    300 """ + GitLogMessage()
    301 
    302         def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
    303 
    304         if( Settings && !Settings.Silent ) {
    305                 //send email notification
    306                 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
    307         } else {
    308                 echo "Would send email to: ${email_to}"
    309                 echo "With title: ${email_subject}"
    310                 echo "Content: \n${email_body}"
    311         }
    312 }
    31382
    31483//===========================================================================================================
    31584// Helper classes/variables/routines
    31685//===========================================================================================================
    317 //Description of a compiler (Must be serializable since pipelines are persistent)
    318 class CC_Desc implements Serializable {
    319         public String name
    320         public String CXX
    321         public String CC
    322 
    323         CC_Desc(String name, String CXX, String CC) {
    324                 this.name = name
    325                 this.CXX = CXX
    326                 this.CC = CC
    327         }
    328 }
    329 
    330 //Description of an architecture (Must be serializable since pipelines are persistent)
    331 class Arch_Desc implements Serializable {
    332         public String name
    333         public String flags
    334         public String node
    335 
    336         Arch_Desc(String name, String flags, String node) {
    337                 this.name  = name
    338                 this.flags = flags
    339                 this.node  = node
    340         }
    341 }
    342 
    343 class BuildSettings implements Serializable {
    344         public final CC_Desc Compiler
    345         public final Arch_Desc Architecture
    346         public final Boolean RunAllTests
    347         public final Boolean RunBenchmark
    348         public final Boolean BuildDocumentation
    349         public final Boolean Publish
    350         public final Boolean Silent
    351         public final Boolean IsSandbox
    352         public final String DescLong
    353         public final String DescShort
    354 
    355         public String GitNewRef
    356         public String GitOldRef
    357 
    358         BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
    359                 switch( param.Compiler ) {
    360                         case 'gcc-6':
    361                                 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
    362                         break
    363                         case 'gcc-5':
    364                                 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
    365                         break
    366                         case 'gcc-4.9':
    367                                 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
    368                         break
    369                         case 'clang':
    370                                 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
    371                         break
    372                         default :
    373                                 error "Unhandled compiler : ${cc}"
    374                 }
    375 
    376                 switch( param.Architecture ) {
    377                         case 'x64':
    378                                 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
    379                         break
    380                         case 'x86':
    381                                 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
    382                         break
    383                         default :
    384                                 error "Unhandled architecture : ${arch}"
    385                 }
    386 
    387                 this.IsSandbox          = (branch == "jenkins-sandbox")
    388                 this.RunAllTests        = param.RunAllTests
    389                 this.RunBenchmark       = param.RunBenchmark
    390                 this.BuildDocumentation = param.BuildDocumentation
    391                 this.Publish            = param.Publish
    392                 this.Silent             = param.Silent
    393 
    394                 def full = param.RunAllTests ? " (Full)" : ""
    395                 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
    396 
    397                 this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
    398 Architecture            : ${ this.Architecture.name }
    399 Arc Flags               : ${ this.Architecture.flags }
    400 Run All Tests           : ${ this.RunAllTests.toString() }
    401 Run Benchmark           : ${ this.RunBenchmark.toString() }
    402 Build Documentation     : ${ this.BuildDocumentation.toString() }
    403 Publish                 : ${ this.Publish.toString() }
    404 Silent                  : ${ this.Silent.toString() }
    405 """
    406 
    407                 this.GitNewRef = ''
    408                 this.GitOldRef = ''
    409         }
    410 }
    411 
    412 class PlotGroup implements Serializable {
    413         public String name
    414         public String unit
    415         public boolean log
    416 
    417         PlotGroup(String name, String unit, boolean log) {
    418                 this.name = name
    419                 this.unit = unit
    420                 this.log = log
    421         }
     86//Helper routine to collect information about the git history
     87def collect_git_info() {
     88
     89        checkout scm
     90
     91        //create the temporary output directory in case it doesn't already exist
     92        def out_dir = pwd tmp: true
     93        sh "mkdir -p ${out_dir}"
     94
     95        //parse git logs to find what changed
     96        gitRefName = env.BRANCH_NAME
     97        sh "git reflog > ${out_dir}/GIT_COMMIT"
     98        git_reflog = readFile("${out_dir}/GIT_COMMIT")
     99        gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
     100        gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]
    422101}
    423102
    424103def prepare_build() {
    425         // prepare the properties
    426104        properties ([                                                                                                   \
    427105                [$class: 'ParametersDefinitionProperty',                                                                \
     
    429107                                [$class: 'ChoiceParameterDefinition',                                           \
    430108                                        description: 'Which compiler to use',                                   \
    431                                         name: 'Compiler',                                                                       \
     109                                        name: 'pCompiler',                                                              \
    432110                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
    433111                                        defaultValue: 'gcc-6',                                                          \
     
    435113                                [$class: 'ChoiceParameterDefinition',                                           \
    436114                                        description: 'The target architecture',                                 \
    437                                         name: 'Architecture',                                                           \
     115                                        name: 'pArchitecture',                                                          \
    438116                                        choices: 'x64\nx86',                                                            \
    439117                                        defaultValue: 'x64',                                                            \
     
    441119                                [$class: 'BooleanParameterDefinition',                                                  \
    442120                                        description: 'If false, only the quick test suite is ran',              \
    443                                         name: 'RunAllTests',                                                            \
     121                                        name: 'pRunAllTests',                                                           \
    444122                                        defaultValue: false,                                                            \
    445123                                ],                                                                                              \
    446124                                [$class: 'BooleanParameterDefinition',                                                  \
    447125                                        description: 'If true, jenkins also runs benchmarks',           \
    448                                         name: 'RunBenchmark',                                                           \
     126                                        name: 'pRunBenchmark',                                                          \
     127                                        defaultValue: true,                                                             \
     128                                ],                                                                                              \
     129                                [$class: 'BooleanParameterDefinition',                                                  \
     130                                        description: 'If true, jenkins also builds documentation',              \
     131                                        name: 'pBuildDocumentation',                                                    \
     132                                        defaultValue: true,                                                             \
     133                                ],                                                                                              \
     134                                [$class: 'BooleanParameterDefinition',                                                  \
     135                                        description: 'If true, jenkins also publishes results',                 \
     136                                        name: 'pPublish',                                                               \
    449137                                        defaultValue: false,                                                            \
    450                                 ],                                                                                              \
    451                                 [$class: 'BooleanParameterDefinition',                                                  \
    452                                         description: 'If true, jenkins also builds documentation',              \
    453                                         name: 'BuildDocumentation',                                                     \
    454                                         defaultValue: true,                                                             \
    455                                 ],                                                                                              \
    456                                 [$class: 'BooleanParameterDefinition',                                                  \
    457                                         description: 'If true, jenkins also publishes results',                 \
    458                                         name: 'Publish',                                                                        \
    459                                         defaultValue: false,                                                            \
    460138                                ],                                                                                              \
    461139                                [$class: 'BooleanParameterDefinition',                                                  \
    462140                                        description: 'If true, jenkins will not send emails',           \
    463                                         name: 'Silent',                                                                         \
     141                                        name: 'pSilent',                                                                        \
    464142                                        defaultValue: false,                                                            \
    465143                                ],                                                                                              \
     
    467145                ]])
    468146
    469         // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
    470         checkout scm
    471 
    472         final settings = new BuildSettings(params, env.BRANCH_NAME)
    473 
    474         currentBuild.description = settings.DescShort
    475         echo                       settings.DescLong
    476 
    477         return settings
    478 }
    479 
    480 def build_stage(String name, boolean run, Closure block ) {
    481         StageName = name
    482         echo " -------- ${StageName} -------- "
    483         if(run) {
    484                 stage(name, block)
    485         } else {
    486                 stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
    487         }
     147        compiler                = compiler_from_params( pCompiler )
     148        arch_name               = pArchitecture
     149        architecture    = architecture_from_params( arch_name )
     150
     151        do_alltests             = (pRunAllTests == 'true')
     152        do_benchmark    = (pRunBenchmark == 'true')
     153        do_doc          = (pBuildDocumentation == 'true')
     154        do_publish              = (pPublish == 'true')
     155        do_sendemail    = ! (pSilent == 'true')
     156
     157        echo """Compiler              : ${compiler.cc_name} (${compiler.cpp_cc}/${compiler.cfa_cc})
     158Architecture            : ${arch_name}
     159Arc Flags               : ${architecture}
     160Run All Tests           : ${ pRunAllTests.toString() }
     161Run Benchmark           : ${ pRunBenchmark.toString() }
     162Build Documentation     : ${ pBuildDocumentation.toString() }
     163Publish                 : ${ pPublish.toString() }
     164Silent                  : ${ pSilent.toString() }
     165"""
     166
     167        collect_git_info()
     168}
     169
     170def build_stage(String name, Closure block ) {
     171        stage_name = name
     172        stage(name, block)
     173}
     174
     175def notify_server(int wait) {
     176        sh """curl --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
     177        return
    488178}
    489179
     
    496186        catch (Exception caughtError) {
    497187                err = caughtError //rethrow error later
    498                 sh 'cat build/*.log'
     188                sh 'cat *.log'
    499189        }
    500190        finally {
     
    503193}
    504194
    505 def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
    506 
    507         if(new_data) {
    508                 echo "Publishing new data"
    509         }
    510 
    511         def series = new_data ? [[
    512                                 file: "${file}.csv",
    513                                 exclusionValues: '',
    514                                 displayTableFlag: false,
    515                                 inclusionFlag: 'OFF',
    516                                 url: ''
    517                         ]] : [];
    518 
    519         echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
    520         dir("${BuildDir}/benchmark/") {
    521                 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
    522                         csvSeries: series,
    523                         group: "${group.name}",
    524                         title: "${title}",
    525                         style: 'lineSimple',
    526                         exclZero: false,
    527                         keepRecords: false,
    528                         logarithmic: !relative && group.log,
    529                         numBuilds: '120',
    530                         useDescr: true,
    531                         yaxis: group.unit,
    532                         yaxisMaximum: '',
    533                         yaxisMinimum: ''
    534         }
    535 }
     195//Description of a compiler (Must be serializable since pipelines are persistent)
     196class CC_Desc implements Serializable {
     197        public String cc_name
     198        public String cpp_cc
     199        public String cfa_cc
     200
     201        CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
     202                this.cc_name = cc_name
     203                this.cpp_cc = cpp_cc
     204                this.cfa_cc = cfa_cc
     205        }
     206}
     207
     208def compiler_from_params(cc) {
     209        switch( cc ) {
     210                case 'gcc-6':
     211                        return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
     212                break
     213                case 'gcc-5':
     214                        return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
     215                break
     216                case 'gcc-4.9':
     217                        return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
     218                break
     219                case 'clang':
     220                        return new CC_Desc('clang', 'clang++', 'gcc-6')
     221                break
     222                default :
     223                        error "Unhandled compiler : ${cc}"
     224        }
     225}
     226
     227def architecture_from_params( arch ) {
     228        switch( arch ) {
     229                case 'x64':
     230                        return '--host=x86_64'
     231                break
     232                case 'x86':
     233                        return '--host=i386'
     234                break
     235                default :
     236                        error "Unhandled architecture : ${arch}"
     237        }
     238}
     239
     240//===========================================================================================================
     241// Main compilation routines
     242//===========================================================================================================
     243//Compilation script is done here but environnement set-up and error handling is done in main loop
     244def checkout() {
     245        build_stage('Checkout') {
     246                //checkout the source code and clean the repo
     247                checkout scm
     248
     249                //Clean all temporary files to make sure no artifacts of the previous build remain
     250                sh 'git clean -fdqx'
     251
     252                //Reset the git repo so no local changes persist
     253                sh 'git reset --hard'
     254        }
     255}
     256
     257def build() {
     258        build_stage('Build') {
     259
     260                def install_dir = pwd tmp: true
     261
     262                //Output compiler version to help with debug
     263                echo """C++ Compiler :"""
     264                sh "which ${compiler.cpp_cc} && ${compiler.cpp_cc} --version"
     265                echo """C   Compiler :"""
     266                sh "which ${compiler.cfa_cc} && ${compiler.cfa_cc} --version"
     267
     268                //Configure the conpilation (Output is not relevant)
     269                //Use the current directory as the installation target so nothing escapes the sandbox
     270                //Also specify the compiler by hand
     271                sh "./configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --prefix=${install_dir} --enable-silent-rules --quiet"
     272
     273                //Compile the project
     274                sh 'make -j 8 --no-print-directory V=0 install'
     275        }
     276}
     277
     278def test() {
     279        build_stage('Test') {
     280
     281                //Run the tests from the tests directory
     282                if ( do_alltests ) {
     283                        sh 'make -C src/tests all-tests debug=yes --no-print-directory'
     284                        sh 'make -C src/tests all-tests debug=no --no-print-directory'
     285                }
     286                else {
     287                        sh 'make -C src/tests --no-print-directory'
     288                }
     289        }
     290}
     291
     292def benchmark() {
     293        build_stage('Benchmark') {
     294
     295                if( !do_benchmark ) return
     296
     297                //Append bench results
     298                sh 'make -C src/benchmark --no-print-directory jenkins githash=' + gitRefNewValue + ' arch=' + arch_name + ' | tee bench.json'
     299        }
     300}
     301
     302def clean() {
     303        build_stage('Cleanup') {
     304
     305                //do a maintainer-clean to make sure we need to remake from scratch
     306                sh 'make maintainer-clean > /dev/null'
     307        }
     308}
     309
     310def build_doc() {
     311        build_stage('Documentation') {
     312
     313                if( !do_doc ) return
     314
     315                dir ('doc/user') {
     316                        make_doc()
     317                }
     318
     319                dir ('doc/refrat') {
     320                        make_doc()
     321                }
     322        }
     323}
     324
     325def publish() {
     326        build_stage('Publish') {
     327
     328                if( !do_publish ) return
     329
     330                //Then publish the results
     331                sh 'curl -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
     332        }
     333}
     334
     335//===========================================================================================================
     336//Routine responsible of sending the email notification once the build is completed
     337//===========================================================================================================
     338//Standard build email notification
     339def email(String status, boolean log) {
     340        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
     341        //Configurations for email format
     342        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
     343
     344        def gitLog = 'Error retrieving git logs'
     345        def gitDiff = 'Error retrieving git diff'
     346
     347        try {
     348
     349                sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG"
     350                gitLog = readFile('GIT_LOG')
     351
     352                sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF"
     353                gitDiff = readFile('GIT_DIFF')
     354        }
     355        catch (Exception error) {}
     356
     357        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
     358        def email_body = """This is an automated email from the Jenkins build machine. It was
     359generated because of a git hooks/post-receive script following
     360a ref change was pushed to the repository containing
     361the project "UNNAMED PROJECT".
     362
     363The branch ${env.BRANCH_NAME} has been updated.
     364   via  ${gitRefOldValue} (commit)
     365  from  ${gitRefNewValue} (commit)
     366
     367Check console output at ${env.BUILD_URL} to view the results.
     368
     369- Status --------------------------------------------------------------
     370
     371BUILD# ${env.BUILD_NUMBER} - ${status}
     372
     373- Log -----------------------------------------------------------------
     374${gitLog}
     375-----------------------------------------------------------------------
     376Summary of changes:
     377${gitDiff}
     378"""
     379
     380        def email_to = "cforall@lists.uwaterloo.ca"
     381
     382        //send email notification
     383        emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
     384}
Note: See TracChangeset for help on using the changeset viewer.