Timmmm
Timmmm

Reputation: 96625

Post-build step in QBS

I'm trying to convert the nRF51822 (an Arm Cortex microcontroller) build process from Make to QBS. I've got the compilation process working ok (lots of hard-coded paths but I'll fix that later). However, the final step is to use objcopy to convert the .out file produced by the linker to a .hex file. I can't work out how to get my rule to run other than by making another Application like this (which doesn't work very well):

import qbs
import qbs.FileInfo

Project {
    CppApplication {
        type: "application" // To suppress bundle generation on Mac

        name: "nrf51_template"

        files: ["main.cpp",
            "nrf51822/Source/nrf_delay/nrf_delay.c"]

        Group {
            name: "Startup files"
            files: ["nrf51822/Source/Templates/system_" + deviceSeries + ".c",
            "nrf51822/Source/Templates/gcc/gcc_startup_" + deviceSeries + ".s"]
        }


        // The chip variant can be:
        //
        // "xxaa": The 256 kB version
        // "xxbb": The 128 kB version
        //
        // RFduino is xxaa.
        property string deviceVariant: "xxaa"

        // Must be "nrf51"
        property string deviceSeries: "nrf51"

        // The softdevice (radio firmware) to use. Can be:
        //
        // "": For no radio.
        // "s110": For BLE slave/peripheral
        // "s120": For BLE host/central
        // "s130": For BLE central and peripheral
        property string softDevice: "s110"

        // Must be cortex-m0
        property string cpu: "cortex-m0"

        cpp.includePaths: ["nrf51822/Include", "nrf51822/Include/gcc"]
        cpp.compilerName: ["arm-none-eabi-g++.exe"]
        cpp.compilerPath: ["C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/bin/arm-none-eabi-g++.exe"]
        cpp.linkerName: ["arm-none-eabi-g++.exe"]
        cpp.linkerPath: ["C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/bin/arm-none-eabi-g++.exe"]

        cpp.cxxFlags: ["-mcpu=" + cpu, "-mthumb", "-mabi=aapcs", "--std=c++11", "-mfloat-abi=soft"]
        cpp.linkerFlags: ["-L\"C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/arm-none-eabi/lib/armv6-m\"",
            "-L\"C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/lib/gcc/arm-none-eabi/4.8.3/armv6-m\"",
            "-Xlinker",
            "-Map=C:/Users/thutt/nRF51_Template/output_filename.map",
            "-mcpu=" + cpu,
            "-mthumb",
            "-mabi=aapcs",
            "-L", "C:/Users/thutt/nRF51_Template/nrf51822/Source/templates/gcc/",
            "-Tgcc_" + deviceSeries + "_" + softDevice + "_" + deviceVariant + ".ld"]

        cpp.defines: ["BOARD_PCA10001", "NRF51"]

        // Suppresses -m32 compiler option.
        cpp.architecture: "arm"

        // Suppress windows definitions and compiler options.
        cpp.minimumWindowsVersion: undefined

        cpp.executableSuffix: ".out"

        // To flash:

        // nrfjprog --reset --program $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

    }

    Application {
        name: "nrf51_template_hex"

        Group {
            files: "C:/Users/thutt/nRF51_Template-build/qtc_Desktop2-debug/nrf51_template.out"
            fileTags: ["out"]
        }

        Depends {
            name: "nrf51_template"
        }


        Rule {
            id: hex
            inputs: ["out"]

            Artifact {
                fileTags: ["application"]
                fileName: ".obj/" + product.name + "/" + input.baseDir + "/" + input.fileName + ".hex"
            }

            prepare: {
    //          var compilerPath = ModUtils.moduleProperty(product, "compilerPath");

                var objCopyPath = "C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/bin/arm-none-eabi-objcopy.exe";
                var args = ["-O", "ihex", input.filePath, output.filePath];
                var cmd = new Command(objCopyPath, args);

                cmd.description = "converting to hex: " + FileInfo.fileName(input.filePath);
                cmd.highlight = "linker";
                return cmd;
            }
        }
    }
}

Is it possible to have a post-link step in the CppApplication instead of two Applications like this? Am I better off defining a totally new Application with my own Rules for compilation and linking?

Also bonus question, is it possible to specify the "run" executable in the QBS file so that when I click run in QtCreator it actually runs nrfjprog.exe and flashes the code to the chip? (You can do this in the IDE but I'd prefer to be able to do it in the QBS file.)

Upvotes: 2

Views: 1798

Answers (1)

Timmmm
Timmmm

Reputation: 96625

Figured it out, the final targets are determined by the type: line in the Application so just change it to this:

import qbs
import qbs.FileInfo

Project {
    CppApplication {

        // The filetag to generate.
        type: "hex"

        name: "nrf51_template"

        files: ["main.cpp",
            "SaneSPI.cpp",
            "SaneSPI.h",
            "Timer.cpp",
            "Timer.h",
            "Delay.cpp",
            "Delay.h",
            "GPIO.cpp",
            "GPIO.h"]

        Group {
            name: "Startup files"
            files: ["nrf51822/Source/Templates/system_" + deviceSeries + ".c",
            "nrf51822/Source/Templates/gcc/gcc_startup_" + deviceSeries + ".s"]
        }


        // The chip variant can be:
        //
        // "xxaa": The 256 kB version
        // "xxbb": The 128 kB version
        //
        // RFduino is xxaa.
        property string deviceVariant: "xxaa"

        // Must be "nrf51"
        property string deviceSeries: "nrf51"

        // The softdevice (radio firmware) to use. Can be:
        //
        // "": For no radio.
        // "s110": For BLE slave/peripheral
        // "s120": For BLE host/central
        // "s130": For BLE central and peripheral
        property string softDevice: "s110"

        // Must be cortex-m0
        property string cpu: "cortex-m0"

        cpp.includePaths: ["nrf51822/Include",
            "nrf51822/Include/gcc",
            "nrf51822/Include/" + softDevice]
        cpp.compilerName: ["arm-none-eabi-g++.exe"]
        cpp.compilerPath: ["C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/bin/arm-none-eabi-g++.exe"]
        cpp.linkerName: ["arm-none-eabi-g++.exe"]
        cpp.linkerPath: ["C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/bin/arm-none-eabi-g++.exe"]

        cpp.cxxFlags: ["-mcpu=" + cpu, "-mthumb", "-mabi=aapcs", "--std=c++11", "-mfloat-abi=soft"]
        cpp.linkerFlags: ["-L\"C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/arm-none-eabi/lib/armv6-m\"",
            "-L\"C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/lib/gcc/arm-none-eabi/4.8.3/armv6-m\"",
            "-Xlinker",
            "-Map=C:/Users/thutt/nRF51_Template/output_filename.map",
            "-mcpu=" + cpu,
            "-mthumb",
            "-mabi=aapcs",
            "-L", "C:/Users/thutt/nRF51_Template/nrf51822/Source/templates/gcc/",
            "-Tgcc_" + deviceSeries + "_" + softDevice + "_" + deviceVariant + ".ld"]

        cpp.defines: ["BOARD_PCA10001", "NRF51"]

        // Suppresses -m32 compiler option.
        cpp.architecture: "arm"

        // Suppress windows definitions and compiler options.
        cpp.minimumWindowsVersion: undefined

        cpp.executableSuffix: ".out"

        Rule {
            id: hex
            inputs: ["application"]

            Artifact {
                fileTags: ["hex"]
                fileName: ".obj/" + product.name + "/" + input.baseDir + "/" + input.fileName + ".hex"
            }

            prepare: {
    //          var compilerPath = ModUtils.moduleProperty(product, "compilerPath");

                var objCopyPath = "C:/Program Files/GNU Tools ARM Embedded/4.8 2014q1/bin/arm-none-eabi-objcopy.exe";
                var args = ["-O", "ihex", input.filePath, output.filePath];
                var cmd = new Command(objCopyPath, args);

                cmd.description = "converting to hex: " + FileInfo.fileName(input.filePath);
                cmd.highlight = "linker";
                return cmd;
            }
        }

        // To flash:

        // nrfjprog --reset --program $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

    }
}

Upvotes: 3

Related Questions