import gradlecpp.RegamedllPlayTestPlugin import gradlecpp.RegamedllPlayTestTask import gradlecpp.VelocityUtils import org.doomedsociety.gradlecpp.GradleCppUtils import org.doomedsociety.gradlecpp.LazyNativeDepSet import org.doomedsociety.gradlecpp.cfg.ToolchainConfig import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig import org.doomedsociety.gradlecpp.msvc.EnhancedInstructionsSet import org.doomedsociety.gradlecpp.msvc.FloatingPointModel import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig import org.doomedsociety.gradlecpp.toolchain.icc.Icc import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin import org.gradle.language.cpp.CppSourceSet import org.gradle.nativeplatform.NativeBinarySpec import org.gradle.nativeplatform.NativeExecutableSpec import org.gradle.nativeplatform.NativeLibrarySpec import org.gradle.nativeplatform.SharedLibraryBinarySpec import regamedll.testdemo.RegamedllDemoRunner import versioning.RegamedllVersionInfo import org.apache.commons.io.FilenameUtils import org.apache.commons.compress.archivers.ArchiveInputStream apply plugin: 'cpp' apply plugin: IccCompilerPlugin apply plugin: GccCompilerPlugin apply plugin: RegamedllPlayTestPlugin apply plugin: gradlecpp.CppUnitTestPlugin repositories { maven { url 'http://nexus.rehlds.org/nexus/content/repositories/regamedll-releases/' } } configurations { regamedll_tests } dependencies { regamedll_tests 'regamedll.testdemos:cstrike-basic:1.0' } project.ext.dep_cppunitlite = project(':dep/cppunitlite') void createIntergrationTestTask(NativeBinarySpec b) { boolean regamedllFixes = b.flavor.name.contains('regamedllFixes') if (!(b instanceof SharedLibraryBinarySpec)) return if (!GradleCppUtils.windows) return if (regamedllFixes) return String unitTestTask = b.hasProperty('cppUnitTestTask') ? b.cppUnitTestTask : null def demoItgTestTask = project.tasks.create(b.namingScheme.getTaskName('demoItgTest'), RegamedllPlayTestTask) demoItgTestTask.with { regamedllImageRoot = new File(project.projectDir, '_regamedllTestImg') regamedllTestLogs = new File(this.project.buildDir, "_regamedllTestLogs/${b.name}") testDemos = project.configurations.regamedll_tests testFor = b // inputs/outputs for up-to-date check inputs.files testDemos.files outputs.dir regamedllTestLogs // dependencies on test executable if (unitTestTask) { dependsOn unitTestTask } postExtractAction { def binaryOutFile = GradleCppUtils.getBinaryOutputFile(b) def binaryOutDir = new File(project.projectDir, '/_regamedllTestImg/cstrike/dlls') GradleCppUtils.copyFile(binaryOutFile, new File(binaryOutDir, binaryOutFile.name), true) } } b.buildTask.dependsOn demoItgTestTask } void postEvaluate(NativeBinarySpec b) { // attach generateAppVersion task to all 'compile source' tasks GradleCppUtils.getCompileTasks(b).each { Task t -> t.dependsOn project.generateAppVersion } createIntergrationTestTask(b) } void setupToolchain(NativeBinarySpec b) { boolean useGcc = project.hasProperty("useGcc") boolean unitTestExecutable = b.component.name.endsWith('_tests') boolean regamedllFixes = b.flavor.name.contains('regamedllFixes') ToolchainConfig cfg = rootProject.createToolchainConfig(b) cfg.projectInclude(project, '', '/engine', '/common', '/dlls', '/game_shared', '/pm_shared', '/regamedll', '/public', '/public/regamedll') if (unitTestExecutable) { cfg.projectInclude(dep_cppunitlite, '/include') b.lib LazyNativeDepSet.create(dep_cppunitlite, 'cppunitlite', b.buildType.name, true) } cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'REGAMEDLL_SELF', 'REGAMEDLL_API', 'CLIENT_WEAPONS', 'USE_QSTRING' if (cfg instanceof MsvcToolchainConfig) { cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig( enabled: true, pchHeader: 'precompiled.h', pchSourceSet: 'regamedll_pch' ); cfg.singleDefines('_CRT_SECURE_NO_WARNINGS') if (!regamedllFixes) { cfg.compilerOptions.floatingPointModel = FloatingPointModel.PRECISE cfg.compilerOptions.enhancedInstructionsSet = EnhancedInstructionsSet.DISABLED } else { cfg.compilerOptions.args '/Oi', '/GF', '/GS-', '/GR-' } cfg.projectLibpath(project, '/lib') cfg.extraLibs 'libacof32.lib' } else if (cfg instanceof GccToolchainConfig) { if (!useGcc) { cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions( enabled: true, pchSourceSet: 'regamedll_pch' ); } cfg.compilerOptions.languageStandard = 'c++14' cfg.defines([ '_stricmp': 'strcasecmp', '_strnicmp': 'strncasecmp', '_strdup': 'strdup', '_unlink': 'unlink', '_vsnprintf': 'vsnprintf', '_write' : 'write', '_close' : 'close', '_vsnwprintf' : 'vswprintf', '_access' : 'access' ]) if (useGcc) { // Produce code optimized for the most common IA32/AMD64/EM64T processors. // As new processors are deployed in the marketplace, the behavior of this option will change. cfg.compilerOptions.args '-mtune=generic', '-msse3', '-Wno-write-strings', '-Wno-invalid-offsetof', '-fpermissive', '-fno-devirtualize' } else { cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp' // Not use c++ class hierarchy for analyze and resolve C++ virtual function calls at compile time. // // Example issue: // Expected: FF .. call dword ptr + offset, pEntity->Spawn(); // Got: E8 .. call CBaseEntity::Spawn(); cfg.linkerOptions.args '-qno-opt-class-analysis' } if (cfg.linkerOptions.staticLibStdCpp) { cfg.singleDefines 'BUILD_STATIC_LIBSTDC' } cfg.compilerOptions.args '-g0', '-fno-rtti', '-fno-exceptions' cfg.projectLibpath(project, '/lib/linux32') cfg.extraLibs 'dl', 'm', 'aelf32' } if (GradleCppUtils.windows && !unitTestExecutable) { cfg.linkerOptions.definitionFile = "${projectDir}\\msvc\\mp.def"; } if (unitTestExecutable) { cfg.singleDefines 'REGAMEDLL_UNIT_TESTS' } if (regamedllFixes) { cfg.singleDefines 'REGAMEDLL_FIXES', 'BUILD_LATEST', 'BUILD_LATEST_FIXES', 'REGAMEDLL_CHECKS', 'REGAMEDLL_ADD', 'UNICODE_FIXES', 'NDEBUG' } else { cfg.singleDefines 'PLAY_GAMEDLL' } ToolchainConfigUtils.apply(project, cfg, b) GradleCppUtils.onTasksCreated(project, 'postEvaluate', { postEvaluate(b) }) } class RegamedllSrc { static void regamedll_src(def h) { h.engine_src(CppSourceSet) { source { srcDir "engine" include "unicode_strtools.cpp" } } h.shared_src(CppSourceSet) { source { srcDirs "game_shared", "pm_shared", "regamedll", "public", "version" include "**/*.cpp" exclude "precompiled.cpp" exclude "tier0/dbg.cpp", "utlsymbol.cpp", "utlbuffer.cpp" if (GradleCppUtils.windows) { exclude "tier0/platform_linux.cpp" } else { exclude "tier0/platform_win32.cpp" exclude "classes_dummy.cpp" } } } h.gamedll_src(CppSourceSet) { source { srcDirs "dlls", "dlls/API", "dlls/addons" include "**/*.cpp" } } } static void regamedll_pch(def h) { h.regamedll_pch(CppSourceSet) { source { srcDir "regamedll" include "precompiled.cpp" } } } static void regamedll_tests_gcc_src(def h) { h.regamedll_tests_gcc_src(CppSourceSet) { source { srcDir "unittests" include "**/*.cpp" exclude "mathfun_tests.cpp" } } } static void regamedll_tests_src(def h) { h.regamedll_tests_src(CppSourceSet) { source { srcDir "unittests" include "**/*.cpp" } } } } model { buildTypes { debug release } platforms { x86 { architecture "x86" } } toolChains { visualCpp(VisualCpp) { } if (project.hasProperty("useGcc")) { gcc(Gcc) } else { icc(Icc) } } flavors { regamedllNofixes regamedllFixes } components { regamedll_mp_gamedll(NativeLibrarySpec) { targetPlatform 'x86' baseName GradleCppUtils.windows ? 'mp' : 'cs' sources { RegamedllSrc.regamedll_pch(it) RegamedllSrc.regamedll_src(it) } binaries.all { NativeBinarySpec b -> project.setupToolchain(b) } } regamedll_mp_gamedll_tests(NativeExecutableSpec) { targetPlatform 'x86' sources { RegamedllSrc.regamedll_pch(it) RegamedllSrc.regamedll_src(it) if (project.hasProperty("useGcc")) { RegamedllSrc.regamedll_tests_gcc_src(it) } else { RegamedllSrc.regamedll_tests_src(it) } } binaries.all { NativeBinarySpec b -> project.setupToolchain(b) } } } } task buildFinalize << { if (GradleCppUtils.windows) { return; } binaries.withType(SharedLibraryBinarySpec) { def sharedBinary = it.getSharedLibraryFile(); if (sharedBinary.exists()) { sharedBinary.renameTo(new File(sharedBinary.getParent() + "/" + sharedBinary.getName().replaceFirst("^lib", ""))); } } } task buildRelease { dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib -> blib.buildable && blib.buildType.name == 'release' } } task buildFixes { dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib -> blib.buildable && blib.buildType.name == 'release' && blib.flavor.name == 'regamedllFixes' && blib.component.name == 'regamedll_mp_gamedll' } } buildFixes.finalizedBy(buildFinalize); buildRelease.finalizedBy(buildFinalize); gradle.taskGraph.whenReady { graph -> if (!graph.hasTask(buildFixes)) { return; } // skip all tasks with the matched substrings in the name like "test" def tasks = graph.getAllTasks(); tasks.findAll { it.name.toLowerCase().contains("test") }.each { task -> task.enabled = false; } } task prepareDevEnvTests { def regamedllTests = new File(project.projectDir, '_dev/testDemos') inputs.files configurations.regamedll_tests.files outputs.dir regamedllTests doLast { regamedllTests.mkdirs() configurations.regamedll_tests.files.each { File f -> def t = zipTree(f) copy { into new File(regamedllTests, FilenameUtils.getBaseName(f.absolutePath)) from t } } } } task prepareDevEnvGamedll << { ['_dev/regamedll', '_dev/regamedll_mp'].each { gamedllDir -> def regamedllImage = new File(project.projectDir, gamedllDir) regamedllImage.mkdirs() def demoRunner = new RegamedllDemoRunner(project.configurations.regamedll_playtest_image.getFiles(), regamedllImage, null) demoRunner.prepareEngine() //demoRunner.prepareDemo() } } task prepareDevEnv { dependsOn prepareDevEnvGamedll, prepareDevEnvTests } tasks.clean.doLast { project.file('version/appversion.h').delete() } task generateAppVersion { RegamedllVersionInfo verInfo = (RegamedllVersionInfo) rootProject.regamedllVersionInfo def tplFile = project.file('version/appversion.vm') def renderedFile = project.file('version/appversion.h') // check to up-to-date inputs.file tplFile inputs.file project.file('gradle.properties') outputs.file renderedFile // this will ensure that this task is redone when the versions change inputs.property('version', rootProject.version) inputs.property('commitDate', verInfo.asCommitDate()) println "##teamcity[buildNumber '" + verInfo.asMavenVersion(false) + "']"; doLast { def templateCtx = [ verInfo: verInfo ] def content = VelocityUtils.renderTemplate(tplFile, templateCtx) renderedFile.delete() renderedFile.write(content, 'utf-8') println 'The current ReGameDLL maven version is ' + rootProject.version + ', url: (' + verInfo.commitURL + '' + verInfo.commitSHA + ')'; } }