mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			
		
			
				
	
	
		
			280 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Groovy
		
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Groovy
		
	
	
echo "Start to build"
 | 
						|
 | 
						|
properties ([
 | 
						|
  buildDiscarder(
 | 
						|
    logRotator(
 | 
						|
      artifactNumToKeepStr: '10',
 | 
						|
      numToKeepStr: '100'
 | 
						|
    )
 | 
						|
  )
 | 
						|
])
 | 
						|
 | 
						|
// List of targets to compile
 | 
						|
def morpheusTargets = [
 | 
						|
  //"LPC1768",
 | 
						|
  //"NUCLEO_F401RE",
 | 
						|
  "K64F"
 | 
						|
]
 | 
						|
// Map morpheus toolchains to compiler labels on Jenkins
 | 
						|
def toolchains = [
 | 
						|
  ARM: "armcc",
 | 
						|
  IAR: "iar_arm",
 | 
						|
  GCC_ARM: "arm-none-eabi-gcc"
 | 
						|
]
 | 
						|
// yotta target includes toolchain
 | 
						|
def yottaTargets = [
 | 
						|
  "frdm-k64f-gcc": "gcc",
 | 
						|
  "frdm-k64f-armcc": "armcc",
 | 
						|
  "stm32f429i-disco-gcc": "gcc",
 | 
						|
  "x86-linux-native": "linux && astyle"
 | 
						|
]
 | 
						|
 | 
						|
// Initial maps for parallel build steps
 | 
						|
def stepsForParallel = [:]
 | 
						|
// Jenkins pipeline does not support map.each, we need to use oldschool for loop
 | 
						|
for (int i = 0; i < morpheusTargets.size(); i++) {
 | 
						|
  for(int j = 0; j < toolchains.size(); j++) {
 | 
						|
    def target = morpheusTargets.get(i)
 | 
						|
    def toolchain = toolchains.keySet().asList().get(j)
 | 
						|
    def compilerLabel = toolchains.get(toolchain)
 | 
						|
    def stepName = "mbed-os5-${target} ${toolchain}"
 | 
						|
    stepsForParallel[stepName] = morpheusBuildStep(target, compilerLabel, toolchain)
 | 
						|
  }
 | 
						|
}
 | 
						|
// map yotta steps
 | 
						|
for (int i = 0; i < yottaTargets.size(); i++) {
 | 
						|
  def target = yottaTargets.keySet().asList().get(i)
 | 
						|
  def compilerLabel = yottaTargets.get(target)
 | 
						|
  def stepName = "mbed-os3-${target}"
 | 
						|
  stepsForParallel[stepName] = yottaBuildStep(target, compilerLabel)
 | 
						|
}
 | 
						|
 | 
						|
/* Jenkins does not allow stages inside parallel execution,
 | 
						|
 * https://issues.jenkins-ci.org/browse/JENKINS-26107 will solve this by adding labeled blocks
 | 
						|
 */
 | 
						|
// Actually run the steps in parallel - parallel takes a map as an argument, hence the above.
 | 
						|
timestamps {
 | 
						|
  timeout(time: 30, unit: "MINUTES") {
 | 
						|
    parallel stepsForParallel
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
def execute(cmd) {
 | 
						|
  if(isUnix()) {
 | 
						|
   sh "${cmd}"
 | 
						|
  } else {
 | 
						|
   bat "${cmd}"
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
//Create morpheus build steps for parallel execution
 | 
						|
def morpheusBuildStep(target, compilerLabel, toolchain) {
 | 
						|
  return {
 | 
						|
    node ("${compilerLabel}") {
 | 
						|
      deleteDir()
 | 
						|
      dir("mbed-trace") {
 | 
						|
        String buildName = "mbed-os5-${target}-${toolchain}"
 | 
						|
        def scmVars = checkout scm
 | 
						|
        env.GIT_COMMIT_HASH = scmVars.GIT_COMMIT
 | 
						|
        setBuildStatus('PENDING', "build ${buildName}", 'build starts')
 | 
						|
        stage ("build:${buildName}") {
 | 
						|
          try{
 | 
						|
            execute("mbed --version")
 | 
						|
            execute("echo https://github.com/armmbed/mbed-os/#6a0a86538c0b9b2bfcc4583b1e2b7fea8f4e71e9 > mbed-os.lib")
 | 
						|
            execute("mbed deploy")
 | 
						|
            execute("rm -rf ./mbed-os/platform/mbed-trace")
 | 
						|
            execute("mbed compile -m ${target} -t ${toolchain} --library")
 | 
						|
            setBuildStatus('SUCCESS', "build ${buildName}", "build done")
 | 
						|
          } catch (err) {
 | 
						|
            echo "Caught exception: ${err}"
 | 
						|
            setBuildStatus('FAILURE', "build ${buildName}", "build failed")
 | 
						|
            throw err
 | 
						|
          }
 | 
						|
        }
 | 
						|
        stage("build:example:${buildName}") {
 | 
						|
          execute("mkdir ../example-mbed-os-5 || true")
 | 
						|
          execute("cp -R example/mbed-os-5 ../example-mbed-os-5")
 | 
						|
          dir("../example-mbed-os-5") {
 | 
						|
            def exampleName = "example-${buildName}"
 | 
						|
            setBuildStatus('PENDING', "build ${exampleName}", 'build starts')
 | 
						|
            try {
 | 
						|
              execute("echo \"https://github.com/ARMmbed/mbed-os/#6a0a86538c0b9b2bfcc4583b1e2b7fea8f4e71e9\" > mbed-os.lib")
 | 
						|
              execute("echo \"https://github.com/ARMmbed/mbed-trace#${env.GIT_COMMIT_HASH}\" > mbed-trace.lib")
 | 
						|
              execute("mbed new .")
 | 
						|
              execute("mbed deploy")
 | 
						|
              execute("rm -rf ./mbed-os/platform/mbed-trace")
 | 
						|
              execute("rm -rf ./mbed-trace/example")
 | 
						|
              execute("rm -rf ./mbed-trace/test")
 | 
						|
              execute("mbed compile -t ${toolchain} -m ${target}")
 | 
						|
              setBuildStatus('SUCCESS', "build ${exampleName}", "build done")
 | 
						|
            } catch(err) {
 | 
						|
              echo "Caught exception: ${err}"
 | 
						|
              setBuildStatus('FAILURE', "build ${exampleName}", "build failed")
 | 
						|
              currentBuild.result = 'FAILURE'
 | 
						|
            } finally {
 | 
						|
              // clean up
 | 
						|
              postBuild(buildName, false)
 | 
						|
              step([$class: 'WsCleanup'])
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
//Create yotta build steps for parallel execution
 | 
						|
def yottaBuildStep(target, compilerLabel) {
 | 
						|
  return {
 | 
						|
    String buildName = "mbed-os3-${target}"
 | 
						|
    node ("${compilerLabel}") {
 | 
						|
      deleteDir()
 | 
						|
      dir("mbed-trace") {
 | 
						|
        def scmVars = checkout scm
 | 
						|
        env.GIT_COMMIT_HASH = scmVars.GIT_COMMIT
 | 
						|
        def isTest = target == "x86-linux-native" // tests are valid only in linux target
 | 
						|
        stage ("build:${buildName}") {
 | 
						|
          setBuildStatus('PENDING', "build ${buildName}", 'build starts')
 | 
						|
          try{
 | 
						|
            execute("yotta --version")
 | 
						|
            execute("yotta target $target")
 | 
						|
            execute("yotta --plain build mbed-trace")
 | 
						|
            setBuildStatus('SUCCESS', "build ${buildName}", "build done")
 | 
						|
          } catch (err) {
 | 
						|
            echo "Caught exception: ${err}"
 | 
						|
            setBuildStatus('FAILURE', "build ${buildName}", "build failed")
 | 
						|
            currentBuild.result = 'FAILURE'
 | 
						|
          }
 | 
						|
        } // stage
 | 
						|
        if (isTest) {
 | 
						|
          stage("test:${buildName}") {
 | 
						|
            setBuildStatus('PENDING', "test ${buildName}", 'test starts')
 | 
						|
            try {
 | 
						|
              execute("yotta test mbed_trace_test")
 | 
						|
              execute("lcov --base-directory . --directory . --capture --output-file coverage.info")
 | 
						|
              execute("genhtml -o ./test_coverage coverage.info")
 | 
						|
              execute("gcovr -x -o junit.xml")
 | 
						|
              execute("cppcheck --enable=all --std=c99 --inline-suppr --template=\"{file},{line},{severity},{id},{message}\" source 2> cppcheck.txt")
 | 
						|
 | 
						|
              // check if astyle is correct
 | 
						|
              execute("astyle --options=.astylerc source/*.c mbed-trace/*.h")
 | 
						|
              // check differency
 | 
						|
              execute("git diff-index -p --exit-code HEAD")
 | 
						|
 | 
						|
              setBuildStatus('SUCCESS', "test ${buildName}", "test done")
 | 
						|
            } catch(err) {
 | 
						|
              echo "Caught exception: ${err}"
 | 
						|
              setBuildStatus('FAILURE', "test ${buildName}", "test failed")
 | 
						|
              currentBuild.result = 'FAILURE'
 | 
						|
            }
 | 
						|
          } // stage
 | 
						|
          stage("example:${buildName}") {
 | 
						|
            dir("example/linux") {
 | 
						|
              def exampleName = "example-linux"
 | 
						|
              setBuildStatus('PENDING', "build ${exampleName}", 'build starts')
 | 
						|
              try {
 | 
						|
                execute("make")
 | 
						|
                setBuildStatus('SUCCESS', "build ${exampleName}", "build done")
 | 
						|
              } catch(err) {
 | 
						|
                echo "Caught exception: ${err}"
 | 
						|
                setBuildStatus('FAILURE', "build ${exampleName}", "build failed")
 | 
						|
                currentBuild.result = 'FAILURE'
 | 
						|
              }
 | 
						|
            }
 | 
						|
          } // stage
 | 
						|
 | 
						|
          stage("leak-check:${buildName}") {
 | 
						|
            dir("example/linux") {
 | 
						|
              def stageName = "leak-check"
 | 
						|
              setBuildStatus('PENDING', "test ${stageName}", 'test starts')
 | 
						|
              try {
 | 
						|
                execute("./memtest.sh")
 | 
						|
                setBuildStatus('SUCCESS', "test ${stageName}", "test done")
 | 
						|
              } catch(err) {
 | 
						|
                echo "Caught exception: ${err}"
 | 
						|
                setBuildStatus('FAILURE', "test ${stageName}", "test failed")
 | 
						|
                currentBuild.result = 'FAILURE'
 | 
						|
              }
 | 
						|
            }
 | 
						|
          } // stage
 | 
						|
        } // if linux
 | 
						|
        postBuild(buildName, isTest)
 | 
						|
        step([$class: 'WsCleanup'])
 | 
						|
      } // dir
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
def postBuild(buildName, isTest) {
 | 
						|
    // move files to target+toolchain specific folder
 | 
						|
    execute("mkdir -p output/${buildName}")
 | 
						|
    execute("find . -name 'libmbed-trace.a' -exec mv {} 'output/${buildName}' \\;")
 | 
						|
    execute("find . -name 'mbed-trace.ar' -exec mv {} 'output/${buildName}' \\;")
 | 
						|
    execute("find ../example-mbed-os-5 -name 'example-mbed-os-5.bin' -exec mv {} 'output/${buildName}/example-mbed-os-5.bin' \\; || true")
 | 
						|
    // Archive artifacts
 | 
						|
    step([
 | 
						|
      $class: 'ArtifactArchiver',
 | 
						|
      artifacts: "cppcheck.txt,output/**",
 | 
						|
      fingerprint: true,
 | 
						|
      allowEmptyArchive: true
 | 
						|
    ])
 | 
						|
    if (isTest) {
 | 
						|
        // Publish cobertura
 | 
						|
        step([
 | 
						|
            $class: 'CoberturaPublisher',
 | 
						|
            coberturaReportFile: 'junit.xml'
 | 
						|
        ])
 | 
						|
        // Publish compiler warnings
 | 
						|
        step([
 | 
						|
          $class: 'WarningsPublisher',
 | 
						|
          parserConfigurations: [[
 | 
						|
            parserName: 'GNU Make + GNU C Compiler (gcc)',
 | 
						|
            pattern: 'mbed-trace/*.h,source/*.c,test/*.cpp'
 | 
						|
          ]],
 | 
						|
          unstableTotalAll: '0',
 | 
						|
          useDeltaValues: true,
 | 
						|
          usePreviousBuildAsReference: true
 | 
						|
        ])
 | 
						|
        // Publish HTML reports
 | 
						|
        publishHTML(target: [
 | 
						|
          alwayLinkToLastBuild: false,
 | 
						|
          keepAll: true,
 | 
						|
          reportDir: "test_coverage",
 | 
						|
          reportFiles: "index.html",
 | 
						|
          reportName: "Build HTML Report"
 | 
						|
        ])
 | 
						|
    }
 | 
						|
}
 | 
						|
// helper function to set build status to github PR
 | 
						|
def setBuildStatus(String state, String context, String message) {
 | 
						|
    step([
 | 
						|
        $class: "GitHubCommitStatusSetter",
 | 
						|
        reposSource: [
 | 
						|
            $class: "ManuallyEnteredRepositorySource",
 | 
						|
            url: "https://github.com/ARMmbed/mbed-trace.git"
 | 
						|
        ],
 | 
						|
        contextSource: [
 | 
						|
            $class: "ManuallyEnteredCommitContextSource",
 | 
						|
            context: context
 | 
						|
        ],
 | 
						|
        errorHandlers: [[
 | 
						|
            $class: "ChangingBuildStatusErrorHandler",
 | 
						|
            result: "UNSTABLE"
 | 
						|
        ]],
 | 
						|
        commitShaSource: [
 | 
						|
            $class: "ManuallyEnteredShaSource",
 | 
						|
            sha: env.GIT_COMMIT_HASH
 | 
						|
        ],
 | 
						|
        statusResultSource: [
 | 
						|
            $class: 'ConditionalStatusResultSource',
 | 
						|
            results: [
 | 
						|
                [
 | 
						|
                    $class: 'AnyBuildResult',
 | 
						|
                    message: message,
 | 
						|
                    state: state
 | 
						|
                ]
 | 
						|
            ]
 | 
						|
        ]
 | 
						|
    ])
 | 
						|
}
 |