Replacing python stuff with BAT, 1993-style.

This commit is contained in:
Ben Vanik 2015-05-02 21:46:42 -07:00
parent ce7270b839
commit 519fefd58d
10 changed files with 550 additions and 858 deletions

View File

@ -1,23 +0,0 @@
# Make Travis use docker (for faster builds, in theory)
sudo: false
language: cpp
compiler:
- clang
# - gcc don't really care
os:
- linux
- osx # beta only
# Run setup to build ninja/gyp/etc and actually build xenia.
before_script:
- travis_retry ./xenia-build.py setup
- ./xenia-build.py build --debug alloy-test
- ./xenia-build.py build --debug alloy-ppc-test
# Run test suite.
script:
- ./build/xenia/Debug/alloy-test
- ./build/xenia/Debug/alloy-ppc-test --runtime_backend=ivm
- ./build/xenia/Debug/alloy-ppc-test --runtime_backend=x64

View File

@ -35,13 +35,15 @@ legally purchased devices and games and information made public on the internet
## Quickstart
Windows 8.1+:
Windows 8.1+ with Python 2.7 and Visual Studio 2015 installed:
# install python 2.7 and VS2015
git clone https://github.com/benvanik/xenia.git
cd xenia
xb setup
# open build\xenia\xenia.sln and start xenia-run
> git clone https://github.com/benvanik/xenia.git
> cd xenia
> xb setup
# Build on command line:
> xb build
# Open Visual Studio (run the 'xenia' project):
> xb edit
When fetching updates use `xb pull` to automatically fetch everything and
update gyp files/etc.

View File

@ -1,176 +0,0 @@
#---------------------------------#
# general configuration #
#---------------------------------#
# version format
version: 1.0.{build} # You can use {branch} too, for example
# you can use {branch} name in version format too
# version: 1.0.{build}-{branch}
# branches to build
branches:
# blacklist
except:
- gh-pages
# Do not build on tags (GitHub only)
skip_tags: true
#---------------------------------#
# environment configuration #
#---------------------------------#
# Operating system (build VM template)
os: Visual Studio 2015 CTP
# scripts that are called at very beginning, before repo cloning
init:
- git config --global core.autocrlf input
# clone directory
clone_folder: c:\dev\xenia
# environment variables
environment:
my_var1: value1
my_var2: value2
# scripts that run after cloning repository
install:
- cmd: set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
- cmd: tools\buildbot\setup.bat
#---------------------------------#
# build configuration #
#---------------------------------#
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
platform: x64
# build Configuration, i.e. Debug, Release, etc.
configuration: Debug
build:
parallel: true # enable MSBuild parallel builds
project: build\xenia\xenia.sln # path to Visual Studio solution or project
# MSBuild verbosity level
#verbosity: quiet|minimal|normal|detailed
verbosity: detailed
# scripts to run before build
before_build:
# scripts to run after build
after_build:
# to run your custom scripts instead of automatic MSBuild
#build_script:
# - cmd: tools\buildbot\build.bat
# to disable automatic builds
#build: off
#---------------------------------#
# tests configuration #
#---------------------------------#
# scripts to run before tests
before_test:
# scripts to run after tests
after_test:
# to run your custom scripts instead of automatic tests
test_script:
- cmd: tools\buildbot\test.bat
# to disable automatic tests
#test: off
#---------------------------------#
# artifacts configuration #
#---------------------------------#
#artifacts:
# pushing a single file
#- path: test.zip
# pushing entire folder as a zip archive
#- path: logs
# pushing all *.nupkg files in directory
#- path: out\*.nupkg
#---------------------------------#
# deployment configuration #
#---------------------------------#
# providers: Local, FTP, WebDeploy, AzureCS, AzureBlob, S3, NuGet, Environment
# provider names are case-sensitive!
#deploy:
# Deploy to GitHub Releases
#- provider: GitHub
# artifact: /.*\.nupkg/ # upload all NuGet packages to release assets
# draft: false
# prerelease: false
# on:
# branch: master # release from master branch only
# appveyor_repo_tag: true # deploy on tag push only
# scripts to run before deployment
before_deploy:
# scripts to run after deployment
after_deploy:
# to run your custom scripts instead of provider deployments
deploy_script:
# to disable deployment
deploy: off
#---------------------------------#
# global handlers #
#---------------------------------#
# on successful build
on_success:
# on build failure
on_failure:
# after build failure or success
on_finish:
#---------------------------------#
# notifications #
#---------------------------------#
# notifications:
# # Email
# - provider: Email
# to:
# - user1@email.com
# - user2@email.com
# subject: 'Build {{status}}' # optional
# message: "{{message}}, {{commitId}}, ..." # optional
# on_build_status_changed: true
# # Webhook
# - provider: Webhook
# url: http://www.myhook2.com
# headers:
# User-Agent: myapp 1.0
# Authorization:
# secure: GhD+5xhLz/tkYY6AO3fcfQ==
# on_build_success: false
# on_build_failure: true
# on_build_status_changed: true

View File

@ -25,81 +25,6 @@ and set the 'Command' to `$(SolutionDir)$(TargetPath)` and the
'Working Directory' to `$(SolutionDir)..\..`. You can specify flags and
the file to run in the 'Command Arguments' field (or use `--flagfile=flags.txt`).
### OSX
* Mac OSX 10.9+
* Xcode 5.1+
#### Debugging
Choose `Product > Scheme > Edit Scheme`. For xenia, alloy-sandbox, and the
other executables select the Run action on the left and set
`Options > Working Directory` to your root xenia/ git path.
## xenia-build
A simple build script is included to manage basic tasks such as building
dependencies.
./xenia-build.py --help
On Windows the `xb.bat` file enables you to issue all commands by just typing
`xb`. Note that you should run everything from the root `xenia\` folder.
On Linux/OSX the `xeniarc` bash file has some aliases that save some
keypresses:
source xeniarc
xb -> python xenia-build.py
xbb -> python xenia-build.py build
xbc -> python xenia-build.py clean
### Commands
#### setup
Run this on initial checkout to pull down all dependencies and submodules.
xb setup
#### pull
Does a `git pull` in addition to updating submodules and rebuilding dependencies
and gyp outputs. Use this, if possible, instead of git pull.
xb pull
#### gyp
Updates all of the supported gyp projects. If you're using Visual Studio or
Xcode to build or debug your projects you'll need to run this after you change
gyp/gypi files.
xb gyp
#### build
Builds all xenia targets using ninja. Release is built by default; specify
`--debug` to build the debug configuration.
xb build
xb build --debug
#### clean
Cleans just xenia outputs from the build/ directory. A following build will just
have the rebuild xenia and not all of the dependencies.
xb clean
#### nuke
Cleans up xenia outputs as well as all dependencies. A full build will be
required after this so only do this if you want to reclaim your disk space or
something is really wrong.
xb nuke
## Running
Use the wrapper shell scripts under `bin/` to run tools. They will ensure the
@ -108,9 +33,3 @@ switching between the debug and release variants with `--debug`.
To make life easier you can use `--flagfile=myflags.txt` to specify all
arguments, including using `--target=my.xex` to pick an executable.
### xenia
Runs a xex.
./bin/xenia some.xex

View File

@ -1,3 +0,0 @@
@ECHO OFF
python xenia-build.py build --debug

View File

@ -1,3 +0,0 @@
REM @ECHO OFF
python xenia-build.py setup --no-ninja

View File

@ -1,4 +0,0 @@
@ECHO OFF
build\xenia\Debug\alloy-test
build\xenia\Debug\alloy-ppc-test --runtime_backend=x64

544
xb.bat
View File

@ -1,6 +1,546 @@
@ECHO OFF
REM Copyright 2013 Ben Vanik. All Rights Reserved.
REM Copyright 2015 Ben Vanik. All Rights Reserved.
TITLE xenia
SET DIR=%~dp0
python xenia-build.py %*
SET XENIA_SLN=build\xenia\xenia.sln
REM ============================================================================
REM Environment Validation
REM ============================================================================
REM To make life easier we just require everything before we try running.
CALL :check_git
IF %_RESULT% NEQ 0 (
ECHO ERROR:
ECHO git must be installed and on PATH.
GOTO :exit_error
)
CALL :check_python
IF %_RESULT% NEQ 0 (
ECHO ERROR:
ECHO Python 2.7 must be installed and on PATH:
ECHO https://www.python.org/ftp/python/2.7.9/python-2.7.9.msi
GOTO :exit_error
)
CALL :check_msvc
IF %_RESULT% NEQ 0 (
ECHO ERROR:
ECHO Visual Studio 2015 must be installed.
ECHO.
ECHO The Community Edition is free and can be downloaded here:
ECHO https://www.visualstudio.com/downloads/visual-studio-2015-downloads-vs
ECHO.
ECHO Once installed, launch the 'Developer Command Prompt for VS2015' and run
ECHO this script again.
GOTO :exit_error
)
REM ============================================================================
REM Command Parsing
REM ============================================================================
SET _RESULT=-2
REM Ensure a command has been passed.
IF -%1-==-- GOTO :show_help
REM Dispatch to handler (:perform_foo).
2>NUL CALL :perform_%1 %*
IF %_RESULT% EQU -2 GOTO :show_help
IF %_RESULT% EQU -1 GOTO :exit_nop
IF %_RESULT% EQU 0 GOTO :exit_success
GOTO :exit_error
:exit_success
ECHO.
ECHO OK
EXIT /b 0
:exit_error
ECHO.
ECHO Error: %_RESULT%
EXIT /b 1
:exit_nop
ECHO.
ECHO (no actions performed)
EXIT /b 0
REM ============================================================================
REM xb help
REM ============================================================================
:show_help
SETLOCAL
ECHO.
ECHO Usage: xb COMMAND [options]
ECHO.
ECHO Commands:
ECHO.
ECHO xb setup
ECHO Initializes dependencies and prepares build environment.
ECHO.
ECHO xb pull [--rebase]
ECHO Fetches latest changes from github and rebuilds dependencies.
ECHO.
ECHO xb gyp
ECHO Creates/updates xenia.sln and project files. Use after changing gypi.
ECHO.
ECHO xb edit
ECHO Opens Visual Studio with `xenia.sln`.
ECHO.
ECHO xb build [--debug OR --release] [--force]
ECHO Initializes dependencies and prepares build environment.
ECHO.
ECHO xb test [--debug OR --release] [--continue]
ECHO Runs automated tests. Tests must have been built with `xb build`.
ECHO.
ECHO xb clean
ECHO Cleans normal build artifacts to force a rebuild.
ECHO.
ECHO xb nuke
ECHO Resets branch and build environment to defaults to unhose state.
ECHO.
ECHO xb lint [--all]
ECHO Runs linter on local changes (or entire codebase).
ECHO.
ECHO xb format [--all]
ECHO Runs linter/auto-formatter on local changes (or entire codebase).
ECHO.
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb setup
REM ============================================================================
:perform_setup
SETLOCAL
ECHO Setting up the build environment...
ECHO.
ECHO ^> git submodule update --init
git submodule update --init
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ERROR: failed to initialize git submodules
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ECHO.
ECHO ^> generating projects...
CALL :generate_projects
IF %_RESULT% NEQ 0 (
ECHO.
ECHO ERROR: failed to generate projects
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb pull
REM ============================================================================
:perform_pull
SETLOCAL
SET REBASE=0
SHIFT
:perform_pull_args
IF "%~1"=="" GOTO :perform_pull_parsed
IF "%~1"=="--" GOTO :perform_pull_parsed
IF "%~1"=="--rebase" (SET REBASE=1)
SHIFT
GOTO :perform_pull_args
:perform_pull_parsed
ECHO Pulling latest changes and rebuilding dependencies...
ECHO.
ECHO ^> git checkout master
git checkout master
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ERROR: failed to checkout master
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ECHO.
IF %REBASE% EQU 1 (
ECHO ^> git pull --rebase
git pull --rebase
) ELSE (
ECHO ^> git pull
git pull
)
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ERROR: failed to pull latest changes from git
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ECHO.
ECHO ^> git submodule update
git submodule update
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ERROR: failed to update git submodules
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ECHO.
ECHO ^> generating projects...
CALL :generate_projects
IF %_RESULT% NEQ 0 (
ECHO.
ECHO ERROR: failed to generate projects
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb gyp
REM ============================================================================
:perform_gyp
SETLOCAL
ECHO Generating projects...
ECHO.
ECHO ^> generating projects...
CALL :generate_projects
IF %_RESULT% NEQ 0 (
ECHO.
ECHO ERROR: failed to generate projects
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb edit
REM ============================================================================
:perform_edit
SETLOCAL
ECHO Launching Visual Studio...
ECHO.
ECHO ^> generating projects...
CALL :generate_projects
IF %_RESULT% NEQ 0 (
ECHO.
ECHO ERROR: failed to generate projects
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ECHO.
ECHO ^> devenv %XENIA_SLN%
START devenv %XENIA_SLN%
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb build
REM ============================================================================
:perform_build
SETLOCAL
SET CONFIG="debug"
SET FORCE=0
SHIFT
:perform_build_args
IF "%~1"=="" GOTO :perform_build_parsed
IF "%~1"=="--" GOTO :perform_build_parsed
IF "%~1"=="--debug" (SET CONFIG="debug")
IF "%~1"=="--release" (SET CONFIG="release")
IF "%~1"=="--force" (SET FORCE=1)
SHIFT
GOTO :perform_build_args
:perform_build_parsed
ECHO Building for config %CONFIG%...
ECHO.
ECHO ^> generating projects...
CALL :generate_projects
IF %_RESULT% NEQ 0 (
ECHO.
ECHO ERROR: failed to generate projects
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
IF %FORCE% EQU 1 (
SET DEVENV_COMMAND=/rebuild
) ELSE (
SET DEVENV_COMMAND=/build
)
ECHO.
ECHO ^> devenv %XENIA_SLN% %DEVENV_COMMAND% %CONFIG%
devenv %XENIA_SLN% /nologo %DEVENV_COMMAND% %CONFIG%
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ERROR: build failed with errors
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb test
REM ============================================================================
:perform_test
SETLOCAL EnableDelayedExpansion
SET BUILD=1
SET CONFIG="debug"
SET CONTINUE=0
SHIFT
:perform_test_args
IF "%~1"=="" GOTO :perform_test_parsed
IF "%~1"=="--" GOTO :perform_test_parsed
IF "%~1"=="--debug" (SET CONFIG="debug")
IF "%~1"=="--release" (SET CONFIG="release")
IF "%~1"=="--continue" (SET CONTINUE=1)
SHIFT
GOTO :perform_test_args
:perform_test_parsed
ECHO Running automated testing for config %CONFIG%...
SET TEST_NAMES=xe-cpu-hir-test xe-cpu-ppc-test
FOR %%G IN (%TEST_NAMES%) DO (
IF NOT EXIST build\xenia\%CONFIG%\%%G.exe (
ECHO.
ECHO ERROR: unable to find `%%G.exe` - ensure it is built.
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
)
SET ANY_FAILED=0
FOR %%G IN (%TEST_NAMES%) DO (
ECHO.
ECHO ^> build\xenia\%CONFIG%\%%G.exe
build\xenia\%CONFIG%\%%G.exe
IF !ERRORLEVEL! NEQ 0 (
SET ANY_FAILED=1
IF %CONTINUE% EQU 0 (
ECHO.
ECHO ERROR: test failed, aborting, use --continue to keep going
ENDLOCAL & SET _RESULT=1
GOTO :eof
) ELSE (
ECHO.
ECHO ERROR: test failed but continuing due to --continue
)
)
)
IF %ANY_FAILED% NEQ 0 (
ECHO.
ECHO ERROR: one or more tests failed
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb clean
REM ============================================================================
:perform_clean
SETLOCAL
ECHO Cleaning normal build outputs...
ECHO (use nuke to kill all artifacts)
SET CONFIG_NAMES=Debug Release
FOR %%G IN (%CONFIG_NAMES%) DO (
ECHO.
ECHO ^> devenv %XENIA_SLN% /clean %%G
devenv %XENIA_SLN% /nologo /clean %%G
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb nuke
REM ============================================================================
:perform_nuke
SETLOCAL
ECHO Nuking all local changes...
ECHO.
REM rmdir build/
REM git checkout --hard /etc
ECHO TODO(benvanik): blast away build/ for now
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb lint
REM ============================================================================
:perform_lint
SETLOCAL
SET ALL=0
SHIFT
:perform_lint_args
IF "%~1"=="" GOTO :perform_lint_parsed
IF "%~1"=="--" GOTO :perform_lint_parsed
IF "%~1"=="--all" (SET ALL=1)
SHIFT
GOTO :perform_lint_args
:perform_lint_parsed
IF %ALL% EQU 1 (
ECHO Running code linter on all code...
) ELSE (
ECHO Running code linter on code staged in git index...
)
ECHO.
REM --all
REM run lint
ECHO TODO(benvanik): just `xb format`
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM xb format
REM ============================================================================
:perform_format
SETLOCAL EnableDelayedExpansion
SET ALL=0
SHIFT
:perform_format_args
IF "%~1"=="" GOTO :perform_format_parsed
IF "%~1"=="--" GOTO :perform_format_parsed
IF "%~1"=="--all" (SET ALL=1)
SHIFT
GOTO :perform_format_args
:perform_format_parsed
IF %ALL% EQU 1 (
ECHO Running code formatter on all code...
) ELSE (
ECHO Running code formatter on code staged in git index...
)
SET CLANG_FORMAT=""
SET LLVM_CLANG_FORMAT="C:\Program Files (x86)\LLVM\bin\clang-format.exe"
IF EXIST %LLVM_CLANG_FORMAT% (
SET CLANG_FORMAT=%LLVM_CLANG_FORMAT%
) ELSE (
1>NUL 2>NUL CMD /c where clang-format
IF %ERRORLEVEL% NEQ 0 (
SET CLANG_FORMAT="clang-format"
)
)
IF %CLANG_FORMAT%=="" (
ECHO.
ECHO ERROR: clang-format is not on PATH or the standard location.
ECHO LLVM is available from http://llvm.org/releases/download.html
ECHO See docs/style_guide.md for instructions on how to get it.
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
IF %ALL% NEQ 1 (
ECHO.
ECHO ^> git-clang-format
CMD /c python third_party/clang-format/git-clang-format --binary=%CLANG_FORMAT% --commit=HEAD
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ERROR: clang-format failed - ensure all files are staged
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
) ELSE (
SET ANY_ERRORS=0
ECHO.
ECHO ^> clang-format (all)
PUSHD src
FOR /R %%G in (*.cc *.c *.h *.inl) DO (
ECHO ^> clang-format %%G
CMD /C %CLANG_FORMAT% -i -style=file %%G
IF !ERRORLEVEL! NEQ 0 (
SET ANY_ERRORS=1
)
)
POPD
IF %ANY_ERRORS% NEQ 0 (
ECHO FOOO
)
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
REM ============================================================================
REM Utilities
REM ============================================================================
:check_python
SETLOCAL
1>NUL 2>NUL CMD /c where python
IF %ERRORLEVEL% NEQ 0 (
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
CMD /c python -c "import sys; sys.exit(1 if sys.version_info[:2] != (2, 7) else 0)"
IF %ERRORLEVEL% NEQ 0 (
ENDLOCAL & SET _RESULT=1
GOTO :eof
)
ENDLOCAL & SET _RESULT=0
GOTO :eof
:check_git
1>NUL 2>NUL CMD /c where git
SET _RESULT=%ERRORLEVEL%
GOTO :eof
:check_msvc
1>NUL 2>NUL CMD /c where devenv
SET _RESULT=%ERRORLEVEL%
IF %_RESULT% NEQ 0 GOTO :eof
SET _RESULT=1
IF "%VS140COMNTOOLS%" NEQ "" (
IF EXIST "%VS140COMNTOOLS%" (
REM VS2015 CTP/RC
SET _RESULT=0
)
)
IF "%VS150COMNTOOLS%" NEQ "" (
IF EXIST "%VS150COMNTOOLS%" (
REM VS2015
SET _RESULT=0
)
)
GOTO :eof
:generate_projects
CALL third_party\gyp\gyp.bat -f msvs -G output_dir=. --depth=. --toplevel-dir=. --generator-output=build/xenia/ -G msvs_version=2015 -D windows_sdk_dir="C:\Program Files (x86)\Windows Kits\8.1" xenia.gyp
SET _RESULT=%ERRORLEVEL%
GOTO :eof

View File

@ -1,552 +0,0 @@
#!/usr/bin/env python
# Copyright 2013 Ben Vanik. All Rights Reserved.
"""
"""
__author__ = 'ben.vanik@gmail.com (Ben Vanik)'
import os
import re
import shutil
import subprocess
import sys
def main():
# Add self to the root search path.
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
# Augment path to include our fancy things.
os.environ['PATH'] += os.pathsep + os.pathsep.join([
os.path.abspath('third_party/ninja/'),
os.path.abspath('third_party/gyp/')
])
# Check python version.
if not sys.version_info[:2] == (2, 7):
print('ERROR: python 2.7 required')
print('(unfortunately gyp doesn\'t work with 3!)')
sys.exit(1)
return
# Grab Visual Studio version and execute shell to set up environment.
if sys.platform == 'win32':
vs_version = import_vs_environment()
if vs_version != 2015:
print('ERROR: Visual Studio 2015 not found!')
print('Ensure you have the VS140COMNTOOLS environment variable!')
sys.exit(1)
return
# Grab all commands.
commands = discover_commands()
# Parse command name and dispatch.
try:
if len(sys.argv) < 2:
raise ValueError('No command given')
command_name = sys.argv[1]
if not command_name in commands:
raise ValueError('Command "%s" not found' % (command_name))
command = commands[command_name]
return_code = run_command(command=command,
args=sys.argv[2:],
cwd=os.getcwd())
except ValueError:
print(usage(commands))
return_code = 1
except Exception as e:
#print e
raise
return_code = 1
sys.exit(return_code)
def import_vs_environment():
"""Finds the installed Visual Studio version and imports
interesting environment variables into os.environ.
Returns:
A version such as 2015 or None if no VS is found.
"""
version = 0
tools_path = ''
if 'VS150COMNTOOLS' in os.environ:
version = 2015
tools_path = os.environ['VS150COMNTOOLS']
elif 'VS140COMNTOOLS' in os.environ:
# TODO(benvanik): remove preview tools.
version = 2015
tools_path = os.environ['VS140COMNTOOLS']
if version == 0:
return None
tools_path = os.path.join(tools_path, '..\\..\\vc\\vcvarsall.bat')
args = [tools_path, '&&', 'set']
popen = subprocess.Popen(
args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
variables, _ = popen.communicate()
envvars_to_save = (
'devenvdir',
'include',
'lib',
'libpath',
'path',
'pathext',
'systemroot',
'temp',
'tmp',
'windowssdkdir',
)
for line in variables.splitlines():
for envvar in envvars_to_save:
if re.match(envvar + '=', line.lower()):
var, setting = line.split('=', 1)
if envvar == 'path':
setting = os.path.dirname(sys.executable) + os.pathsep + setting
os.environ[var.upper()] = setting
break
os.environ['VSVERSION'] = str(version)
return version
def discover_commands():
"""Looks for all commands and returns a dictionary of them.
In the future commands could be discovered on disk.
Returns:
A dictionary containing name-to-Command mappings.
"""
commands = {
'setup': SetupCommand(),
'pull': PullCommand(),
'gyp': GypCommand(),
'build': BuildCommand(),
'test': TestCommand(),
'clean': CleanCommand(),
'nuke': NukeCommand(),
'format': FormatCommand(),
}
return commands
def usage(commands):
"""Gets usage info that can be displayed to the user.
Args:
commands: A command dictionary from discover_commands.
Returns:
A string containing usage info and a command listing.
"""
s = 'xenia-build.py command [--help]\n'
s += '\n'
s += 'Commands:\n'
command_names = sorted(commands.keys())
for command_name in command_names:
s += ' %s\n' % (command_name)
command_help = commands[command_name].help_short
if command_help:
s += ' %s\n' % (command_help)
return s
def run_command(command, args, cwd):
"""Runs a command with the given context.
Args:
command: Command to run.
args: Arguments, with the app and command name stripped.
cwd: Current working directory.
Returns:
0 if the command succeeded and non-zero otherwise.
Raises:
ValueError: The command could not be found or was not specified.
"""
# TODO(benvanik): parse arguments/etc.
return command.execute(args, cwd)
def has_bin(bin):
"""Checks whether the given binary is present.
"""
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, bin)
if os.path.isfile(exe_file) and os.access(exe_file, os.X_OK):
return True
exe_file = exe_file + '.exe'
if os.path.isfile(exe_file) and os.access(exe_file, os.X_OK):
return True
return None
def shell_call(command, throw_on_error=True):
"""Executes a shell command.
Args:
command: Command to execute.
throw_on_error: Whether to throw an error or return the status code.
Returns:
If throw_on_error is False the status code of the call will be returned.
"""
if throw_on_error:
subprocess.check_call(command, shell=True)
return 0
else:
return subprocess.call(command, shell=True)
class Command(object):
"""Base type for commands.
"""
def __init__(self, name, help_short=None, help_long=None, *args, **kwargs):
"""Initializes a command.
Args:
name: The name of the command exposed to the management script.
help_short: Help text printed alongside the command when queried.
help_long: Extended help text when viewing command help.
"""
self.name = name
self.help_short = help_short
self.help_long = help_long
def execute(self, args, cwd):
"""Executes the command.
Args:
args: Arguments list.
cwd: Current working directory.
Returns:
Return code of the command.
"""
return 1
def post_update_deps(config):
"""Runs common tasks that should be executed after any deps are changed.
Args:
config: 'debug' or 'release'.
"""
pass
class SetupCommand(Command):
"""'setup' command."""
def __init__(self, *args, **kwargs):
super(SetupCommand, self).__init__(
name='setup',
help_short='Setup the build environment.',
*args, **kwargs)
def execute(self, args, cwd):
print('Setting up the build environment...')
print('')
# Setup submodules.
print('- git submodule init / update...')
shell_call('git submodule init')
shell_call('git submodule update')
print('')
# Disable core.filemode on Windows to prevent weird file mode diffs in git.
# TODO(benvanik): check cygwin test - may be wrong when using Windows python
if os.path.exists('/Cygwin.bat'):
print('- setting filemode off on cygwin...')
shell_call('git config core.filemode false')
shell_call('git submodule foreach git config core.filemode false')
print('')
# Run the ninja bootstrap to build it, if it's missing.
if (not '--no-ninja' in args and
not os.path.exists('third_party/ninja/ninja') and
not os.path.exists('third_party/ninja/ninja.exe')):
print('- preparing ninja...')
os.chdir('third_party/ninja')
# Windows needs --x64 to force building the 64-bit ninja.
extra_args = ''
#if sys.platform == 'win32':
# extra_args = '--x64'
shell_call('python configure.py --bootstrap ' + extra_args)
os.chdir(cwd)
print('')
# binutils (with vmx128).
print('- Building binutils...')
if sys.platform == 'win32':
# TODO(benvanik): cygwin or vagrant
print('WARNING: binutils build not supported yet')
else:
shell_call('third_party/binutils/build.sh')
print('')
post_update_deps('debug')
post_update_deps('release')
print('- running gyp...')
run_all_gyps()
print('')
print('Success!')
return 0
class PullCommand(Command):
"""'pull' command."""
def __init__(self, *args, **kwargs):
super(PullCommand, self).__init__(
name='pull',
help_short='Pulls the repo and all dependencies.',
*args, **kwargs)
def execute(self, args, cwd):
print('Pulling...')
print('')
print('- pulling self...')
shell_call('git pull')
print('')
print('- pulling dependencies...')
shell_call('git submodule update')
print('')
post_update_deps('debug')
post_update_deps('release')
print('- running gyp...')
run_all_gyps()
print('')
print('Success!')
return 0
def run_gyp(format):
"""Runs gyp on the main project with the given format.
Args:
format: gyp -f value.
"""
shell_call(' '.join([
'gyp',
'-f %s' % (format),
# Removes the out/ from ninja builds.
'-G output_dir=.',
'--depth=.',
'--toplevel-dir=.',
'--generator-output=build/xenia/',
# Set the VS version.
'-G msvs_version=%s' % (os.environ.get('VSVERSION', 2015)),
#'-D windows_sdk_dir=%s' % (os.environ['WINDOWSSDKDIR']),
'-D windows_sdk_dir="C:\\Program Files (x86)\\Windows Kits\\8.1"',
'xenia.gyp',
]))
def run_all_gyps():
"""Runs all gyp configurations.
"""
run_gyp('ninja')
if sys.platform == 'darwin':
run_gyp('xcode')
elif sys.platform == 'win32':
run_gyp('msvs')
class GypCommand(Command):
"""'gyp' command."""
def __init__(self, *args, **kwargs):
super(GypCommand, self).__init__(
name='gyp',
help_short='Runs gyp to update all projects.',
*args, **kwargs)
def execute(self, args, cwd):
print('Running gyp...')
print('')
# Update GYP.
run_all_gyps()
print('Success!')
return 0
class BuildCommand(Command):
"""'build' command."""
def __init__(self, *args, **kwargs):
super(BuildCommand, self).__init__(
name='build',
help_short='Builds the project.',
*args, **kwargs)
def execute(self, args, cwd):
# TODO(benvanik): add arguments:
# --force
debug = '--debug' in args
config = 'Debug' if debug else 'Release'
target = ''
for arg in args:
if not arg.startswith('--'):
target = arg
print('Building %s...' % (config))
print('')
print('- running gyp for ninja...')
run_gyp('ninja')
print('')
if not target:
print('- building all:%s...' % (config))
result = shell_call('ninja -C build/xenia/%s' % (config),
throw_on_error=False)
else:
print('- building %s:%s...' % (target, config))
result = shell_call('ninja -C build/xenia/%s %s' % (config, target),
throw_on_error=False)
print('')
if result != 0:
return result
print('Success!')
return 0
class TestCommand(Command):
"""'test' command."""
def __init__(self, *args, **kwargs):
super(TestCommand, self).__init__(
name='test',
help_short='Runs all tests.',
*args, **kwargs)
def execute(self, args, cwd):
print('Testing...')
print('')
# Run base CPU tests.
print('Launching xe-cpu-hir-test runner...')
result = shell_call('"build/xenia/Debug/xe-cpu-hir-test"')
print('')
if result != 0:
return result
# First run make and update all of the test files.
if sys.platform == 'win32':
# TODO(benvanik): use cygwin/vagrant/whatever
print('WARNING: test files not updated!');
else:
print('Updating test files...')
result = shell_call('./src/xenia/cpu/frontend/ppc/test/update.sh')
print('')
if result != 0:
return result
# Start the test runner.
print('Launching xe-cpu-ppc-test runner...')
result = shell_call('"build/xenia/Debug/xe-cpu-ppc-test"')
print('')
if result != 0:
return result
return result
class CleanCommand(Command):
"""'clean' command."""
def __init__(self, *args, **kwargs):
super(CleanCommand, self).__init__(
name='clean',
help_short='Removes intermediate files and build output.',
*args, **kwargs)
def execute(self, args, cwd):
print('Cleaning build artifacts...')
print('')
print('- removing build/xenia/...')
if os.path.isdir('build/xenia/'):
shutil.rmtree('build/xenia/')
print('')
print('Success!')
return 0
class NukeCommand(Command):
"""'nuke' command."""
def __init__(self, *args, **kwargs):
super(NukeCommand, self).__init__(
name='nuke',
help_short='Removes all build/ output.',
*args, **kwargs)
def execute(self, args, cwd):
print('Cleaning build artifacts...')
print('')
print('- removing build/...')
if os.path.isdir('build/'):
shutil.rmtree('build/')
print('')
print('Success!')
return 0
class FormatCommand(Command):
"""'format' command."""
def __init__(self, *args, **kwargs):
super(FormatCommand, self).__init__(
name='format',
help_short='Reformats staged code with clang-format.',
*args, **kwargs)
def execute(self, args, cwd):
print('Formatting staged code...')
print('')
binary = 'clang-format'
win32_binary = 'C:\\Program Files (x86)\\LLVM\\bin\\clang-format.exe'
if os.path.exists(win32_binary):
binary = win32_binary
if not has_bin(binary):
print 'ERROR: clang-format is not on PATH'
print 'LLVM is available from http://llvm.org/releases/download.html'
print 'See docs/style_guide.md for instructions on how to get it'
return 1
shell_call(' '.join([
'python third_party/clang-format/git-clang-format',
'--binary="%s"' % (binary),
'--commit=HEAD',
]))
return 0
if __name__ == '__main__':
main()

View File

@ -1,8 +0,0 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
# Bash aliases
alias xb='python xenia-build.py'
alias xbb='python xenia-build.py build'
alias xbt='python xenia-build.py test'
alias xbc='python xenia-build.py clean'