ReGameDLL_CS/regamedll/build.gradle
2019-09-04 04:56:45 +07:00

426 lines
12 KiB
Groovy

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 + ')';
}
}