mirror of https://github.com/FWGS/hlsdk-xash3d
11 changed files with 1646 additions and 0 deletions
@ -0,0 +1,69 @@ |
|||
#! /usr/bin/env python |
|||
# encoding: utf-8 |
|||
# a1batross, mittorn, 2018 |
|||
|
|||
from waflib import Utils |
|||
import os |
|||
|
|||
def options(opt): |
|||
# stub |
|||
return |
|||
|
|||
def configure(conf): |
|||
if conf.env.GOLDSRC: |
|||
if conf.env.DEST_OS != 'win32': |
|||
conf.check_cc(lib='dl') |
|||
|
|||
def build(bld): |
|||
source = bld.path.parent.ant_glob([ |
|||
'pm_shared/*.c', |
|||
'dlls/crossbow.cpp', 'dlls/crowbar.cpp', 'dlls/egon.cpp', 'dlls/gauss.cpp', 'dlls/handgrenade.cpp', |
|||
'dlls/hornetgun.cpp', 'dlls/mp5.cpp', 'dlls/python.cpp', 'dlls/rpg.cpp', 'dlls/satchel.cpp', |
|||
'dlls/shotgun.cpp', 'dlls/squeakgrenade.cpp', 'dlls/tripmine.cpp', 'dlls/glock.cpp' |
|||
]) |
|||
|
|||
source += bld.path.ant_glob(['hl/*.cpp']) |
|||
source += [ |
|||
'ev_hldm.cpp', 'ammo.cpp', 'ammo_secondary.cpp', 'ammohistory.cpp', |
|||
'battery.cpp', 'cdll_int.cpp', 'com_weapons.cpp', 'death.cpp', |
|||
'demo.cpp', 'entity.cpp', 'ev_common.cpp', 'events.cpp', |
|||
'flashlight.cpp', 'GameStudioModelRenderer.cpp', 'geiger.cpp', |
|||
'health.cpp', 'hud.cpp', 'hud_msg.cpp', 'hud_redraw.cpp', |
|||
'hud_spectator.cpp', 'hud_update.cpp', 'in_camera.cpp', |
|||
'input.cpp', 'input_goldsource.cpp', 'input_mouse.cpp', |
|||
'input_xash3d.cpp', 'menu.cpp', 'message.cpp', |
|||
'overview.cpp', 'parsemsg.cpp', 'saytext.cpp', |
|||
'status_icons.cpp', 'statusbar.cpp', 'studio_util.cpp', |
|||
'StudioModelRenderer.cpp', 'text_message.cpp', 'train.cpp', |
|||
'tri.cpp', 'util.cpp', 'view.cpp', 'scoreboard.cpp', 'MOTD.cpp' |
|||
] |
|||
|
|||
includes = Utils.to_list('. hl/ ../dlls ../dlls/wpn_shared ../common ../engine ../pm_shared ../game_shared ../public ../utils/false_vgui/include') |
|||
|
|||
defines = ['CLIENT_DLL'] |
|||
if bld.env.GOLDSRC: |
|||
defines += ['GOLDSOURCE_SUPPORT'] |
|||
|
|||
libs = [] |
|||
if bld.env.GOLDSRC: |
|||
libs += ['DL'] |
|||
|
|||
if bld.env.DEST_OS == 'win32': |
|||
libname = 'client.dll' |
|||
elif bld.env.DEST_OS == 'linux': |
|||
libname = 'client.so' |
|||
elif bld.env.DEST_OS == 'darwin': |
|||
libname = 'client.dylib' |
|||
else: libname = '' |
|||
|
|||
bld.shlib( |
|||
source = source, |
|||
target = 'client', |
|||
features = 'c cxx', |
|||
includes = includes, |
|||
defines = defines, |
|||
use = libs, |
|||
install_path = os.path.join(bld.env.GAMEDIR, bld.env.CLIENT_DIR, libname), |
|||
subsystem = bld.env.MSVC_SUBSYSTEM, |
|||
idx = 1 |
|||
) |
@ -0,0 +1,75 @@ |
|||
#! /usr/bin/env python |
|||
# encoding: utf-8 |
|||
# a1batross, mittorn, 2018 |
|||
|
|||
from waflib import Utils |
|||
import os |
|||
|
|||
def options(opt): |
|||
# stub |
|||
return |
|||
|
|||
def configure(conf): |
|||
# stub |
|||
return |
|||
|
|||
def build(bld): |
|||
defines = [] |
|||
source = bld.path.parent.ant_glob([ |
|||
'pm_shared/*.c', |
|||
]) |
|||
|
|||
source += [ |
|||
'agrunt.cpp', 'airtank.cpp', 'aflock.cpp', 'animating.cpp', 'animation.cpp', 'apache.cpp', |
|||
'barnacle.cpp', 'barney.cpp', 'bigmomma.cpp', 'bloater.cpp', 'bmodels.cpp', 'bullsquid.cpp', 'buttons.cpp', |
|||
'cbase.cpp', 'client.cpp', 'combat.cpp', 'controller.cpp', 'crossbow.cpp', 'crowbar.cpp', |
|||
'defaultai.cpp', 'doors.cpp', |
|||
'effects.cpp', 'egon.cpp', 'explode.cpp', |
|||
'flyingmonster.cpp', 'func_break.cpp', 'func_tank.cpp', |
|||
'game.cpp', 'gamerules.cpp', 'gargantua.cpp', 'gauss.cpp', 'genericmonster.cpp', 'ggrenade.cpp', 'globals.cpp', 'glock.cpp', 'gman.cpp', |
|||
'h_ai.cpp', 'h_battery.cpp', 'h_cine.cpp', 'h_cycler.cpp', 'h_export.cpp', 'handgrenade.cpp', 'hassassin.cpp', 'headcrab.cpp', |
|||
'healthkit.cpp', 'hgrunt.cpp', 'hornet.cpp', 'hornetgun.cpp', 'houndeye.cpp', |
|||
'ichthyosaur.cpp', 'islave.cpp', 'items.cpp', |
|||
'leech.cpp', 'lights.cpp', |
|||
'maprules.cpp', 'monstermaker.cpp', 'monsters.cpp', 'monsterstate.cpp', 'mortar.cpp', 'mp5.cpp', 'multiplay_gamerules.cpp', |
|||
'nihilanth.cpp', 'nodes.cpp', |
|||
'observer.cpp', 'osprey.cpp', |
|||
'pathcorner.cpp', 'plane.cpp', 'plats.cpp', 'player.cpp', 'playermonster.cpp', 'python.cpp', |
|||
'rat.cpp', 'roach.cpp', 'rpg.cpp', |
|||
'satchel.cpp', 'schedule.cpp', 'scientist.cpp', 'scripted.cpp', 'shotgun.cpp', 'singleplay_gamerules.cpp', 'skill.cpp', |
|||
'sound.cpp', 'soundent.cpp', 'spectator.cpp', 'squadmonster.cpp', 'squeakgrenade.cpp', 'subs.cpp', |
|||
'talkmonster.cpp', 'teamplay_gamerules.cpp', 'tempmonster.cpp', 'tentacle.cpp', |
|||
'triggers.cpp', 'tripmine.cpp', 'turret.cpp', |
|||
'util.cpp', |
|||
'weapons.cpp', 'world.cpp', 'xen.cpp', 'zombie.cpp'] |
|||
|
|||
if bld.env.VOICEMGR: |
|||
source += bld.path.parent.ant_glob([ |
|||
'game_shared/voice_gamemgr.cpp', |
|||
]) |
|||
else: |
|||
defines += ['NO_VOICEGAMEMGR'] |
|||
|
|||
includes = Utils.to_list('. wpn_shared ../common ../engine ../pm_shared ../game_shared ../public') |
|||
|
|||
libs = [] |
|||
|
|||
if bld.env.DEST_OS == 'win32': |
|||
libname = bld.env.SERVER_NAME + '.dll' |
|||
elif bld.env.DEST_OS == 'linux': |
|||
libname = bld.env.SERVER_NAME + '.so' |
|||
elif bld.env.DEST_OS == 'darwin': |
|||
libname = bld.env.SERVER_NAME + '.dylib' |
|||
else: libname = '' |
|||
|
|||
bld.shlib( |
|||
source = source, |
|||
target = 'server', |
|||
features = 'c cxx', |
|||
includes = includes, |
|||
defines = defines, |
|||
use = libs, |
|||
install_path = os.path.join(bld.env.GAMEDIR, bld.env.SERVER_DIR, libname), |
|||
subsystem = bld.env.MSVC_SUBSYSTEM, |
|||
idx = 2 |
|||
) |
@ -0,0 +1,65 @@ |
|||
#!/usr/bin/env python |
|||
# -*- encoding: utf-8 -*- |
|||
# Michel Mooij, michel.mooij7@gmail.com |
|||
|
|||
from waflib import Utils |
|||
from waflib import Errors |
|||
|
|||
|
|||
def get_deps(bld, target): |
|||
'''Returns a list of (nested) targets on which this target depends. |
|||
|
|||
:param bld: a *waf* build instance from the top level *wscript* |
|||
:type bld: waflib.Build.BuildContext |
|||
:param target: task name for which the dependencies should be returned |
|||
:type target: str |
|||
:returns: a list of task names on which the given target depends |
|||
''' |
|||
try: |
|||
tgen = bld.get_tgen_by_name(target) |
|||
except Errors.WafError: |
|||
return [] |
|||
else: |
|||
uses = Utils.to_list(getattr(tgen, 'use', [])) |
|||
deps = uses[:] |
|||
for use in uses: |
|||
deps += get_deps(bld, use) |
|||
return list(set(deps)) |
|||
|
|||
|
|||
def get_tgens(bld, names): |
|||
'''Returns a list of task generators based on the given list of task |
|||
generator names. |
|||
|
|||
:param bld: a *waf* build instance from the top level *wscript* |
|||
:type bld: waflib.Build.BuildContext |
|||
:param names: list of task generator names |
|||
:type names: list of str |
|||
:returns: list of task generators |
|||
''' |
|||
tgens=[] |
|||
for name in names: |
|||
try: |
|||
tgen = bld.get_tgen_by_name(name) |
|||
except Errors.WafError: |
|||
pass |
|||
else: |
|||
tgens.append(tgen) |
|||
return list(set(tgens)) |
|||
|
|||
|
|||
def get_targets(bld): |
|||
'''Returns a list of user specified build targets or None if no specific |
|||
build targets has been selected using the *--targets=* command line option. |
|||
|
|||
:param bld: a *waf* build instance from the top level *wscript*. |
|||
:type bld: waflib.Build.BuildContext |
|||
:returns: a list of user specified target names (using --targets=x,y,z) or None |
|||
''' |
|||
if bld.targets == '': |
|||
return None |
|||
targets = bld.targets.split(',') |
|||
for target in targets: |
|||
targets += get_deps(bld, target) |
|||
return targets |
|||
|
@ -0,0 +1,56 @@ |
|||
# encoding: utf-8 |
|||
# force_32bit.py -- force compiler to create 32-bit code |
|||
# Copyright (C) 2018 a1batross |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU General Public License as published by |
|||
# the Free Software Foundation, either version 3 of the License, or |
|||
# (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU General Public License for more details. |
|||
|
|||
from fwgslib import get_flags_by_compiler |
|||
|
|||
# Input: |
|||
# BIT32_MANDATORY(optional) -- fail if 32bit mode not available |
|||
# BIT32_ALLOW64(optional) -- ignore all checks, just set DEST_SIZEOF_VOID_P to 8 |
|||
# Output: |
|||
# DEST_SIZEOF_VOID_P -- an integer, equals sizeof(void*) on target |
|||
|
|||
def check_32bit(ctx, msg): |
|||
try: |
|||
ctx.check_cc( |
|||
fragment='''int main( void ) |
|||
{ |
|||
int check[sizeof(void*) == 4 ? 1: -1]; |
|||
return 0; |
|||
}''', |
|||
msg = msg) |
|||
except ctx.errors.ConfigurationError: |
|||
return False |
|||
return True |
|||
|
|||
def configure(conf): |
|||
if getattr(conf.env, 'BIT32_ALLOW64'): |
|||
conf.env.DEST_SIZEOF_VOID_P = 8 |
|||
else: |
|||
if check_32bit(conf, 'Checking if \'{0}\' can target 32-bit'.format(conf.env.COMPILER_CC)): |
|||
conf.env.DEST_SIZEOF_VOID_P = 4 |
|||
else: |
|||
flags = ['-m32'] |
|||
# Think different. |
|||
if(conf.env.DEST_OS == 'darwin'): |
|||
flags = ['-arch', 'i386'] |
|||
env_stash = conf.env |
|||
conf.env.append_value('LINKFLAGS', flags) |
|||
conf.env.append_value('CFLAGS', flags) |
|||
conf.env.append_value('CXXFLAGS', flags) |
|||
if check_32bit(conf, '...trying with additional flags'): |
|||
conf.env.DEST_SIZEOF_VOID_P = 4 |
|||
else: |
|||
conf.env.DEST_SIZEOF_VOID_P = 8 |
|||
conf.env = env_stash |
|||
if getattr(conf.env, 'BIT32_MANDATORY') and conf.env.DEST_SIZEOF_VOID_P == 8: |
|||
conf.fatal('Compiler can\'t create 32-bit code!') |
@ -0,0 +1,30 @@ |
|||
# encoding: utf-8 |
|||
# fwgslib.py -- utils for Waf build system by FWGS |
|||
# Copyright (C) 2018 a1batross |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU General Public License as published by |
|||
# the Free Software Foundation, either version 3 of the License, or |
|||
# (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU General Public License for more details. |
|||
|
|||
import os |
|||
|
|||
def get_flags_by_compiler(flags, compiler): |
|||
out = [] |
|||
if compiler in flags: |
|||
out += flags[compiler] |
|||
elif 'default' in flags: |
|||
out += flags['default'] |
|||
return out |
|||
|
|||
def get_flags_by_type(flags, type, compiler): |
|||
out = [] |
|||
if 'common' in flags: |
|||
out += get_flags_by_compiler(flags['common'], compiler) |
|||
if type in flags: |
|||
out += get_flags_by_compiler(flags[type], compiler) |
|||
return out |
@ -0,0 +1,774 @@ |
|||
#!/usr/bin/env python |
|||
# -*- encoding: utf-8 -*- |
|||
# Michel Mooij, michel.mooij7@gmail.com |
|||
# modified: Alibek Omarov, a1ba.omarov@gmail.com |
|||
|
|||
''' |
|||
Summary |
|||
------- |
|||
Exports and converts *waf* project data, for C/C++ programs, static- and shared |
|||
libraries, into **Microsoft Visual Studio**, also known as **msdev**, |
|||
project files (.vcproj) and solution (.sln) files. |
|||
|
|||
**Microsoft Visual Studio** is a mature and stable integrated development |
|||
environment for, amongst others, the C and C++ programming language. A free |
|||
version of this IDE, known as the *express* version can be obtained from Microsoft |
|||
at http://wwww.visualstudio.com. |
|||
|
|||
Description |
|||
----------- |
|||
When exporting *waf* project data, a single **Visual Studio** solution will be |
|||
exported in the top level directory of your *WAF* build environment. This |
|||
solution file will contain references to all exported **Visual Studio** |
|||
projects and will include dependencies between those projects and will have the |
|||
same name as APPNAME variable from the top level *wscript* file. |
|||
|
|||
For each single task generator (*waflib.TaskGenerator*), for instance a |
|||
*bld.program(...)* which has been defined within a *wscript* file somewhere in |
|||
the build environment, a single **Visual Studio** project file will be generated |
|||
in the same directory as where the task generator has been defined. |
|||
The name of this task generator will be used as name for the exported **Visual |
|||
Studio** project file. If for instance the name of the task generator is |
|||
*hello*, then a **Visual Studio** project file named *hello.vcproj* will be |
|||
exported. |
|||
|
|||
Example below presents an overview of an environment in which **Visual Studio** |
|||
files already have been exported:: |
|||
|
|||
. |
|||
├── components |
|||
│ └── clib |
|||
│ ├── program |
|||
│ │ ├── cprogram.vcproj |
|||
│ │ └── wscript |
|||
│ ├── shared |
|||
│ │ ├── cshlib.vcproj |
|||
│ │ └── wscript |
|||
│ └── static |
|||
│ ├── cstlib.vcproj |
|||
│ └── wscript |
|||
│ |
|||
├── waf.vcproj |
|||
├── appname.sln |
|||
└── wscript |
|||
|
|||
|
|||
Projects will be exported such that they will use the same settings and |
|||
structure as has been defined for that build task within the *waf* build |
|||
environment as much as possible. Note that since cross compilation is not |
|||
really supported in this IDE, only the first environment encountered that |
|||
is targeted for **MS Windows** will be exported; i.e. an environment in |
|||
which:: |
|||
|
|||
bld.env.DEST_OS == 'win32' |
|||
|
|||
is true. |
|||
|
|||
|
|||
Please note that in contrast to a *normal* IDE setup the exported projects |
|||
will contain either a *debug* **or** a *release* build target but not both at |
|||
the same time. By doing so exported projects will always use the same settings |
|||
(e.g. compiler options, installation paths) as when building the same task in |
|||
the *waf* build environment from command line. |
|||
|
|||
|
|||
Usage |
|||
----- |
|||
**Visual Studio** project and workspace files can be exported using the *msdev* |
|||
command, as shown in the example below:: |
|||
|
|||
$ waf msdev |
|||
|
|||
When needed, exported **Visual Studio** project- and solution files can be |
|||
removed using the *clean* command, as shown in the example below:: |
|||
|
|||
$ waf msdev --clean |
|||
|
|||
Once exported simply open the *appname.sln* using **Visual Studio** |
|||
this will automatically open all exported projects as well. |
|||
|
|||
Tasks generators to be excluded can be marked with the *skipme* option |
|||
as shown below:: |
|||
|
|||
def build(bld): |
|||
bld.program(name='foo', src='foobar.c', msdev_skip=True) |
|||
|
|||
''' |
|||
|
|||
import os |
|||
import sys |
|||
import copy |
|||
import uuid |
|||
import shutil |
|||
import xml.etree.ElementTree as ElementTree |
|||
from xml.dom import minidom |
|||
from waflib import Utils, Logs, Errors, Context |
|||
from waflib.Build import BuildContext |
|||
# import waftools |
|||
# from waftools import deps |
|||
from deps import get_targets |
|||
from subproject import get_subproject_env |
|||
|
|||
|
|||
def options(opt): |
|||
'''Adds command line options to the *waf* build environment |
|||
|
|||
:param opt: Options context from the *waf* build environment. |
|||
:type opt: waflib.Options.OptionsContext |
|||
''' |
|||
opt.add_option('--msdev', dest='msdev', default=False, action='store_true', help='select msdev for export/import actions') |
|||
opt.add_option('--clean', dest='clean', default=False, action='store_true', help='delete exported files') |
|||
|
|||
|
|||
def configure(conf): |
|||
'''Method that will be invoked by *waf* when configuring the build |
|||
environment. |
|||
|
|||
:param conf: Configuration context from the *waf* build environment. |
|||
:type conf: waflib.Configure.ConfigurationContext |
|||
''' |
|||
pass |
|||
|
|||
|
|||
class MsDevContext(BuildContext): |
|||
'''export C/C++ tasks to MS Visual Studio projects and solutions.''' |
|||
cmd = 'msdev' |
|||
|
|||
def execute(self): |
|||
'''Will be invoked when issuing the *msdev* command.''' |
|||
self.restore() |
|||
if not self.all_envs: |
|||
self.load_envs() |
|||
self.recurse([self.run_dir]) |
|||
self.pre_build() |
|||
|
|||
for group in self.groups: |
|||
for tgen in group: |
|||
try: |
|||
f = tgen.post |
|||
except AttributeError: |
|||
pass |
|||
else: |
|||
f() |
|||
try: |
|||
self.get_tgen_by_name('') |
|||
except Exception: |
|||
pass |
|||
|
|||
self.msdev = True |
|||
if self.options.clean: |
|||
cleanup(self) |
|||
else: |
|||
export(self) |
|||
self.timer = Utils.Timer() |
|||
|
|||
def export(bld): |
|||
'''Exports all C and C++ task generators as **Visual Studio** projects |
|||
and creates a **Visual Studio** solution containing references to |
|||
those project. |
|||
|
|||
:param bld: a *waf* build instance from the top level *wscript*. |
|||
:type bld: waflib.Build.BuildContext |
|||
''' |
|||
if not bld.options.msdev and not hasattr(bld, 'msdev'): |
|||
return |
|||
|
|||
Logs.pprint('RED', '''This tool is intended only to ease development for Windows-fags. |
|||
Don't use it for release builds, as it doesn't enables WinXP compatibility for now!''') |
|||
|
|||
solution = MsDevSolution(bld) |
|||
targets = get_targets(bld) |
|||
|
|||
saveenv = bld.env # root env |
|||
for tgen in bld.task_gen_cache_names.values(): |
|||
if targets and tgen.get_name() not in targets: |
|||
continue |
|||
if getattr(tgen, 'msdev_skipme', False): |
|||
continue |
|||
try: |
|||
bld.env = get_subproject_env(bld, tgen.path, True) |
|||
except IndexError: |
|||
bld.env = saveenv |
|||
if set(('c', 'cxx')) & set(getattr(tgen, 'features', [])): |
|||
project = MsDevProject(bld, tgen) |
|||
project.export() |
|||
|
|||
(name, fname, deps, pid) = project.get_metadata() |
|||
solution.add_project(name, fname, deps, pid) |
|||
|
|||
solution.export() |
|||
|
|||
|
|||
def cleanup(bld): |
|||
'''Removes all **Visual Studio** projects and workspaces from the |
|||
*waf* build environment. |
|||
|
|||
:param bld: a *waf* build instance from the top level *wscript*. |
|||
:type bld: waflib.Build.BuildContext |
|||
''' |
|||
if not bld.options.msdev and not hasattr(bld, 'msdev'): |
|||
return |
|||
|
|||
targets = get_targets(bld) |
|||
saveenv = bld.env |
|||
|
|||
for tgen in bld.task_gen_cache_names.values(): |
|||
if targets and tgen.get_name() not in targets: |
|||
continue |
|||
if getattr(tgen, 'msdev_skipme', False): |
|||
continue |
|||
try: |
|||
bld.env = get_subproject_env(bld, tgen.path) |
|||
except IndexError: |
|||
bld.env = saveenv |
|||
if set(('c', 'cxx')) & set(getattr(tgen, 'features', [])): |
|||
project = MsDevProject(bld, tgen) |
|||
project.cleanup() |
|||
|
|||
solution = MsDevSolution(bld) |
|||
solution.cleanup() |
|||
|
|||
|
|||
class MsDev(object): |
|||
'''Abstract base class used for exporting *waf* project data to |
|||
**Visual Studio** projects and solutions. |
|||
|
|||
REMARK: |
|||
bld.objects() taks generators are treated as static libraries. |
|||
|
|||
:param bld: Build context as used in *wscript* files of your *waf* build |
|||
environment. |
|||
:type bld: waflib.Build.BuildContext |
|||
''' |
|||
|
|||
PROGRAM = '1' |
|||
'''Identifier for projects containing an executable''' |
|||
|
|||
SHLIB = '2' |
|||
'''Identifier for projects containing a shared library''' |
|||
|
|||
STLIB = '4' |
|||
'''Identifier for projects containing a static library''' |
|||
|
|||
C = 'c' |
|||
'''Identifier for projects using C language''' |
|||
|
|||
CXX = 'cxx' |
|||
'''Identifier for projects using C++ language''' |
|||
|
|||
def __init__(self, bld): |
|||
self.bld = bld |
|||
|
|||
def export(self): |
|||
'''Exports a **Visual Studio** solution or project.''' |
|||
content = self.get_content() |
|||
if not content: |
|||
return |
|||
if self.xml_clean: |
|||
content = self.xml_clean(content) |
|||
|
|||
node = self.make_node() |
|||
if not node: |
|||
return |
|||
node.write(content) |
|||
Logs.pprint('YELLOW', 'exported: %s' % node.abspath()) |
|||
|
|||
def cleanup(self): |
|||
'''Deletes a **Visual Studio** solution or project file including |
|||
associated files (e.g. *.ncb*). |
|||
''' |
|||
cwd = self.get_cwd() |
|||
for node in cwd.ant_glob('*.user'): |
|||
node.delete() |
|||
Logs.pprint('YELLOW', 'removed: %s' % node.abspath()) |
|||
for node in cwd.ant_glob('*.ncb'): |
|||
node.delete() |
|||
Logs.pprint('YELLOW', 'removed: %s' % node.abspath()) |
|||
for node in cwd.ant_glob('*.suo'): |
|||
node.delete() |
|||
Logs.pprint('YELLOW', 'removed: %s' % node.abspath()) |
|||
for node in cwd.ant_glob('*.sln'): |
|||
node.delete() |
|||
Logs.pprint('YELLOW', 'removed: %s' % node.abspath()) |
|||
node = self.find_node() |
|||
if node: |
|||
node.delete() |
|||
Logs.pprint('YELLOW', 'removed: %s' % node.abspath()) |
|||
|
|||
def get_cwd(self): |
|||
cwd = os.path.dirname(self.get_fname()) |
|||
if cwd == "": |
|||
cwd = "." |
|||
return self.bld.srcnode.find_node(cwd) |
|||
|
|||
def find_node(self): |
|||
name = self.get_fname() |
|||
if not name: |
|||
return None |
|||
return self.bld.srcnode.find_node(name) |
|||
|
|||
def make_node(self): |
|||
name = self.get_fname() |
|||
if not name: |
|||
return None |
|||
return self.bld.srcnode.make_node(name.lower()) |
|||
|
|||
def get_fname(self): |
|||
'''<abstract> Returns file name.''' |
|||
return None |
|||
|
|||
def get_content(self): |
|||
'''<abstract> Returns file content.''' |
|||
return None |
|||
|
|||
def xml_clean(self, content): |
|||
s = minidom.parseString(content).toprettyxml(indent="\t") |
|||
lines = [l for l in s.splitlines() if not l.isspace() and len(l)] |
|||
lines[0] = '<?xml version="1.0" encoding="UTF-8"?>' |
|||
return '\n'.join(lines) |
|||
|
|||
|
|||
class MsDevSolution(MsDev): |
|||
'''Class used for exporting *waf* project data to a **Visual Studio** |
|||
solution located in the lop level directory of the *waf* build |
|||
environment. |
|||
|
|||
:param bld: Build context as used in *wscript* files of your *waf* build |
|||
environment. |
|||
:type bld: waflib.Build.BuildContext |
|||
''' |
|||
|
|||
def __init__(self, bld): |
|||
super(MsDevSolution, self).__init__(bld) |
|||
self.projects = {} |
|||
self.xml_clean = None |
|||
|
|||
def get_fname(self): |
|||
'''Returns the workspace's file name.''' |
|||
return '%s.sln' % getattr(Context.g_module, Context.APPNAME) |
|||
|
|||
def export(self): |
|||
'''Exports a **Visual Studio** solution.''' |
|||
dst = self.get_fname() |
|||
|
|||
s = MSDEV_SOLUTION |
|||
|
|||
with open(dst, 'w') as f: |
|||
for line in s[0:3]: |
|||
f.write(line) |
|||
for name, (fname, deps, pid) in self.projects.items(): |
|||
sid = str(uuid.uuid4()).upper() |
|||
f.write('Project("{%s}") = "%s", "%s", "{%s}"\n' % (sid, name, fname, pid)) |
|||
if len(deps): |
|||
f.write('\tProjectSection(ProjectDependencies) = postProject\n') |
|||
for d in deps: |
|||
try: |
|||
(_, _, pid) = self.projects[d] |
|||
except KeyError: |
|||
pass |
|||
else: |
|||
f.write('\t\t{%s} = {%s}\n' % (pid, pid)) |
|||
f.write('\tEndProjectSection\n') |
|||
f.write('EndProject\n') |
|||
for line in s[3:8]: |
|||
f.write(line) |
|||
for _, (_, _, pid) in self.projects.items(): |
|||
f.write('\t\t{%s}.Debug|Win32.ActiveCfg = Debug|Win32\n' % (pid)) |
|||
f.write('\t\t{%s}.Debug|Win32.Build.0 = Debug|Win32\n' % (pid)) |
|||
for line in s[8:]: |
|||
f.write(line) |
|||
Logs.pprint('YELLOW', 'exported: %s' % os.path.abspath(dst)) |
|||
|
|||
def add_project(self, name, fname, deps, pid): |
|||
'''Adds a project to the workspace. |
|||
|
|||
:param name: Name of the project. |
|||
:type name: str |
|||
:param fname: Complete path to the project file |
|||
:type fname: str |
|||
:param deps: List of names on which this project depends |
|||
:type deps: list of str |
|||
''' |
|||
self.projects[name] = (fname, deps, pid) |
|||
|
|||
|
|||
class MsDevProject(MsDev): |
|||
'''Class used for exporting *waf* project data to **Visual Studio** |
|||
projects. |
|||
|
|||
:param bld: Build context as used in *wscript* files of your *waf* build |
|||
environment. |
|||
:type bld: waflib.Build.BuildContext |
|||
|
|||
:param gen: Task generator that contains all information of the task to be |
|||
converted and exported to the **Visual Studio** project. |
|||
:type gen: waflib.Task.TaskGen |
|||
''' |
|||
|
|||
def __init__(self, bld, gen): |
|||
super(MsDevProject, self).__init__(bld) |
|||
self.gen = gen |
|||
self.id = str(uuid.uuid4()).upper() |
|||
self.type = self.get_type(gen) |
|||
self.language = self.get_language(gen) |
|||
self.buildpath = self.get_buildpath(bld, gen) |
|||
|
|||
def get_type(self, gen): |
|||
if set(('cprogram', 'cxxprogram')) & set(gen.features): |
|||
return MsDev.PROGRAM |
|||
elif set(('cshlib', 'cxxshlib')) & set(gen.features): |
|||
return MsDev.SHLIB |
|||
else: |
|||
return MsDev.STLIB |
|||
|
|||
def get_language(self, gen): |
|||
return MsDev.CXX if 'cxx' in gen.features else MsDev.C |
|||
|
|||
def get_buildpath(self, bld, gen): |
|||
pth = '%s/%s' % (bld.path.get_bld().path_from(gen.path), gen.path.relpath()) |
|||
return pth.replace('/', '\\') |
|||
|
|||
def get_fname(self): |
|||
'''Returns the project's file name.''' |
|||
return '%s/%s.vcproj' % (self.gen.path.relpath().replace('\\', '/'), self.gen.get_name()) |
|||
|
|||
def get_root(self): |
|||
'''Returns a document root, either from an existing file, or from template.''' |
|||
fname = self.get_fname() |
|||
if os.path.exists(fname): |
|||
tree = ElementTree.parse(fname) |
|||
root = tree.getroot() |
|||
else: |
|||
root = ElementTree.fromstring(MSDEV_PROJECT) |
|||
return root |
|||
|
|||
def get_content(self): |
|||
'''Returns the content of a project file.''' |
|||
root = self.get_root() |
|||
root.set('Name', self.gen.get_name()) |
|||
root.set('ProjectGUID', '{%s}' % self.id) |
|||
configurations = root.find('Configurations') |
|||
for configuration in configurations.iter('Configuration'): |
|||
configuration.set('ConfigurationType', '%s' % self.type) |
|||
configuration.set('OutputDirectory', '%s\\msdev' % self.buildpath) |
|||
configuration.set('IntermediateDirectory', '%s\\msdev' % self.buildpath) |
|||
for tool in configuration.iter('Tool'): |
|||
name = tool.get('Name') |
|||
if name == 'VCCLCompilerTool': |
|||
tool.set('PreprocessorDefinitions', '%s' % self.get_compiler_defines(self.gen)) |
|||
includes = [] |
|||
for include in self.get_compiler_includes(self.bld, self.gen): |
|||
includes.append('%s' % include) |
|||
tool.set('AdditionalIncludeDirectories', ';'.join(includes)) |
|||
if name == 'VCLinkerTool': |
|||
if self.type == MsDev.PROGRAM: |
|||
# Force Windows Subsystem |
|||
# TODO: this isn't enables Windows XP compatibility! |
|||
tool.set('SubSystem', '2') |
|||
self.update_link_deps(tool) |
|||
self.update_link_paths(tool) |
|||
files = root.find('Files') |
|||
self.update_includes(files) |
|||
self.update_sources(files) |
|||
return ElementTree.tostring(root) |
|||
|
|||
def update_includes(self, files): |
|||
'''Add include files.''' |
|||
includes = [] |
|||
for filtr in files.iter('Filter'): |
|||
if filtr.get('Name') == 'Header Files': |
|||
for include in filtr.iter('File'): |
|||
includes.append(include.get('RelativePath')) |
|||
break |
|||
if len(includes) == 0: |
|||
filtr = ElementTree.SubElement(files, 'Filter', attrib={'Name':'Header Files', 'Filter':'h;hpp;hxx;hm;inl;inc;xsd'}) |
|||
filtr.set('UniqueIdentifier', '{%s}' % str(uuid.uuid4()).upper()) |
|||
for include in self.get_include_files(self.bld, self.gen): |
|||
if include not in includes: |
|||
ElementTree.SubElement(filtr, 'File', attrib={'RelativePath':'%s' % include}) |
|||
|
|||
def update_sources(self, files): |
|||
'''Add source files.''' |
|||
sources = [] |
|||
for filtr in files.iter('Filter'): |
|||
if filtr.get('Name') == 'Source Files': |
|||
for source in filtr.iter('File'): |
|||
sources.append(source.get('RelativePath')) |
|||
break |
|||
if len(sources) == 0: |
|||
filtr = ElementTree.SubElement(files, 'Filter', attrib={'Name':'Source Files', 'Filter':'cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx'}) |
|||
filtr.set('UniqueIdentifier', '{%s}' % str(uuid.uuid4()).upper()) |
|||
for source in self.get_genlist(self.gen, 'source'): |
|||
if source not in sources: |
|||
ElementTree.SubElement(filtr, 'File', attrib={'RelativePath':'%s' % source}) |
|||
|
|||
def update_link_deps(self, tool): |
|||
'''Add libraries on which this project depends.''' |
|||
deps = tool.get('AdditionalDependencies') |
|||
|
|||
deps = [] # clean out deps everytime |
|||
|
|||
libs = self.get_link_libs(self.bld, self.gen) |
|||
for lib in libs: |
|||
dep = '%s.lib' % lib |
|||
if dep not in deps: |
|||
deps.append(dep) |
|||
if len(deps): |
|||
add_deps = " ".join(deps) # work around when converting to vcxproj by inserting spaces |
|||
tool.set('AdditionalDependencies', add_deps) |
|||
|
|||
def update_link_paths(self, tool): |
|||
deps = tool.get('AdditionalLibraryDirectories', '') |
|||
deps = [] |
|||
dirs = self.get_link_paths(self.bld, self.gen) |
|||
for dep in dirs: |
|||
if dep not in deps: |
|||
deps.append(dep) |
|||
if len(deps): |
|||
tool.set('AdditionalLibraryDirectories', ';'.join(deps)) |
|||
|
|||
def get_metadata(self): |
|||
'''Returns a tuple containing project information (name, file name and |
|||
dependencies). |
|||
''' |
|||
name = self.gen.get_name() |
|||
fname = self.get_fname().replace('/', '\\') |
|||
deps = Utils.to_list(getattr(self.gen, 'use', [])) |
|||
return (name, fname, deps, self.id) |
|||
|
|||
def get_genlist(self, gen, name): |
|||
lst = Utils.to_list(getattr(gen, name, [])) |
|||
lst = [str(l.path_from(gen.path)) if hasattr(l, 'path_from') else l for l in lst] |
|||
return [l.replace('/', '\\') for l in lst] |
|||
|
|||
def get_compiler_options(self, bld, gen): |
|||
if self.language == MsDev.CXX: |
|||
flags = getattr(gen, 'cxxflags', []) + bld.env.CXXFLAGS |
|||
else: |
|||
flags = getattr(gen, 'cflags', []) + bld.env.CFLAGS |
|||
if self.type == MsDev.SHLIB: |
|||
if self.language == MsDev.CXX: |
|||
flags.extend(bld.env.CXXFLAGS_cxxshlib) |
|||
else: |
|||
flags.extend(bld.env.CFLAGS_cshlib) |
|||
return list(set(flags)) |
|||
|
|||
def get_compiler_includes(self, bld, gen): |
|||
includes = self.get_genlist(gen, 'includes') |
|||
for include in bld.env['INCLUDES']: |
|||
root = bld.path.abspath().replace('\\', '/') |
|||
pref = os.path.commonprefix([root, include]) |
|||
if pref == root: |
|||
node = bld.root.find_dir(include) |
|||
if node: |
|||
includes.append(node.path_from(gen.path).replace('/', '\\')) |
|||
|
|||
deps = Utils.to_list(getattr(gen, 'use', [])) |
|||
for dep in deps: |
|||
uselib_incs = bld.env['INCLUDES_%s' % dep] |
|||
for uselib_inc in uselib_incs: |
|||
root = bld.root.abspath().replace('\\', '/') |
|||
pref = os.path.commonprefix([root, uselib_inc]) |
|||
if pref == root: |
|||
node = bld.root.find_dir(uselib_inc) |
|||
if node: |
|||
inc = node.path_from(gen.path).replace('/', '\\') |
|||
includes.append(inc) |
|||
Logs.pprint('YELLOW', 'Added relative include: %s' % inc) |
|||
includes.append(uselib_inc) |
|||
return includes |
|||
|
|||
def get_compiler_defines(self, gen): |
|||
defines = self.get_genlist(gen, 'defines') + gen.bld.env.DEFINES |
|||
if 'win32' in sys.platform: |
|||
defines = [d.replace('"', '\\"') for d in defines] |
|||
defines = ';'.join(defines) |
|||
return defines |
|||
|
|||
def get_link_options(self, bld, gen): |
|||
flags = getattr(gen, 'linkflags', []) + bld.env.LINKFLAGS |
|||
if self.language == MsDev.CXX: |
|||
if self.type == MsDev.SHLIB: |
|||
flags.extend(bld.env.LINKFLAGS_cxxshlib) |
|||
else: |
|||
flags.extend(bld.env.LINKFLAGS_cshlib) |
|||
return list(set(flags)) |
|||
|
|||
def get_link_libs(self, bld, gen): |
|||
libs = Utils.to_list(getattr(gen, 'lib', [])) |
|||
deps = Utils.to_list(getattr(gen, 'use', [])) |
|||
for dep in deps: |
|||
try: |
|||
tgen = bld.get_tgen_by_name(dep) |
|||
except Errors.WafError: |
|||
uselib_libs = bld.env['LIB_%s' % dep] |
|||
for uselib_lib in uselib_libs: |
|||
libs.append(uselib_lib) |
|||
pass |
|||
else: |
|||
if self.type == MsDev.STLIB: |
|||
libs.append(dep) |
|||
return libs |
|||
|
|||
def get_link_paths(self, bld, gen): |
|||
dirs = [] |
|||
deps = Utils.to_list(getattr(gen, 'use', [])) |
|||
for dep in deps: |
|||
try: |
|||
tgen = bld.get_tgen_by_name(dep) |
|||
except Errors.WafError: |
|||
uselib_paths = bld.env['LIBPATH_%s' % dep] |
|||
for uselib_path in uselib_paths: |
|||
root = bld.root.abspath().replace('\\', '/') |
|||
pref = os.path.commonprefix([root, uselib_path]) |
|||
if pref == root: |
|||
node = bld.root.find_dir(uselib_path) |
|||
if node: |
|||
libpath = node.path_from(gen.path).replace('/', '\\') |
|||
dirs.append(libpath) |
|||
Logs.pprint('YELLOW', 'Added relative library path: %s' % libpath) |
|||
dirs.append(uselib_path) |
|||
pass |
|||
else: |
|||
if self.type in (MsDev.STLIB, MsDev.SHLIB): |
|||
directory = '%s\\msdev' % tgen.path.get_bld().path_from(gen.path) |
|||
if directory not in dirs: |
|||
dirs.append(directory.replace('/', '\\')) |
|||
elif self.type in (MsDev.PROGRAM): |
|||
for directory in tgen.lib_paths: |
|||
if directory not in dirs: |
|||
dirs.append(directory.replace('/', '\\')) |
|||
return dirs |
|||
|
|||
def get_include_files(self, bld, gen): |
|||
includes = [] |
|||
for include in self.get_genlist(gen, 'includes'): |
|||
node = gen.path.find_dir(include) |
|||
if node: |
|||
for header in node.ant_glob('*.h*'): |
|||
includes.append(header.path_from(gen.path).replace('/', '\\')) |
|||
|
|||
for include in bld.env['INCLUDES']: |
|||
root = bld.path.abspath().replace('\\', '/') |
|||
pref = os.path.commonprefix([root, include]) |
|||
if pref == root: |
|||
node = bld.root.find_dir(include) |
|||
if node: |
|||
for header in node.ant_glob('*.h*'): |
|||
includes.append(header.path_from(gen.path).replace('/', '\\')) |
|||
|
|||
return includes |
|||
|
|||
|
|||
MSDEV_PROJECT = \ |
|||
'''<?xml version="1.0" encoding="UTF-8"?> |
|||
<VisualStudioProject |
|||
ProjectType="Visual C++" |
|||
Version="8,00" |
|||
Name="" |
|||
ProjectGUID="" |
|||
Keyword="Win32Proj" |
|||
TargetFrameworkVersion="0" |
|||
> |
|||
<Platforms> |
|||
<Platform |
|||
Name="Win32" |
|||
/> |
|||
</Platforms> |
|||
<ToolFiles> |
|||
</ToolFiles> |
|||
<Configurations> |
|||
<Configuration |
|||
Name="Debug|Win32" |
|||
OutputDirectory="Debug" |
|||
IntermediateDirectory="Debug" |
|||
ConfigurationType="1" |
|||
> |
|||
<Tool |
|||
Name="VCPreBuildEventTool" |
|||
/> |
|||
<Tool |
|||
Name="VCCustomBuildTool" |
|||
/> |
|||
<Tool |
|||
Name="VCXMLDataGeneratorTool" |
|||
/> |
|||
<Tool |
|||
Name="VCWebServiceProxyGeneratorTool" |
|||
/> |
|||
<Tool |
|||
Name="VCMIDLTool" |
|||
/> |
|||
<Tool |
|||
Name="VCCLCompilerTool" |
|||
Optimization="0" |
|||
PreprocessorDefinitions="" |
|||
MinimalRebuild="true" |
|||
BasicRuntimeChecks="3" |
|||
RuntimeLibrary="3" |
|||
UsePrecompiledHeader="0" |
|||
WarningLevel="3" |
|||
DebugInformationFormat="4" |
|||
/> |
|||
<Tool |
|||
Name="VCManagedResourceCompilerTool" |
|||
/> |
|||
<Tool |
|||
Name="VCResourceCompilerTool" |
|||
/> |
|||
<Tool |
|||
Name="VCPreLinkEventTool" |
|||
/> |
|||
<Tool |
|||
Name="VCLinkerTool" |
|||
LinkIncremental="2" |
|||
GenerateDebugInformation="true" |
|||
SubSystem="1" |
|||
TargetMachine="1" |
|||
/> |
|||
<Tool |
|||
Name="VCALinkTool" |
|||
/> |
|||
<Tool |
|||
Name="VCManifestTool" |
|||
/> |
|||
<Tool |
|||
Name="VCXDCMakeTool" |
|||
/> |
|||
<Tool |
|||
Name="VCBscMakeTool" |
|||
/> |
|||
<Tool |
|||
Name="VCFxCopTool" |
|||
/> |
|||
<Tool |
|||
Name="VCAppVerifierTool" |
|||
/> |
|||
<Tool |
|||
Name="VCPostBuildEventTool" |
|||
/> |
|||
</Configuration> |
|||
</Configurations> |
|||
<References> |
|||
</References> |
|||
<Files> |
|||
</Files> |
|||
<Globals> |
|||
</Globals> |
|||
</VisualStudioProject> |
|||
''' |
|||
|
|||
MSDEV_SOLUTION = [ |
|||
'Microsoft Visual Studio Solution File, Format Version 8.00\n', |
|||
'# Visual Studio 2005\n', |
|||
'Global\n', |
|||
'GlobalSection(SolutionConfigurationPlatforms) = preSolution\n', |
|||
'Debug|Win32 = Debug|Win32\n', |
|||
'EndGlobalSection\n', |
|||
'GlobalSection(ProjectConfigurationPlatforms) = postSolution\n', |
|||
'EndGlobalSection\n', |
|||
'GlobalSection(SolutionProperties) = preSolution\n', |
|||
'HideSolutionNode = FALSE\n', |
|||
'EndGlobalSection\n', |
|||
'EndGlobal\n', |
|||
'\n'] |
@ -0,0 +1,47 @@ |
|||
#!/usr/bin/env python |
|||
# encoding: utf-8 |
|||
# Copyright (c) 2019 mittorn |
|||
|
|||
''' |
|||
Reconfigure |
|||
|
|||
Store/load configuration user input |
|||
|
|||
Usage: |
|||
def options(opt): |
|||
opt.load('reconfigure') |
|||
|
|||
def configure(conf): |
|||
conf.load('reconfigure') |
|||
|
|||
./waf configure --reconfigure |
|||
''' |
|||
|
|||
from waflib import Configure, Logs, Options, Utils, ConfigSet |
|||
import os |
|||
|
|||
import optparse |
|||
STORE_PATH = 'build/configuration.py' |
|||
|
|||
def options(opt): |
|||
opt.add_option('--rebuild-cache', dest='rebuild_cache', default=False, action='store_true', help='load previous configuration') |
|||
opt.add_option('--reconfigure', dest='reconfigure', default=False, action='store_true', help='load and update configuration') |
|||
|
|||
def configure(conf): |
|||
store_data = ConfigSet.ConfigSet() |
|||
options = vars(conf.options) |
|||
environ = conf.environ |
|||
if conf.options.reconfigure or conf.options.rebuild_cache: |
|||
store_data.load(STORE_PATH) |
|||
if conf.options.reconfigure: |
|||
for o in options: |
|||
if options[o]: store_data['OPTIONS'][o] = options[o] |
|||
store_data['ENVIRON'].update(environ) |
|||
store_data.store(STORE_PATH) |
|||
conf.environ = store_data['ENVIRON'] |
|||
conf.options = optparse.Values(store_data['OPTIONS']) |
|||
else: |
|||
store_data['OPTIONS'] = vars(conf.options) |
|||
store_data['ENVIRON'] = conf.environ |
|||
store_data.store(STORE_PATH) |
|||
|
@ -0,0 +1,208 @@ |
|||
# encoding: utf-8 |
|||
# xcompile.py -- crosscompiling utils |
|||
# Copyright (C) 2018 a1batross |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU General Public License as published by |
|||
# the Free Software Foundation, either version 3 of the License, or |
|||
# (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU General Public License for more details. |
|||
|
|||
from fwgslib import get_flags_by_compiler |
|||
import os |
|||
import sys |
|||
|
|||
# Output: |
|||
# CROSSCOMPILING -- set to true, if crosscompiling is enabled |
|||
# DEST_OS2 -- as some operating systems is built on top of another, it's better to not change DEST_OS, |
|||
# instead of this DEST_OS2 is defined with target value |
|||
# For example: android is built on top of linux and have many things in common, |
|||
# but it can't be considered as default GNU/Linux. |
|||
# Possible values: |
|||
# DEST_OS2 DEST_OS |
|||
# 'android' 'linux' |
|||
|
|||
class Android: |
|||
arch = None |
|||
toolchain = None |
|||
api = None |
|||
toolchain_path = None |
|||
ndk_home = None |
|||
|
|||
# TODO: New Android NDK support? |
|||
# TODO: Crystax support? |
|||
# TODO: Support for everything else than linux-x86_64? |
|||
# TODO: Determine if I actually need to implement listed above |
|||
|
|||
def is_arm(self): |
|||
''' |
|||
Checks if selected architecture is **32-bit** ARM |
|||
''' |
|||
return self.arch.startswith('armeabi') |
|||
|
|||
def is_x86(self): |
|||
''' |
|||
Checks if selected architecture is **32-bit** or **64-bit** x86 |
|||
''' |
|||
return self.arch.startswith('x86') |
|||
|
|||
def is_arm64(self): |
|||
''' |
|||
Checks if selected architecture is AArch64 |
|||
''' |
|||
return self.arch == 'aarch64' |
|||
|
|||
def is_clang(self): |
|||
''' |
|||
Checks if selected toolchain is Clang (TODO) |
|||
''' |
|||
return self.toolchain.startswith('clang') |
|||
|
|||
def is_hardfp(self): |
|||
return self.arch.endswith('-hard') |
|||
|
|||
def gen_toolchain_path(self): |
|||
path = 'toolchains' |
|||
if self.is_clang(): |
|||
raise Exception('Clang is not supported yet') |
|||
else: |
|||
if self.is_x86(): |
|||
toolchain_folder = self.arch + '-' + self.toolchain |
|||
elif self.is_arm(): |
|||
toolchain_folder = 'arm-linux-androideabi-' + self.toolchain |
|||
else: |
|||
toolchain_folder = self.arch + '-linux-android-' + self.toolchain |
|||
|
|||
if sys.platform.startswith('linux'): |
|||
toolchain_host = 'linux' |
|||
elif sys.platform.startswith('darwin'): |
|||
toolchain_host = 'darwin' |
|||
elif sys.platform.startswith('win32') or sys.platform.startswith('cygwin'): |
|||
toolchain_host = 'windows' |
|||
else: raise Exception('Unsupported by NDK host platform') |
|||
|
|||
toolchain_host += '-' |
|||
|
|||
# Assuming we are building on x86 |
|||
if sys.maxsize > 2**32: |
|||
toolchain_host += 'x86_64' |
|||
else: toolchain_host += 'x86' |
|||
|
|||
if self.arch == 'x86': |
|||
triplet = 'i686-linux-android-' |
|||
elif self.is_arm(): |
|||
triplet = 'arm-linux-androideabi-' |
|||
else: |
|||
triplet = self.arch + '-linux-android-' |
|||
|
|||
return os.path.join(path, toolchain_folder, 'prebuilt', toolchain_host, 'bin', triplet) |
|||
|
|||
def cc(self): |
|||
return os.path.abspath(os.path.join(self.ndk_home, self.toolchain_path + 'gcc')) |
|||
|
|||
def cxx(self): |
|||
return os.path.abspath(os.path.join(self.ndk_home, self.toolchain_path + 'g++')) |
|||
|
|||
def system_stl(self): |
|||
# TODO: proper STL support |
|||
return os.path.abspath(os.path.join(self.ndk_home, 'sources', 'cxx-stl', 'system', 'include')) |
|||
|
|||
def sysroot(self): |
|||
arch = self.arch |
|||
if self.is_arm(): |
|||
arch = 'arm' |
|||
elif self.is_arm64(): |
|||
arch = 'arm64' |
|||
path = 'platforms/android-{0}/arch-{1}'.format(self.api, arch) |
|||
|
|||
return os.path.abspath(os.path.join(self.ndk_home, path)) |
|||
|
|||
def cflags(self): |
|||
cflags = ['--sysroot={0}'.format(self.sysroot()), '-DANDROID', '-D__ANDROID__'] |
|||
cflags += ['-I{0}'.format(self.system_stl())] |
|||
if self.is_arm(): |
|||
if self.arch.startswith('armeabi-v7a'): |
|||
# ARMv7 support |
|||
cflags += ['-mthumb', '-mfpu=neon', '-mcpu=cortex-a9', '-mvectorize-with-neon-quad', '-DHAVE_EFFICIENT_UNALIGNED_ACCESS', '-DVECTORIZE_SINCOS'] |
|||
if self.arch == 'armeabi-v7a-hard': |
|||
cflags += ['-D_NDK_MATH_NO_SOFTFP=1', '-mhard-float', '-mfloat-abi=hard', '-DLOAD_HARDFP', '-DSOFTFP_LINK'] |
|||
else: |
|||
cflags += ['-mfloat-abi=softfp'] # Tegra 2 sucks |
|||
else: |
|||
# ARMv5 support |
|||
cflags += ['-march=armv5te', '-mtune=xscale', '-msoft-float'] |
|||
elif self.is_x86(): |
|||
cflags += ['-mtune=atom', '-march=atom', '-mssse3', '-mfpmath=sse', '-DVECTORIZE_SINCOS', '-DHAVE_EFFICIENT_UNALIGNED_ACCESS'] |
|||
return cflags |
|||
|
|||
def ldflags(self): |
|||
ldflags = ['--sysroot={0}'.format(self.sysroot())] |
|||
if self.is_arm(): |
|||
if self.arch.startswith('armeabi-v7a'): |
|||
ldflags += ['-march=armv7-a', '-Wl,--fix-cortex-a8'] |
|||
if self.arch == 'armeabi-v7a-hard': |
|||
ldflags += ['-Wl,--no-warn-mismatch', '-lm_hard'] |
|||
else: |
|||
ldflags += ['-march=armv5te'] |
|||
return ldflags |
|||
|
|||
def __init__(self, ndk_home, arch, toolchain, api): |
|||
self.ndk_home = ndk_home |
|||
self.arch = arch |
|||
self.toolchain = toolchain |
|||
self.api = api |
|||
self.toolchain_path = self.gen_toolchain_path() |
|||
|
|||
def options(opt): |
|||
android = opt.add_option_group('Android options') |
|||
android.add_option('--android', action='store', dest='ANDROID_OPTS', default=None, |
|||
help='enable building for android, format: --android=<arch>,<toolchain>,<api>, example: --android=armeabi-v7a-hard,4.9,9') |
|||
|
|||
def configure(conf): |
|||
if conf.options.ANDROID_OPTS: |
|||
for i in ['ANDROID_NDK_HOME', 'ANDROID_NDK']: |
|||
android_ndk_path = os.getenv(i) |
|||
if android_ndk_path != None: |
|||
break |
|||
|
|||
if not android_ndk_path: |
|||
conf.fatal('Set ANDROID_NDK_HOME environment variable pointing to the root of Android NDK!') |
|||
|
|||
values = conf.options.ANDROID_OPTS.split(',') |
|||
if len(values) != 3: |
|||
conf.fatal('Invalid --android paramater value!') |
|||
|
|||
valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64', 'mipsel', 'mips64el'] |
|||
|
|||
if values[0] not in valid_archs: |
|||
conf.fatal('Unknown arch: {0}. Supported: {1}'.format(values[0], ', '.join(valid_archs))) |
|||
|
|||
android = Android(android_ndk_path, values[0], values[1], values[2]) |
|||
conf.options.ALLOW64 = True # skip pointer length check |
|||
conf.options.NO_VGUI = True # skip vgui |
|||
conf.options.NANOGL = True |
|||
conf.options.GLWES = True |
|||
conf.options.GL = False |
|||
conf.environ['CC'] = android.cc() |
|||
conf.environ['CXX'] = android.cxx() |
|||
conf.env.CFLAGS += android.cflags() |
|||
conf.env.CXXFLAGS += android.cflags() |
|||
conf.env.LINKFLAGS += android.ldflags() |
|||
|
|||
conf.env.HAVE_M = True |
|||
if android.is_hardfp(): |
|||
conf.env.LIB_M = ['m_hard'] |
|||
else: conf.env.LIB_M = ['m'] |
|||
|
|||
conf.msg('Selected Android NDK', android_ndk_path) |
|||
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx |
|||
conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android_ndk_path, '$NDK')) |
|||
conf.msg('... linker flags', ' '.join(android.ldflags()).replace(android_ndk_path, '$NDK')) |
|||
|
|||
# conf.env.ANDROID_OPTS = android |
|||
conf.env.DEST_OS2 = 'android' |
|||
# else: |
|||
# conf.load('compiler_c compiler_cxx') # Use host compiler :) |
File diff suppressed because one or more lines are too long
@ -0,0 +1,149 @@ |
|||
#! /usr/bin/env python |
|||
# encoding: utf-8 |
|||
# a1batross, mittorn, 2018 |
|||
|
|||
from __future__ import print_function |
|||
from waflib import Logs |
|||
import sys |
|||
import os |
|||
sys.path.append(os.path.realpath('scripts/waflib')) |
|||
import fwgslib |
|||
|
|||
VERSION = '2.4' |
|||
APPNAME = 'hlsdk-xash3d' |
|||
top = '.' |
|||
|
|||
def options(opt): |
|||
grp = opt.add_option_group('Common options') |
|||
|
|||
grp.add_option('-T', '--build-type', action='store', dest='BUILD_TYPE', default = None, |
|||
help = 'build type: debug, release or none(custom flags)') |
|||
|
|||
grp.add_option('-8', '--64bits', action = 'store_true', dest = 'ALLOW64', default = False, |
|||
help = 'allow targetting 64-bit game dlls') |
|||
|
|||
grp.add_option('--enable-voicemgr', action = 'store_true', dest = 'VOICEMGR', default = False, |
|||
help = 'enable voice manager') |
|||
|
|||
grp.add_option('--enable-goldsrc-support', action = 'store_true', dest = 'GOLDSRC', default = False, |
|||
help = 'enable GoldSource engine support') |
|||
|
|||
opt.recurse('cl_dll dlls') |
|||
|
|||
opt.load('xcompile compiler_cxx compiler_c') |
|||
if sys.platform == 'win32': |
|||
opt.load('msvc msdev') |
|||
opt.load('reconfigure') |
|||
|
|||
|
|||
def configure(conf): |
|||
# Configuration |
|||
conf.env.GAMEDIR = 'valve' |
|||
conf.env.CLIENT_DIR = 'cl_dlls' |
|||
conf.env.SERVER_DIR = 'dlls' |
|||
conf.env.SERVER_NAME = 'hl' |
|||
conf.env.PREFIX = '' |
|||
|
|||
conf.load('reconfigure') |
|||
|
|||
conf.start_msg('Build type') |
|||
if conf.options.BUILD_TYPE == None: |
|||
conf.end_msg('not set', color='RED') |
|||
conf.fatal('Please set a build type, for example "-T release"') |
|||
elif not conf.options.BUILD_TYPE in ['fast', 'release', 'debug', 'nooptimize', 'sanitize', 'none']: |
|||
conf.end_msg(conf.options.BUILD_TYPE, color='RED') |
|||
conf.fatal('Invalid build type. Valid are "debug", "release" or "none"') |
|||
conf.end_msg(conf.options.BUILD_TYPE) |
|||
|
|||
# -march=native should not be used |
|||
if conf.options.BUILD_TYPE == 'fast': |
|||
Logs.warn('WARNING: \'fast\' build type should not be used in release builds') |
|||
|
|||
conf.env.VOICEMGR = conf.options.VOICEMGR |
|||
conf.env.GOLDSRC = conf.options.GOLDSRC |
|||
|
|||
# Force XP compability, all build targets should add |
|||
# subsystem=bld.env.MSVC_SUBSYSTEM |
|||
# TODO: wrapper around bld.stlib, bld.shlib and so on? |
|||
conf.env.MSVC_SUBSYSTEM = 'WINDOWS,5.01' |
|||
conf.env.MSVC_TARGETS = ['x86'] # explicitly request x86 target for MSVC |
|||
if sys.platform == 'win32': |
|||
conf.load('msvc msdev') |
|||
conf.load('xcompile compiler_c compiler_cxx') |
|||
|
|||
# print(conf.options.ALLOW64) |
|||
|
|||
conf.env.BIT32_MANDATORY = not conf.options.ALLOW64 |
|||
conf.env.BIT32_ALLOW64 = conf.options.ALLOW64 |
|||
conf.load('force_32bit') |
|||
|
|||
if conf.env.DEST_SIZEOF_VOID_P == 4: |
|||
Logs.info('NOTE: will build game dlls for 32-bit target') |
|||
else: |
|||
Logs.warn('WARNING: 64-bit game dlls may be unstable') |
|||
|
|||
linker_flags = { |
|||
'common': { |
|||
'msvc': ['/DEBUG'], # always create PDB, doesn't affect result binaries |
|||
'gcc': ['-Wl,--no-undefined'] |
|||
}, |
|||
'sanitize': { |
|||
'gcc': ['-fsanitize=undefined', '-fsanitize=address'], |
|||
} |
|||
} |
|||
|
|||
compiler_c_cxx_flags = { |
|||
'common': { |
|||
'msvc': ['/D_USING_V110_SDK71_', '/Zi', '/FS'], |
|||
'clang': ['-g', '-gdwarf-2'], |
|||
'gcc': ['-g', '-Werror=implicit-function-declaration', '-fdiagnostics-color=always'] |
|||
}, |
|||
'fast': { |
|||
'msvc': ['/O2', '/Oy'], #todo: check /GL /LTCG |
|||
'gcc': ['-Ofast', '-march=native', '-funsafe-math-optimizations', '-funsafe-loop-optimizations', '-fomit-frame-pointer'], |
|||
'default': ['-O3'] |
|||
}, |
|||
'release': { |
|||
'msvc': ['/O2'], |
|||
'default': ['-O3'] |
|||
}, |
|||
'debug': { |
|||
'msvc': ['/O1'], |
|||
'gcc': ['-Og'], |
|||
'default': ['-O1'] |
|||
}, |
|||
'sanitize': { |
|||
'msvc': ['/Od', '/RTC1'], |
|||
'gcc': ['-Og', '-fsanitize=undefined', '-fsanitize=address'], |
|||
'default': ['-O1'] |
|||
}, |
|||
'nooptimize': { |
|||
'msvc': ['/Od'], |
|||
'default': ['-O0'] |
|||
} |
|||
} |
|||
|
|||
conf.env.append_unique('CFLAGS', fwgslib.get_flags_by_type( |
|||
compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC)) |
|||
conf.env.append_unique('CXXFLAGS', fwgslib.get_flags_by_type( |
|||
compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC)) |
|||
conf.env.append_unique('LINKFLAGS', fwgslib.get_flags_by_type( |
|||
linker_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC)) |
|||
|
|||
if conf.env.COMPILER_CC == 'msvc': |
|||
conf.env.append_unique('DEFINES', ['_CRT_SECURE_NO_WARNINGS','_CRT_NONSTDC_NO_DEPRECATE']) |
|||
else: |
|||
conf.env.append_unique('DEFINES', ['stricmp=strcasecmp','strnicmp=strncasecmp','_LINUX','LINUX','_snprintf=snprintf','_vsnprintf=vsnprintf']) |
|||
cflags = ['-fvisibility=hidden','-Wno-write-strings','-fno-exceptions'] |
|||
conf.env.append_unique('CFLAGS', cflags) |
|||
conf.env.append_unique('CXXFLAGS', cflags + ['-Wno-invalid-offsetof']) |
|||
|
|||
conf.env.append_unique('DEFINES', 'CLIENT_WEAPONS') |
|||
|
|||
conf.recurse('cl_dll dlls') |
|||
|
|||
def build(bld): |
|||
bld.recurse('cl_dll dlls') |
|||
|
|||
|
|||
|
Loading…
Reference in new issue