mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-25 22:34:24 +00:00
waf: update to 2.0.17, rename module dir to waifulib, remove some modules, as they moved to waf binary itself(see waifu project)
This commit is contained in:
parent
003bbea358
commit
a8cc5b7cef
2
mainui
2
mainui
@ -1 +1 @@
|
|||||||
Subproject commit 9b328b4c135b58bee660e4088605f590bd2de57c
|
Subproject commit e36175ae03e0664d5fb316fd726c5006124b7875
|
@ -1,85 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# encoding: utf-8
|
|
||||||
# Christoph Koke, 2013
|
|
||||||
|
|
||||||
"""
|
|
||||||
Writes the c and cpp compile commands into build/compile_commands.json
|
|
||||||
see http://clang.llvm.org/docs/JSONCompilationDatabase.html
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
def configure(conf):
|
|
||||||
conf.load('compiler_cxx')
|
|
||||||
...
|
|
||||||
conf.load('clang_compilation_database')
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys, os, json, shlex, pipes
|
|
||||||
from waflib import Logs, TaskGen, Task
|
|
||||||
|
|
||||||
Task.Task.keep_last_cmd = True
|
|
||||||
|
|
||||||
@TaskGen.feature('c', 'cxx')
|
|
||||||
@TaskGen.after_method('process_use')
|
|
||||||
def collect_compilation_db_tasks(self):
|
|
||||||
"Add a compilation database entry for compiled tasks"
|
|
||||||
try:
|
|
||||||
clang_db = self.bld.clang_compilation_database_tasks
|
|
||||||
except AttributeError:
|
|
||||||
clang_db = self.bld.clang_compilation_database_tasks = []
|
|
||||||
self.bld.add_post_fun(write_compilation_database)
|
|
||||||
|
|
||||||
tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y)
|
|
||||||
for task in getattr(self, 'compiled_tasks', []):
|
|
||||||
if isinstance(task, tup):
|
|
||||||
clang_db.append(task)
|
|
||||||
|
|
||||||
def write_compilation_database(ctx):
|
|
||||||
"Write the clang compilation database as JSON"
|
|
||||||
database_file = ctx.bldnode.make_node('compile_commands.json')
|
|
||||||
Logs.info('Build commands will be stored in %s', database_file.path_from(ctx.path))
|
|
||||||
try:
|
|
||||||
root = json.load(database_file)
|
|
||||||
except IOError:
|
|
||||||
root = []
|
|
||||||
clang_db = dict((x['file'], x) for x in root)
|
|
||||||
for task in getattr(ctx, 'clang_compilation_database_tasks', []):
|
|
||||||
try:
|
|
||||||
cmd = task.last_cmd
|
|
||||||
except AttributeError:
|
|
||||||
continue
|
|
||||||
directory = getattr(task, 'cwd', ctx.variant_dir)
|
|
||||||
f_node = task.inputs[0]
|
|
||||||
filename = os.path.relpath(f_node.abspath(), directory)
|
|
||||||
entry = {
|
|
||||||
"directory": directory,
|
|
||||||
"arguments": cmd,
|
|
||||||
"file": filename,
|
|
||||||
}
|
|
||||||
clang_db[filename] = entry
|
|
||||||
root = list(clang_db.values())
|
|
||||||
database_file.write(json.dumps(root, indent=2))
|
|
||||||
|
|
||||||
# Override the runnable_status function to do a dummy/dry run when the file doesn't need to be compiled.
|
|
||||||
# This will make sure compile_commands.json is always fully up to date.
|
|
||||||
# Previously you could end up with a partial compile_commands.json if the build failed.
|
|
||||||
for x in ('c', 'cxx'):
|
|
||||||
if x not in Task.classes:
|
|
||||||
continue
|
|
||||||
|
|
||||||
t = Task.classes[x]
|
|
||||||
|
|
||||||
def runnable_status(self):
|
|
||||||
def exec_command(cmd, **kw):
|
|
||||||
pass
|
|
||||||
|
|
||||||
run_status = self.old_runnable_status()
|
|
||||||
if run_status == Task.SKIP_ME:
|
|
||||||
setattr(self, 'old_exec_command', getattr(self, 'exec_command', None))
|
|
||||||
setattr(self, 'exec_command', exec_command)
|
|
||||||
self.run()
|
|
||||||
setattr(self, 'exec_command', getattr(self, 'old_exec_command', None))
|
|
||||||
return run_status
|
|
||||||
|
|
||||||
setattr(t, 'old_runnable_status', getattr(t, 'runnable_status', None))
|
|
||||||
setattr(t, 'runnable_status', runnable_status)
|
|
@ -1,51 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
# cxx11.py -- check if compiler can compile C++11 code with lambdas
|
|
||||||
# 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:
|
|
||||||
# CXX11_MANDATORY(optional) -- fail if C++11 not available
|
|
||||||
# Output:
|
|
||||||
# HAVE_CXX11 -- true if C++11 available, otherwise else
|
|
||||||
|
|
||||||
def check_cxx11(ctx, msg):
|
|
||||||
try:
|
|
||||||
# not best way, but this check
|
|
||||||
# was written for exactly mainui_cpp,
|
|
||||||
# where lambdas are mandatory
|
|
||||||
ctx.check_cxx(
|
|
||||||
fragment='int main( void ){ auto pfnLambda = [](){}; return 0;}',
|
|
||||||
msg = msg)
|
|
||||||
except ctx.errors.ConfigurationError:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def configure(conf):
|
|
||||||
conf.env.HAVE_CXX11 = True # predict state
|
|
||||||
if not check_cxx11(conf, 'Checking if \'{0}\' supports C++11'.format(conf.env.COMPILER_CC)):
|
|
||||||
modern_cpp_flags = {
|
|
||||||
'msvc': [],
|
|
||||||
'default': ['-std=c++11']
|
|
||||||
}
|
|
||||||
flags = get_flags_by_compiler(modern_cpp_flags, conf.env.COMPILER_CC)
|
|
||||||
if(len(flags) == 0):
|
|
||||||
conf.env.HAVE_CXX11 = False
|
|
||||||
else:
|
|
||||||
env_stash = conf.env
|
|
||||||
conf.env.append_unique('CXXFLAGS', flags)
|
|
||||||
if not check_cxx11(conf, '...trying with additional flags'):
|
|
||||||
conf.env.HAVE_CXX11 = False
|
|
||||||
conf.env = env_stash
|
|
||||||
if getattr(conf.env, 'CXX11_MANDATORY'):
|
|
||||||
conf.fatal('C++11 support not available!')
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
|||||||
#!/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
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
# 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 check_32bit(conf, 'Checking if \'{0}\' can target 32-bit'.format(conf.env.COMPILER_CC)):
|
|
||||||
conf.env.DEST_SIZEOF_VOID_P = 4
|
|
||||||
else:
|
|
||||||
conf.env.DEST_SIZEOF_VOID_P = 8
|
|
||||||
if not conf.env.BIT32_ALLOW64:
|
|
||||||
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 conf.env.BIT32_MANDATORY and conf.env.DEST_SIZEOF_VOID_P == 8:
|
|
||||||
conf.fatal('Compiler can\'t create 32-bit code!')
|
|
@ -1,30 +0,0 @@
|
|||||||
# 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
|
|
@ -1,33 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
# gitversion.py -- waf plugin to get git version
|
|
||||||
# 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_git_version():
|
|
||||||
# try grab the current version number from git
|
|
||||||
version = None
|
|
||||||
if os.path.exists('.git'):
|
|
||||||
try:
|
|
||||||
version = os.popen('git describe --dirty --always').read().strip()
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if(len(version) == 0):
|
|
||||||
version = None
|
|
||||||
|
|
||||||
return version
|
|
||||||
|
|
||||||
def configure(conf):
|
|
||||||
conf.start_msg('Checking git hash')
|
|
||||||
conf.env.GIT_VERSION = get_git_version()
|
|
||||||
conf.end_msg(conf.env.GIT_VERSION if conf.env.GIT_VERSION else 'no')
|
|
@ -1,774 +0,0 @@
|
|||||||
#!/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']
|
|
@ -1,47 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# encoding: utf-8
|
|
||||||
# Copyright (c) 2019 a1batross
|
|
||||||
|
|
||||||
'''
|
|
||||||
Subproject tool
|
|
||||||
|
|
||||||
Helps you have standalone environment for each subproject(subdirectory)
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
def configure(conf):
|
|
||||||
conf.add_subproject('folder1 folder2')
|
|
||||||
|
|
||||||
def build(bld):
|
|
||||||
bld.add_subproject('folder1 folder2')
|
|
||||||
'''
|
|
||||||
|
|
||||||
from waflib import Configure, Logs, Options, Utils
|
|
||||||
import os
|
|
||||||
|
|
||||||
DEPTH = ''
|
|
||||||
|
|
||||||
def depth_push(path):
|
|
||||||
global DEPTH
|
|
||||||
|
|
||||||
DEPTH = os.path.join(DEPTH, path)
|
|
||||||
# print DEPTH
|
|
||||||
|
|
||||||
def depth_pop():
|
|
||||||
global DEPTH
|
|
||||||
|
|
||||||
DEPTH = os.path.dirname(DEPTH)
|
|
||||||
# print DEPTH
|
|
||||||
|
|
||||||
def depth():
|
|
||||||
global DEPTH
|
|
||||||
return DEPTH
|
|
||||||
|
|
||||||
def opt(f):
|
|
||||||
"""
|
|
||||||
Decorator: attach new option functions to :py:class:`waflib.Options.OptionsContext`.
|
|
||||||
|
|
||||||
:param f: method to bind
|
|
||||||
:type f: function
|
|
||||||
"""
|
|
||||||
setattr(Options.OptionsContext, f.__name__, f)
|
|
||||||
return f
|
|
||||||
|
|
||||||
@opt
|
|
||||||
def add_subproject(ctx, names):
|
|
||||||
names_lst = Utils.to_list(names)
|
|
||||||
|
|
||||||
for name in names_lst:
|
|
||||||
depth_push(name)
|
|
||||||
|
|
||||||
wscript_path = os.path.join(depth(), 'wscript')
|
|
||||||
|
|
||||||
if not os.path.isfile(wscript_path):
|
|
||||||
# HACKHACK: this way we get warning message right in the help
|
|
||||||
# so this just becomes more noticeable
|
|
||||||
ctx.add_option_group('Cannot find wscript in ' + name + '. You probably missed submodule update')
|
|
||||||
else:
|
|
||||||
ctx.recurse(name)
|
|
||||||
|
|
||||||
depth_pop()
|
|
||||||
|
|
||||||
def options(opt):
|
|
||||||
grp = opt.add_option_group('Subproject options')
|
|
||||||
|
|
||||||
grp.add_option('-S', '--skip-subprojects', action='store', dest = 'SKIP_SUBDIRS', default=None,
|
|
||||||
help = 'don\'t recurse into specified subprojects. Use only directory name.')
|
|
||||||
|
|
||||||
def get_subproject_env(ctx, path, log=False):
|
|
||||||
# remove top dir path
|
|
||||||
path = str(path)
|
|
||||||
if path.startswith(ctx.top_dir):
|
|
||||||
if ctx.top_dir[-1] != os.pathsep:
|
|
||||||
path = path[len(ctx.top_dir) + 1:]
|
|
||||||
else: path = path[len(ctx.top_dir):]
|
|
||||||
|
|
||||||
# iterate through possible subprojects names
|
|
||||||
folders = os.path.normpath(path).split(os.sep)
|
|
||||||
# print(folders)
|
|
||||||
for i in range(1, len(folders)+1):
|
|
||||||
name = folders[-i]
|
|
||||||
# print(name)
|
|
||||||
if name in ctx.all_envs:
|
|
||||||
if log: Logs.pprint('YELLOW', 'env: changed to %s' % name)
|
|
||||||
return ctx.all_envs[name]
|
|
||||||
if log: Logs.pprint('YELLOW', 'env: changed to default env')
|
|
||||||
raise IndexError('top env')
|
|
||||||
|
|
||||||
|
|
||||||
def configure(conf):
|
|
||||||
if conf.options.SKIP_SUBDIRS:
|
|
||||||
conf.env.IGNORED_SUBDIRS = conf.options.SKIP_SUBDIRS.split(',')
|
|
||||||
|
|
||||||
@Configure.conf
|
|
||||||
def add_subproject(ctx, names):
|
|
||||||
names_lst = Utils.to_list(names)
|
|
||||||
|
|
||||||
if isinstance(ctx, Configure.ConfigurationContext):
|
|
||||||
for name in names_lst:
|
|
||||||
depth_push(name)
|
|
||||||
if name in ctx.env.IGNORED_SUBDIRS:
|
|
||||||
ctx.msg(msg='--X %s' % depth(), result='ignored', color='YELLOW')
|
|
||||||
depth_pop()
|
|
||||||
continue
|
|
||||||
saveenv = ctx.env
|
|
||||||
ctx.setenv(name, ctx.env) # derive new env from previous
|
|
||||||
ctx.env.ENVNAME = name
|
|
||||||
ctx.msg(msg='--> %s' % depth(), result='in progress', color='BLUE')
|
|
||||||
ctx.recurse(name)
|
|
||||||
ctx.msg(msg='<-- %s' % depth(), result='done', color='BLUE')
|
|
||||||
ctx.setenv('') # save env changes
|
|
||||||
ctx.env = saveenv # but use previous
|
|
||||||
depth_pop()
|
|
||||||
else:
|
|
||||||
if not ctx.all_envs:
|
|
||||||
ctx.load_envs()
|
|
||||||
for name in names_lst:
|
|
||||||
if name in ctx.env.IGNORED_SUBDIRS:
|
|
||||||
continue
|
|
||||||
saveenv = ctx.env
|
|
||||||
ctx.env = ctx.all_envs[name]
|
|
||||||
ctx.recurse(name)
|
|
||||||
ctx.env = saveenv
|
|
@ -65,6 +65,11 @@ def configure(conf):
|
|||||||
except conf.errors.ConfigurationError:
|
except conf.errors.ConfigurationError:
|
||||||
conf.env.HAVE_SDL2 = 0
|
conf.env.HAVE_SDL2 = 0
|
||||||
|
|
||||||
|
if not conf.env.HAVE_SDL2 and conf.env.CONAN:
|
||||||
|
conf.load('conan')
|
||||||
|
conf.add_conan_remote('bincrafters', 'https://api.bintray.com/conan/bincrafters/public-conan')
|
||||||
|
conf.add_dependency('sdl2/2.0.9@bincrafters/stable', options = { 'shared': 'True' } )
|
||||||
|
|
||||||
if conf.env.HAVE_SDL2 and conf.options.SDL2_SANITY_CHECK:
|
if conf.env.HAVE_SDL2 and conf.options.SDL2_SANITY_CHECK:
|
||||||
try:
|
try:
|
||||||
conf.check_cc(
|
conf.check_cc(
|
@ -11,7 +11,8 @@
|
|||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
from fwgslib import get_flags_by_compiler
|
try: from fwgslib import get_flags_by_compiler
|
||||||
|
except: from waflib.extras.fwgslib import get_flags_by_compiler
|
||||||
from waflib import Logs
|
from waflib import Logs
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
12
wscript
12
wscript
@ -7,10 +7,6 @@ from waflib import Logs
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
sys.path.append(os.path.realpath('scripts/waflib'))
|
|
||||||
# print(sys.path)
|
|
||||||
import fwgslib
|
|
||||||
|
|
||||||
VERSION = '0.99'
|
VERSION = '0.99'
|
||||||
APPNAME = 'xash3d-fwgs'
|
APPNAME = 'xash3d-fwgs'
|
||||||
top = '.'
|
top = '.'
|
||||||
@ -71,7 +67,7 @@ def options(opt):
|
|||||||
|
|
||||||
|
|
||||||
def configure(conf):
|
def configure(conf):
|
||||||
conf.load('reconfigure')
|
conf.load('fwgslib reconfigure')
|
||||||
conf.start_msg('Build type')
|
conf.start_msg('Build type')
|
||||||
if conf.options.BUILD_TYPE == None:
|
if conf.options.BUILD_TYPE == None:
|
||||||
conf.end_msg('not set', color='RED')
|
conf.end_msg('not set', color='RED')
|
||||||
@ -163,11 +159,11 @@ def configure(conf):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.env.append_unique('CFLAGS', fwgslib.get_flags_by_type(
|
conf.env.append_unique('CFLAGS', conf.get_flags_by_type(
|
||||||
compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC))
|
compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC))
|
||||||
conf.env.append_unique('CXXFLAGS', fwgslib.get_flags_by_type(
|
conf.env.append_unique('CXXFLAGS', conf.get_flags_by_type(
|
||||||
compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC))
|
compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC))
|
||||||
conf.env.append_unique('LINKFLAGS', fwgslib.get_flags_by_type(
|
conf.env.append_unique('LINKFLAGS', conf.get_flags_by_type(
|
||||||
linker_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC))
|
linker_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC))
|
||||||
|
|
||||||
conf.env.DEDICATED = conf.options.DEDICATED
|
conf.env.DEDICATED = conf.options.DEDICATED
|
||||||
|
Loading…
x
Reference in New Issue
Block a user