// These add the nilibraries shared library to the linker args def niLibraryPath = file('ni-libraries').path def niLibrary = niLibraryPath + "/libnilibraries.so" task downloadArmNetworkTables() { description = 'Downloads the C++ ARM NetworkTables maven dependency.' group = 'WPILib' def depFolder = "$buildDir/dependencies" def ntZip = file("$depFolder/ntcore-arm.zip") outputs.file(ntZip) def armNetTables doFirst { def armNtDependency = project.dependencies.create('edu.wpi.first.wpilib.networktables.cpp:NetworkTables:+:arm@zip') def armConfig = project.configurations.detachedConfiguration(armNtDependency) armConfig.setTransitive(false) armNetTables = armConfig.files[0].canonicalFile } doLast { copy { from armNetTables rename 'NetworkTables(.+)', 'ntcore-arm.zip' into depFolder } } } if (project.hasProperty('makeSim')) { task downloadDesktopNetworkTables() { description = 'Downloads the C++ Desktop NetworkTables maven dependency.' group = 'WPILib' def depFolder = "$buildDir/dependencies" def ntZip = file("$depFolder/ntcore-desk.zip") outputs.file(ntZip) def desktopNetTables doFirst { def desktopNtDependency = project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:+:desktop@zip") def desktopConfig = project.configurations.detachedConfiguration(desktopNtDependency) desktopConfig.setTransitive(false) desktopNetTables = desktopConfig.files[0].canonicalFile } doLast { copy { from desktopNetTables rename 'NetworkTables(.+)', 'ntcore-desk.zip' into depFolder } } } } def netTablesUnzipLocation = "$buildDir/networktables" // Create a task that will unzip the networktables files into a temporary build directory task unzipNetworkTables(type: Copy) { description = 'Unzips the networktables maven dependency so that the include files and libraries can be used' group = 'WPILib' dependsOn downloadArmNetworkTables if (project.hasProperty('makeSim')) { dependsOn downloadDesktopNetworkTables from zipTree(downloadDesktopNetworkTables.outputs.files.singleFile) } from zipTree(downloadArmNetworkTables.outputs.files.singleFile) into netTablesUnzipLocation } task downloadArmWpiUtil() { description = 'Downloads the C++ ARM wpiutil maven dependency.' group = 'WPILib' def depFolder = "$buildDir/dependencies" def utilZip = file("$depFolder/wpiutil-arm.zip") outputs.file(utilZip) def armWpiUtil doFirst { def armWpiUtilDependency = project.dependencies.create("edu.wpi.first.wpilib:wpiutil:+:arm@zip") def armWpiUtilConfig = project.configurations.detachedConfiguration(armWpiUtilDependency) armWpiUtilConfig.setTransitive(false) armWpiUtil = armWpiUtilConfig.files[0].canonicalFile } doLast { copy { from armWpiUtil rename 'wpiutil(.+)', 'wpiutil-arm.zip' into depFolder } } } if (project.hasProperty('makeSim')) { task downloadDesktopWpiUtil() { description = 'Downloads the C++ Desktop wpiutil maven dependency.' group = 'WPILib' def depFolder = "$buildDir/dependencies" def wpiutilZip = file("$depFolder/wpiutil-desk.zip") outputs.file(wpiutilZip) def wpiUtil doFirst { def desktopWpiUtilDependency = project.dependencies.create("edu.wpi.first.wpilib:wpiutil:+:desktop@zip") def desktopWpiUtilConfig = project.configurations.detachedConfiguration(desktopWpiUtilDependency) desktopWpiUtilConfig.setTransitive(false) wpiUtil = desktopWpiUtilConfig.files[0].canonicalFile } doLast { copy { from wpiUtil rename 'wpiutil(.+)', 'wpiutil-desk.zip' into depFolder } } } } def wpiUtilUnzipLocation = "$buildDir/wpiutil" // Create a task that will unzip the wpiutil files into a temporary build directory task unzipWpiUtil(type: Copy) { description = 'Unzips the wpiutil maven dependency so that the include files and libraries can be used' group = 'WPILib' dependsOn downloadArmWpiUtil if (project.hasProperty('makeSim')) { dependsOn downloadDesktopWpiUtil from zipTree(downloadDesktopWpiUtil.outputs.files.singleFile) } from zipTree(downloadArmWpiUtil.outputs.files.singleFile) into wpiUtilUnzipLocation } task clean(type: Delete) { description = "Deletes the build directory" group = "Build" delete buildDir } subprojects { ext.defineWpiUtilProperties = { ext.wpiUtil = wpiUtilUnzipLocation ext.wpiUtilInclude = "$wpiUtilUnzipLocation/include" ext.wpiUtilLibArmLocation = "$wpiUtilUnzipLocation/Linux/arm" if (project.hasProperty('makeSim')) { ext.wpiUtilLibDesktopLocation = "$wpiUtilUnzipLocation/Linux/amd64" } ext.wpiUtilSharedLib = "$wpiUtilLibArmLocation/libwpiutil.so" ext.wpiUtilSharedLibDebug = "$wpiUtilLibArmLocation/libwpiutil.so.debug" ext.wpiUtilStaticLib = "$wpiUtilLibArmLocation/libwpiutil.a" ext.addWpiUtilLibraryLinks = { compileTask, linker, targetPlatform -> compileTask.dependsOn project(':').unzipWpiUtil String architecture = targetPlatform.architecture if (architecture.contains('arm')) { linker.args wpiUtilSharedLib } } ext.addStaticWpiUtilLibraryLinks = { compileTask, linker, targetPlatform -> compileTask.dependsOn project(':').unzipWpiUtil String architecture = targetPlatform.architecture if (architecture.contains('arm')) { linker.args wpiUtilStaticLib } } } // This defines a project property that projects depending on network tables can use to setup that dependency. ext.defineNetworkTablesProperties = { ext.netTables = netTablesUnzipLocation ext.netTablesInclude = "$netTablesUnzipLocation/include" ext.netLibArmLocation = "$netTablesUnzipLocation/Linux/arm" if (project.hasProperty('makeSim')) { ext.netLibDesktopLocation = "$netTablesUnzipLocation/Linux/amd64" } ext.netSharedLib = "$netLibArmLocation/libntcore.so" ext.netSharedLibDebug = "$netLibArmLocation/libntcore.so.debug" ext.netStaticLib = "$netLibArmLocation/libntcore.a" ext.addNetworkTablesLibraryLinks = { compileTask, linker, targetPlatform -> compileTask.dependsOn project(':').unzipNetworkTables String architecture = targetPlatform.architecture if (architecture.contains('arm')) { linker.args netSharedLib } addWpiUtilLibraryLinks(compileTask, linker, targetPlatform) } ext.addStaticNetworkTablesLibraryLinks = { compileTask, linker, targetPlatform -> compileTask.dependsOn project(':').unzipNetworkTables String architecture = targetPlatform.architecture if (architecture.contains('arm')) { linker.args netStaticLib } addStaticWpiUtilLibraryLinks(compileTask, linker, targetPlatform) } } plugins.withType(CppPlugin).whenPluginAdded { // We use a custom-built cross compiler with the prefix arm-frc-linux-gnueabi- // If this ever changes, the prefix will need to be changed here def compilerPrefix = 'arm-frc-linux-gnueabi-' model { buildTypes { debug } // Adds a custom toolchain for our compiler prefix and options toolChains { gcc(Gcc) { target('arm') { cppCompiler.executable = compilerPrefix + cppCompiler.executable linker.executable = compilerPrefix + linker.executable assembler.executable = compilerPrefix + assembler.executable // Gradle auto-adds the -m32 argument to the linker and compiler. Our compiler only supports // arm, and doesn't understand this flag, so it is removed from both cppCompiler.withArguments { args -> args << '-std=c++1y' << '-Wformat=2' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic' args << '-Wno-psabi' << '-Wno-unused-parameter' << '-fPIC' << '-Og' << '-g3' << '-rdynamic' //TODO: When the compiler allows us to actually call deprecated functions from within // deprecated function, remove this line (this will cause calling deprecated functions // to be treated as a warning rather than an error). args << '-Wno-error=deprecated-declarations' args.remove('-m32') } linker.withArguments { args -> args << '-rdynamic' args.remove('-m32') } staticLibArchiver.executable = compilerPrefix + staticLibArchiver.executable } } // Workaround for OS X. Macs for some reason want to use Xcode's gcc // (which just wraps Clang), so we have to explicitly make it so // that trying to compile with Clang will call gcc instead macGcc(Clang) { target('arm') { cppCompiler.executable = compilerPrefix + 'g++' linker.executable = compilerPrefix + 'g++' assembler.executable = compilerPrefix + 'gcc' // Gradle auto-adds the -m32 argument to the linker and compiler. Our compiler only supports // arm, and doesn't understand this flag, so it is removed from both cppCompiler.withArguments { args -> args << '-std=c++1y' << '-Wformat=2' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic' args << '-Wno-psabi' << '-Wno-unused-parameter' << '-fPIC' << '-Og' << '-g3' << '-rdynamic' //TODO: When the compiler allows us to actually call deprecated functions from within // deprecated function, remove this line (this will cause calling deprecated functions // to be treated as a warning rather than an error). args << '-Wno-error=deprecated-declarations' args.remove('-m32') } linker.withArguments { args -> args << '-rdynamic' args.remove('-m32') } staticLibArchiver.executable = compilerPrefix + 'ar' } } } // The only platform is arm linux platforms { arm { architecture 'arm' operatingSystem 'linux' } } } // This task adds the appropriate linker flags for the NI libraries ext.addNiLibraryLinks = { linker, targetPlatform -> String architecture = targetPlatform.architecture if (architecture.contains('arm')){ linker.args << '-L' + niLibraryPath linker.args niLibrary } } // This task sets up the shared libraries to be stripped ext.debugStripSetup = { project-> if (!project.hasProperty('debug')) { project.tasks.whenObjectAdded { task -> def name = task.name.toLowerCase() if (name.contains('link') && name.contains('sharedlibrary')) { def library = task.outputFile.absolutePath def debugLibrary = task.outputFile.absolutePath + ".debug" task.doLast { exec { commandLine "${compilerPrefix}objcopy", '--only-keep-debug', library, debugLibrary } exec { commandLine "${compilerPrefix}strip", '-g', library } exec { commandLine "${compilerPrefix}objcopy", "--add-gnu-debuglink=$debugLibrary", library } } } } } } } }