Build/Core/project.lua

527 lines
18 KiB
Lua

local buildHooks = require("Core/BuildHooks")
local targetingCmake = false
local targetingWindows = os.host() == "windows"
local bugHack = targetingCmake or targetingWindows
local kPathPrefix = "!"
local function configureProjectForSolution(prj)
auFilter(auFilterConfig(Aurora.Settings.sNameOfDebug))
defines { "DEBUG" }
if (Aurora.Settings.bIsBuildDirWd) then
debugdir(Aurora.Settings.sAbsDebug)
end
flags "NoIncrementalLink"
auFilter {}
auFilter(auFilterConfig({Aurora.Settings.sNameOfInternal, Aurora.Settings.sNameOfShip}))
defines { "NDEBUG" }
optimize "Speed"
auFilter {}
auFilter(auFilterConfig(Aurora.Settings.sNameOfInternal))
defines { "STAGING" }
if (Aurora.Settings.bIsBuildDirWd) then
debugdir(Aurora.Settings.sAbsStage)
end
flags "NoIncrementalLink"
auFilter {}
auFilter(auFilterConfig(Aurora.Settings.sNameOfShip))
defines { "SHIP" }
if (Aurora.Settings.bIsBuildDirWd) then
debugdir(Aurora.Settings.sAbsShip)
end
if (Aurora.Settings.bIsShipLTOByDefault) then
flags "LinkTimeOptimization"
end
auFilter {}
local function setTargetDir(id)
local name = Aurora.Settings["sNameOf" .. id]
auFilter(auFilterConfig(name))
defines("AU_CFG_ID_" .. (id:upper()))
local path = Aurora.Settings.sAbsCompilerWd .. "/Bin/" .. name
if (Aurora.Settings.bSplitTargetDirByArch) then
path = path .. "/%{cfg.architecture}"
end
targetdir(path)
auFilter{}
end
setTargetDir("Debug")
setTargetDir("Internal")
setTargetDir("Ship")
auFilterForConfigPlatforms(function(config, platformName, arch)
local platform = Aurora.Platforms[platformName]
if (Aurora.Settings.bDefinePartialABIInTargetName) then
targetname(string.format("%s.%s.%s.%s", prj.name, config, platform.outputName, arch))
end
if (not(config == Aurora.Settings.sNameOfShip)) then return end
if (platform.requiresElfStrip and not platform.supportsElfStrip) then
symbols "Off"
end
end)
end
local function setBestDebugDir(dest)
if (not Aurora.Settings.bIsBuildDirWd) then
return
end
if (not dest or dest:starts(kPathPrefix)) then
local append = dest and dest:sub(#kPathPrefix + 1)
if (not append) then append = "" end
filter(auFilterConfig(Aurora.Settings.sNameOfDebug))
debugdir(Aurora.Settings.sAbsDebug .. "/" .. append)
filter(auFilterConfig(Aurora.Settings.sNameOfInternal))
debugdir(Aurora.Settings.sAbsStage .. "/" .. append)
filter(auFilterConfig(Aurora.Settings.sNameOfShip))
debugdir(Aurora.Settings.sAbsShip .. "/" .. append)
filter {}
else
debugdir(auGetRoot() .. dest)
end
end
local function configureProjectForCompiler()
filter {"toolset:msc"}
buildoptions {"-utf-8"}
filter {}
filter {"toolset:msc", "files:**.cpp or files:**.cc or files:**.cxx"}
buildoptions {"/experimental:module-", "/Zc:__cplusplus"}
filter {}
filter {"toolset:clang"}
disablewarnings { "implicit-function-declaration", "deprecated-non-prototype" }
filter {}
filter {"toolset:clang", "files:**.cpp or files:**.cc or files:**.cxx"}
disablewarnings { "dynamic-class-memaccess", "deprecated-this-capture" }
filter {}
filter { "toolset:msc" }
defines {"AURORA_RUNTIME_MEMCMP=__builtin_memcmp"}
defines {"AURORA_RUNTIME_MEMCMP_=1"}
filter {}
filter { "toolset:clang" }
defines {"AURORA_RUNTIME_MEMSET=__builtin_memset"}
defines {"AURORA_RUNTIME_MEMCPY=__builtin_memcpy"}
defines {"AURORA_RUNTIME_MEMCMP=__builtin_memcmp"}
defines {"AURORA_RUNTIME_MEMSET_=1"}
defines {"AURORA_RUNTIME_MEMCPY_=1"}
defines {"AURORA_RUNTIME_MEMCMP_=1"}
filter {}
end
local function configureProjectForPlatform(platform, projectType)
if (platform == "linux") then
if (Aurora.Settings.bStaticRuntime) then
buildoptions "-static"
linkoptions "-l:libc++abi.a"
linkoptions "-l:libc++.a"
linkoptions "-Wl,--as-needed"
end
end
if (platform == "win32") then
characterset(Aurora.Settings.sMsvcDefCharset)
if (Aurora.Settings.bStaticRuntime) then
staticruntime("On")
links "libucrt.lib"
else
staticruntime("Off")
end
if (not Aurora.Settings.bBasicMitigations) then
flags "NoBufferSecurityCheck"
end
defines "_CRT_SECURE_NO_WARNINGS"
filter {"toolset:msc"}
if (not Aurora.Settings.bBasicMitigations) then
buildoptions {
--"/GS-",
"/sdl-"
}
end
if (Aurora.Settings.bHotswap) then
justmycode("On")
else
justmycode("Off")
end
filter {}
else
if ((projectType == "SharedLib") or
(projectType == "StaticLib")) then
pic "On"
end
end
end
local function configureProjectForPlatforms(projType)
auFilterForPlatforms(function(platformName)
configureProjectForPlatform(platformName, projType)
end)
end
local function configureProjectCPUTarget()
filter { "toolset:msc", "architecture:x86_64"}
buildoptions { "/arch:AVX" }
filter {}
filter { "toolset:clang", "architecture:x86_64"}
-- Some discount VPSes might be running on this dead architecture
-- Haswell introduced AVX2.
-- clang cpu levels: x86_64-v4 contains meme avx512 instructions and beyond, x86_64-v3 includes AVX1+2, x86_64-v2 doesn't have any AVX whatsoever.
-- Dunno if intentional because SSE4.1 >= AVX, but either way, let's get some modern CPU features in an otherwise widely supported binary.
-- Lets sit between v2 and v3 by a single intel generation.
buildoptions { "-march=ivybridge", "-maes" }
filter {}
filter { "toolset:clang", "architecture:x86"}
-- Let Linux x86_32 support Intel Core+ (2006) CPUs
buildoptions { "-march=core2" }
filter {}
end
local function configureProjectErrors()
if (not Aurora.Settings.bDisableWarningsThatAnnoyRec) then
return
end
filter {"toolset:clang"}
buildoptions {"-fms-extensions"}
--buildoptions {"-fevolatile:ms"}
-- The fucking retard cunts behind clang acknowledge there's a 2x slowdown here.
-- Not only that, GCC optimize("no-stack-protector") is broken (ive tried other attributes), their ms stack guard check doesnt do anything,
-- and there are reports that enabling sanitization actually exposes side channel attacks. thanks freetards. very cool.
-- All this because you dont trust me to not memcpy a fucking user provided blob with a bad length check in the very few places that
-- have any load/stores, in or around the stack, as determined by potentially malicious remote/untrusted user input. Even worse, I've seen
-- what should be nothing more than leaf functions doing atomic bit tests and sets get infected with these shitty checks. Meanwhile llvm
-- devs are bitching that "NoOoo you're right, this is a bug, LTO shouldn't be stripping stack checks". Even when the compiler knows
-- the stack isnt being accessed and there's no control flow out of its' reach, these moron compiler devs are obsessed with injecting
-- their shit checks that wont catch any real exploit chain. I'm so fucking sick of these retard security grifters hung up on "MUH OBERFLOWS"
-- "MUH SAFE LANGS" without being able to define what the fuck their attack vector is or how it's going to be exploited. If we cared about
-- overflow checks, then we'd have mimalloc running in secure mode.
-- Once again these twats are 20 years behind commercial alternatives, and that's with infinite apple buxs.
-- If anything happens because of this, i hope somebody burns down a house of a freetard or llvm dev, and shits on their doormat during the escape.
if (not Aurora.Settings.bClangIsNoLongerAPieceOfShitCompiler) then
buildoptions {"-fno-sanitize=all"}
buildoptions {"-fno-stack-protector"}
end
disablewarnings
{
-- we live life on the edge
"unused-result",
-- warning: unused unused enumeration
"unused-value",
-- :(
"unknown-warning-option"
}
filter {}
if (targetingCmake) then
filter {"toolset:msc"}
end
if (bugHack) then
disablewarnings
{
"4996", -- The whiny C99 is no longer supported nag
-- please needlessly use '_s' and '_'d functions __error__
"4251", -- MSVC's hurrdurr abis will break if you dynamically link classes
-- counter: sod off again. we have full control of the build process, and we only link against
-- dynamic c/stl runtimes. which brainlet thought this was a good idea?
-- even microsofts own documentation doesn't state what is guaranteed to be safe.
-- dont mix optimizations, mitigation flags, and so on.
-- rtti works; the stl doesn't abuse inline/module specific globals; who cares?
"4244" -- conversion from 'double' to 'float', possible loss of data
-- this warning is extremely important; however, we're developing a game engine and utilities
-- pragma warning push + disable + pop and/or static_casts to hint we expect floating point precision
-- loss is extremely annoying and impractical. further, projects including harfbuzz, freetype,
-- and v8 don't seem to care about this warning either
}
end
filter {}
end
local function configureProjectForDebug(prj)
local debugDir = nil
if (not Aurora.Settings.bIsBuildDirWd) then
debugdir(Aurora.Settings.sAbsWd)
return
end
if (type(prj.dest) == "string") then
debugDir = prj.dest
end
if (type(prj.dest) == "table") then
debugDir = prj.dest[1]
end
setBestDebugDir(debugDir)
end
local function configureProjectForTarget()
auRequire("Core/Target").startProject()
end
local function configureProjectForLd(prj)
-- I'm not going to deal with this argument
--
-- I don't care for the opinions of greybeards who are stuck in the opinions put forth by AT&Ts meme of an OS
-- In *NIX land, you have +X, use it. I don't want to hear about how operating systems that have more aggressive
-- executable policies than macos and windows, with their vast ecosystem of file system sandboxing extensions,
-- can't cope with loosely following the intentions of the NT loader for the sake of uniformity across platforms.
--
-- https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-desktop-applications
--
-- inb4 LD_LIBRARY_PATH screeching as if users should be expected to mess around with env vars before launching
-- each application. no, just no.
--
-- inb4 muh security. A malcious dependency injection would be the product of a hostile manipulation of the accessible
-- file system files and/or directories. Both are systematic issues we aren't going to make a dent in. The latter being
-- the fundamental issue your administrators should be focused on mitigating; sandbox all apps that could perform hostile IO.
-- If an attacker can write a malicious module or system lib proxy somewhere, you've failed basic attack mitigation,
-- and you're going to be pwned on non-POSIX targets no matter what.
-- Elevation exploits shouldn't be a problem so long as the linkoptions order is maintained so that $origin and then
-- system libraries are considered before any malcious user-installed libraries could possibly be loaded.
-- If you're running a broken arse system with missing protected libraries and you run software as write-level groups,
-- you have bigger issues than my 'lets treat POSIX systems more like NT for cross-compatibility and sanity' assumption.
-- If you're worried about ld.so running unsigned code, go complain to glibc iq-lets who maintain ld.so and force them
-- into developing actual .text and .rodata signature validation with respect to a global root-writable certificate,
-- instead of spreading the ball of responsiblity like hot-fucking-potato in a game of respecting the UNIX :tm: way
-- of doing things (eg: expecting the user to know how to lockdown vendor supplied packages, RO all LD_LIBRARY_PATHs
-- and other undocumented vendor paths, and do god knows what to harden specific softwares dumped without thought
-- across an arahic FHS/XDG tree, all the while developers do jack shit to improve stability, maintainablity, and security).
--
-- Change my mind (without parroting what some dude said on some forum over a decade ago)
-- Don't like it? Disable: Aurora.Settings.bForceWin32EscLd
if (prj.projectType ~= "SharedLib" and
prj.projectType ~= "WindowedApp" and
prj.projectType ~= "ConsoleApp") then
return
end
if (not Aurora.Settings.bForceWin32EscLd) then
return
end
auFilterForConfigPlatforms(function(config, platformName, arch)
local platform = Aurora.Platforms[platformName]
if (not platform) then
return
end
if (not platform.elfSupportsRPath) then
return
end
linkoptions { "-Wl,-rpath,'$$ORIGIN'",
"-Wl,-rpath,'/lib'" }
if (arch == "x86_64" or arch == "arm") then
linkoptions { "-Wl,-rpath,'/lib64'" }
elseif (arch == "x86_32") then
linkoptions { "-Wl,-rpath,'/lib32'" }
end
linkoptions { "-Wl,-rpath,'/usr/lib'" }
if (arch == "x86_64" or arch == "arm") then
linkoptions { "-Wl,-rpath,'/usr/lib64'" }
elseif (arch == "x86_32") then
linkoptions { "-Wl,-rpath,'/usr/lib32'" }
end
linkoptions { "-Wl,-rpath,'.'" }
linkoptions { "-Wl,-rpath,'/usr/local/lib'" }
if (arch == "x86_64" or arch == "arm") then
linkoptions { "-Wl,-rpath,'/usr/local/lib64'" }
elseif (arch == "x86_32") then
linkoptions { "-Wl,-rpath,'/usr/local/lib32'" }
end
end)
end
local function processorDispatchRun(processor)
processor:process()
-- TODO: m4/protobuf/etc support
end
local function processorTranslateDep(this, dep)
if (not this._info.translations) then
return dep
end
local override = this._info.translations[dep]
if (override) then
return override
end
return dep
end
local function processorGetInfo(this)
return this._info
end
local function expendBaseProcessor(prj)
prj.processor._info = prj.info
prj.processor.dispatch = processorDispatchRun
prj.processor.translateDep = processorTranslateDep
prj.processor.getInfo = processorGetInfo
prj.processor.getMeta = processorGetInfo
end
local function setupProject(prj)
print("project", prj.name)
project(prj.name)
language("C++") -- C and MASM drivers are still available to files requiring different compilers
justmycode("Off") -- HACK: default off
targetname(prj.name) -- TODO (reece): you know what to do
kind(prj.projectType)
cppdialect(Aurora.Settings.sCppVersion)
targetprefix(Aurora.Settings.sLibPrefix)
objdir(Aurora.Settings.sAbsCompilerWd .. "/" .. prj.name .. "/%{cfg.architecture}")
configureProjectForSolution(prj)
configureProjectErrors()
configureProjectForCompiler()
configureProjectCPUTarget()
configureProjectForPlatforms(prj.projectType)
configureProjectForTarget()
configureProjectForDebug(prj)
configureProjectForLd(prj)
defines "_AU_HAS_ATOMIC_INTRINS"
defines("_AU_BUILDING_" .. string.upper(prj.projectType))
if (prj.root) then
location(prj.root)
else
location(os.getcwd())
end
defines
{
"_ITERATOR_DEBUG_LEVEL=0",
}
if (Aurora.Settings.bIncludeAuIncludeIfExists) then
local commonInclude = Aurora.Settings.sAbsRootInclude
if (os.isdir(commonInclude)) then
includedirs(commonInclude)
files(commonInclude .. "/**.h*")
end
end
-- add includes, if available
auForEach(prj.inc, function(path)
print("", "include", _G.path.normalize(path))
includedirs(path)
files(path .. "/**.h")
files(path .. "/**.hpp")
files(path .. "/**.inl")
files(path .. "/**.inc")
files(path .. "/**.ipp")
end)
-- add sources, if available
auForEach(prj.src, function(path, root)
print("", "source", _G.path.normalize(path))
--if (string.sub(path, -2) == ".*") then
if (string.find(path, "*")) then
files {path}
return
end
if (os.isfile(path)) then
files {path}
return
end
if (not root) then
includedirs(path)
end
files
{
path .. "/**.*pp",
path .. "/**.inl",
path .. "/**.inc",
path .. "/**.c",
path .. "/**.cc",
path .. "/**.cxx",
path .. "/**.h",
path .. "/**.asm",
path .. "/**.masm" -- required explicitly
}
end, root)
buildHooks.startProject(prj.name, prj.projectType)
auForEach(prj.dest, function(v)
buildHooks.addDest(prj.name, prj.projectType, v)
end)
print()
end
local function setupProjectCompat(name, projectType, src, inc, dest, root)
local project =
{
name = name,
projectType = projectType,
src = src,
inc = inc,
dest = dest,
root = root
}
setupProject(project)
end
return
{
expendBaseProcessor = expendBaseProcessor,
setupProjectCompat = setupProjectCompat,
startProject = setupProject
}