echo Loading VS environment | echo Loading VS environment | ||||
call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | ||||
echo Executing build/test script | echo Executing build/test script | ||||
python -u build.py --cxx cl.exe --test --static || exit 1 | |||||
python -u tools/build.py --cxx cl.exe --test --static || exit 1 | |||||
displayName: Build and Run Unit Tests | displayName: Build and Run Unit Tests | ||||
- publish: _build/ddslim.exe | - publish: _build/ddslim.exe | ||||
artifact: DDSLiM Executable - Windows | artifact: DDSLiM Executable - Windows | ||||
- script: | | - script: | | ||||
echo Loading VS environment | echo Loading VS environment | ||||
call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | ||||
python -u test.py --exe _build/ddslim -T:msvc || exit 1 | |||||
python -u tools/test.py --exe _build/ddslim -T:msvc || exit 1 | |||||
displayName: Smoke Tests | displayName: Smoke Tests | ||||
- job: Windows_MSVC_VS2019 | - job: Windows_MSVC_VS2019 | ||||
echo Loading VS environment | echo Loading VS environment | ||||
call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | ||||
echo Executing build/test script | echo Executing build/test script | ||||
python -u build.py --cxx cl.exe --test --static || exit 1 | |||||
python -u tools/build.py --cxx cl.exe --test --static || exit 1 | |||||
displayName: Build and Run Unit Tests | displayName: Build and Run Unit Tests | ||||
- publish: _build/ddslim.exe | - publish: _build/ddslim.exe | ||||
artifact: DDSLiM Executable - Windows | artifact: DDSLiM Executable - Windows | ||||
- script: | | - script: | | ||||
echo Loading VS environment | echo Loading VS environment | ||||
call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\Common7\\Tools\\vsdevcmd" -arch=x64 || exit 1 | ||||
python -u test.py --exe _build/ddslim -T:msvc || exit 1 | |||||
python -u tools/test.py --exe _build/ddslim -T:msvc || exit 1 | |||||
displayName: Smoke Tests | displayName: Smoke Tests | ||||
- job: Linux_GCC | - job: Linux_GCC | ||||
steps: | steps: | ||||
- script: sudo apt install -y python3-minimal g++-8 | - script: sudo apt install -y python3-minimal g++-8 | ||||
displayName: Prepare System | displayName: Prepare System | ||||
- script: python3 -u build.py --cxx g++-8 --test --static | |||||
- script: python3 -u tools/build.py --cxx g++-8 --test --static | |||||
displayName: Build and Run Unit Tests | displayName: Build and Run Unit Tests | ||||
- publish: _build/ddslim | - publish: _build/ddslim | ||||
artifact: DDSLiM Executable - Linux | artifact: DDSLiM Executable - Linux | ||||
- script: python3 -u test.py --exe _build/ddslim -T:gcc-8 | |||||
- script: python3 -u tools/test.py --exe _build/ddslim -T:gcc-8 | |||||
displayName: Smoke Tests | displayName: Smoke Tests | ||||
- job: macOS | - job: macOS | ||||
steps: | steps: | ||||
- script: brew install gcc@8 | - script: brew install gcc@8 | ||||
displayName: Prepare System | displayName: Prepare System | ||||
- script: python3 -u build.py --cxx g++-8 --test | |||||
- script: python3 -u tools/build.py --cxx g++-8 --test | |||||
displayName: Build and Run Unit Tests | displayName: Build and Run Unit Tests | ||||
- publish: _build/ddslim | - publish: _build/ddslim | ||||
artifact: DDSLiM Executable - macOS | artifact: DDSLiM Executable - macOS | ||||
- script: python3 -u test.py --exe _build/ddslim -T:gcc-8 | |||||
- script: python3 -u tools/test.py --exe _build/ddslim -T:gcc-8 | |||||
displayName: Smoke Tests | displayName: Smoke Tests |
import time | import time | ||||
import sys | import sys | ||||
HERE_DIR = Path(__file__).parent.absolute() | |||||
ROOT = Path(__file__).parent.parent.absolute() | |||||
INCLUDE_DIRS = [ | INCLUDE_DIRS = [ | ||||
'external/taywee-args/include', | 'external/taywee-args/include', | ||||
if not opts.is_msvc: | if not opts.is_msvc: | ||||
cmd = [ | cmd = [ | ||||
str(opts.cxx), | str(opts.cxx), | ||||
f'-I{HERE_DIR / "src"}', | |||||
f'-I{ROOT / "src"}', | |||||
'-std=c++17', | '-std=c++17', | ||||
'-Wall', | '-Wall', | ||||
'-Wextra', | '-Wextra', | ||||
else: | else: | ||||
cmd.append('-O2') | cmd.append('-O2') | ||||
cmd.extend( | cmd.extend( | ||||
itertools.chain.from_iterable(('-isystem', str(HERE_DIR / subdir)) | |||||
itertools.chain.from_iterable(('-isystem', str(ROOT / subdir)) | |||||
for subdir in INCLUDE_DIRS)) | for subdir in INCLUDE_DIRS)) | ||||
return cmd | return cmd | ||||
else: | else: | ||||
'/EHsc', | '/EHsc', | ||||
'/std:c++latest', | '/std:c++latest', | ||||
'/DFMT_HEADER_ONLY=1', | '/DFMT_HEADER_ONLY=1', | ||||
f'/I{HERE_DIR / "src"}', | |||||
f'/I{ROOT / "src"}', | |||||
str(cpp_file), | str(cpp_file), | ||||
'/c', | '/c', | ||||
f'/Fo{obj_file}', | f'/Fo{obj_file}', | ||||
cmd.append('/MT') | cmd.append('/MT') | ||||
else: | else: | ||||
cmd.append('/MD') | cmd.append('/MD') | ||||
cmd.extend(f'/I{HERE_DIR / subdir}' for subdir in INCLUDE_DIRS) | |||||
cmd.extend(f'/I{ROOT / subdir}' for subdir in INCLUDE_DIRS) | |||||
return cmd | return cmd | ||||
def _compile_src(opts: BuildOptions, cpp_file: Path) -> Tuple[Path, Path]: | def _compile_src(opts: BuildOptions, cpp_file: Path) -> Tuple[Path, Path]: | ||||
build_dir = HERE_DIR / '_build' | |||||
src_dir = HERE_DIR / 'src' | |||||
build_dir = ROOT / '_build' | |||||
src_dir = ROOT / 'src' | |||||
relpath = cpp_file.relative_to(src_dir) | relpath = cpp_file.relative_to(src_dir) | ||||
obj_path = build_dir / relpath.with_name(relpath.name + opts.obj_suffix) | obj_path = build_dir / relpath.with_name(relpath.name + opts.obj_suffix) | ||||
obj_path.parent.mkdir(exist_ok=True, parents=True) | obj_path.parent.mkdir(exist_ok=True, parents=True) | ||||
cmd = _create_compile_command(opts, cpp_file, obj_path) | cmd = _create_compile_command(opts, cpp_file, obj_path) | ||||
msg = f'Compile C++ file: {cpp_file}' | |||||
msg = f'Compile C++ file: {cpp_file.relative_to(ROOT)}' | |||||
print(msg) | print(msg) | ||||
start = time.time() | start = time.time() | ||||
res = subprocess.run( | res = subprocess.run( | ||||
raise RuntimeError( | raise RuntimeError( | ||||
f'Compile command ({cmd}) failed for {cpp_file}:\n{res.stdout.decode()}' | f'Compile command ({cmd}) failed for {cpp_file}:\n{res.stdout.decode()}' | ||||
) | ) | ||||
if res.stdout: | |||||
print(res.stdout.decode()) | |||||
stdout: str = res.stdout.decode() | |||||
fname_head = f'{cpp_file.name}\r\n' | |||||
if stdout.startswith(fname_head): | |||||
stdout = stdout[len(fname_head):] | |||||
if stdout: | |||||
print(stdout, end='') | |||||
end = time.time() | end = time.time() | ||||
print(f'{msg} - Done: {end - start:.2}s') | print(f'{msg} - Done: {end - start:.2}s') | ||||
return cpp_file, obj_path | return cpp_file, obj_path | ||||
def _create_archive_command(opts: BuildOptions, | def _create_archive_command(opts: BuildOptions, | ||||
objects: Iterable[Path]) -> Tuple[Path, List[str]]: | objects: Iterable[Path]) -> Tuple[Path, List[str]]: | ||||
if opts.is_msvc: | if opts.is_msvc: | ||||
lib_file = HERE_DIR / '_build/libddslim.lib' | |||||
lib_file = ROOT / '_build/libddslim.lib' | |||||
cmd = ['lib', '/nologo', f'/OUT:{lib_file}', *map(str, objects)] | cmd = ['lib', '/nologo', f'/OUT:{lib_file}', *map(str, objects)] | ||||
return lib_file, cmd | return lib_file, cmd | ||||
else: | else: | ||||
lib_file = HERE_DIR / '_build/libddslim.a' | |||||
lib_file = ROOT / '_build/libddslim.a' | |||||
cmd = ['ar', 'rsc', str(lib_file), *map(str, objects)] | cmd = ['ar', 'rsc', str(lib_file), *map(str, objects)] | ||||
return lib_file, cmd | return lib_file, cmd | ||||
out: Path = None) -> Path: | out: Path = None) -> Path: | ||||
if out is None: | if out is None: | ||||
basename = obj.stem | basename = obj.stem | ||||
out = HERE_DIR / '_build/test' / (basename + '.exe') | |||||
out = ROOT / '_build/test' / (basename + '.exe') | |||||
out.parent.mkdir(exist_ok=True, parents=True) | out.parent.mkdir(exist_ok=True, parents=True) | ||||
print(f'Linking executable {out}') | print(f'Linking executable {out}') | ||||
'--static', action='store_true', help='Build a static executable') | '--static', action='store_true', help='Build a static executable') | ||||
args = parser.parse_args(argv) | args = parser.parse_args(argv) | ||||
all_sources = set(HERE_DIR.glob('src/**/*.cpp')) | |||||
test_sources = set(HERE_DIR.glob('src/**/*.test.cpp')) | |||||
main_sources = set(HERE_DIR.glob('src/**/*.main.cpp')) | |||||
all_sources = set(ROOT.glob('src/**/*.cpp')) | |||||
test_sources = set(ROOT.glob('src/**/*.test.cpp')) | |||||
main_sources = set(ROOT.glob('src/**/*.main.cpp')) | |||||
lib_sources = (all_sources - test_sources) - main_sources | lib_sources = (all_sources - test_sources) - main_sources | ||||
build_opts, | build_opts, | ||||
objects[next(iter(main_sources))], | objects[next(iter(main_sources))], | ||||
lib, | lib, | ||||
out=HERE_DIR / '_build/ddslim') | |||||
out=ROOT / '_build/ddslim') | |||||
if args.test: | if args.test: | ||||
list(pool.map(run_test, test_exes)) | list(pool.map(run_test, test_exes)) |
import sys | import sys | ||||
ROOT = Path(__file__).parent.parent.absolute() | |||||
class TestOptions(NamedTuple): | class TestOptions(NamedTuple): | ||||
exe: Path | exe: Path | ||||
toolchain: str | toolchain: str | ||||
def run_test_dir(dir: Path, opts: TestOptions) -> bool: | def run_test_dir(dir: Path, opts: TestOptions) -> bool: | ||||
print(f'Running test: {dir.name} ', end='') | |||||
print(f'Running test: {dir.stem} ', end='') | |||||
out_dir = dir / '_build' | out_dir = dir / '_build' | ||||
if out_dir.exists(): | if out_dir.exists(): | ||||
shutil.rmtree(out_dir) | shutil.rmtree(out_dir) | ||||
def run_tests(opts: TestOptions) -> int: | def run_tests(opts: TestOptions) -> int: | ||||
print('Sanity check...') | print('Sanity check...') | ||||
subprocess.check_output([str(opts.exe), '--help']) | subprocess.check_output([str(opts.exe), '--help']) | ||||
tests_subdir = Path(__file__).parent.absolute() / 'tests' | |||||
tests_subdir = ROOT / 'tests' | |||||
test_dirs = tests_subdir.glob('*.test') | test_dirs = tests_subdir.glob('*.test') | ||||
ret = 0 | ret = 0 |