mirror of
https://github.com/FWGS/hlsdk-xash3d
synced 2024-11-21 17:36:18 +01:00
waf: initial deploy
This commit is contained in:
parent
f7e51e2c20
commit
470a71540b
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,3 +17,6 @@ cmake_install.cmake
|
||||
*.vsxproj
|
||||
*.vsproj
|
||||
*.sln
|
||||
.waf-*
|
||||
.lock*
|
||||
*.pyc
|
||||
|
69
cl_dll/wscript
Normal file
69
cl_dll/wscript
Normal file
@ -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
|
||||
)
|
75
dlls/wscript
Normal file
75
dlls/wscript
Normal file
@ -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
|
||||
)
|
65
scripts/waflib/deps.py
Normal file
65
scripts/waflib/deps.py
Normal file
@ -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
|
||||
|
56
scripts/waflib/force_32bit.py
Normal file
56
scripts/waflib/force_32bit.py
Normal file
@ -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!')
|
30
scripts/waflib/fwgslib.py
Normal file
30
scripts/waflib/fwgslib.py
Normal file
@ -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
|
774
scripts/waflib/msdev.py
Normal file
774
scripts/waflib/msdev.py
Normal file
@ -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']
|
47
scripts/waflib/reconfigure.py
Normal file
47
scripts/waflib/reconfigure.py
Normal file
@ -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)
|
||||
|
208
scripts/waflib/xcompile.py
Normal file
208
scripts/waflib/xcompile.py
Normal file
@ -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 :)
|
170
waf
vendored
Executable file
170
waf
vendored
Executable file
File diff suppressed because one or more lines are too long
149
wscript
Normal file
149
wscript
Normal file
@ -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
Block a user