浏览代码

Merge branch 'develop' into feature/get-deps

default_compile_flags
vector-of-bool 5 年前
父节点
当前提交
7ef65b76e1
共有 9 个文件被更改,包括 93 次插入71 次删除
  1. +3
    -3
      azure-pipelines.yml
  2. +1
    -0
      src/dds/library_manifest.cpp
  3. +1
    -0
      src/dds/source.hpp
  4. +1
    -1
      src/libman/parse.cpp
  5. +15
    -32
      src/libman/parse.hpp
  6. +13
    -13
      src/libman/parse.test.cpp
  7. +11
    -8
      tools/bootstrap.py
  8. +46
    -12
      tools/ci.py
  9. +2
    -2
      tools/msvc.dds

+ 3
- 3
azure-pipelines.yml 查看文件

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 and Tests echo Executing Build and Tests
python -u tools/ci.py --cxx cl.exe -T tools\\msvc.dds || exit 1
python -u tools/ci.py -B download --cxx cl.exe -T tools\\msvc.dds || exit 1
displayName: Full CI displayName: Full CI
- publish: _build/dds.exe - publish: _build/dds.exe
artifact: DDS Executable - Windows VS2019 artifact: DDS Executable - Windows VS2019
steps: steps:
- script: sudo apt update -y && sudo apt install -y python3-minimal g++-8 - script: sudo apt update -y && sudo apt install -y python3-minimal g++-8
displayName: Prepare System displayName: Prepare System
- script: python3 -u tools/ci.py --cxx g++-8 -T tools/gcc-8.dds
- script: python3 -u tools/ci.py -B download --cxx g++-8 -T tools/gcc-8.dds
displayName: Full CI displayName: Full CI
- publish: _build/dds - publish: _build/dds
artifact: DDS Executable - Linux artifact: DDS Executable - Linux
steps: steps:
- script: brew install gcc@8 - script: brew install gcc@8
displayName: Prepare System displayName: Prepare System
- script: python3 -u tools/ci.py --cxx g++-8 -T tools/gcc-8.dds
- script: python3 -u tools/ci.py -B download --cxx g++-8 -T tools/gcc-8.dds
displayName: Build and Run Unit Tests displayName: Build and Run Unit Tests
- publish: _build/dds - publish: _build/dds
artifact: DDS Executable - macOS artifact: DDS Executable - macOS

+ 1
- 0
src/dds/library_manifest.cpp 查看文件

lm::read_accumulate("Uses", uses_strings), lm::read_accumulate("Uses", uses_strings),
lm::read_accumulate("Links", links_strings), lm::read_accumulate("Links", links_strings),
lm::read_required("Name", ret.name), lm::read_required("Name", ret.name),
lm::ignore_x_keys(),
lm::reject_unknown()); lm::reject_unknown());


extend(ret.uses, ranges::views::transform(uses_strings, lm::split_usage_string)); extend(ret.uses, ranges::views::transform(uses_strings, lm::split_usage_string));

+ 1
- 0
src/dds/source.hpp 查看文件

#include <dds/util/fs.hpp> #include <dds/util/fs.hpp>


#include <optional> #include <optional>
#include <vector>


namespace dds { namespace dds {



+ 1
- 1
src/libman/parse.cpp 查看文件

void lm::write_pairs(fs::path fpath, const std::vector<pair>& pairs) { void lm::write_pairs(fs::path fpath, const std::vector<pair>& pairs) {
auto fstream = dds::open(fpath, std::ios::out | std::ios::binary); auto fstream = dds::open(fpath, std::ios::out | std::ios::binary);
for (auto& pair : pairs) { for (auto& pair : pairs) {
fstream << pair.key() << ": " << pair.value() << '\n';
fstream << pair.key << ": " << pair.value << '\n';
} }
} }



+ 15
- 32
src/libman/parse.hpp 查看文件

namespace lm { namespace lm {


class pair { class pair {
std::string _key;
std::string _value;

public: public:
std::string key;
std::string value;

pair(std::string_view k, std::string_view v) pair(std::string_view k, std::string_view v)
: _key(k)
, _value(v) {}

auto& key() const noexcept { return _key; }
auto& value() const noexcept { return _value; }

template <std::size_t I>
std::string_view get() const {
if constexpr (I == 0) {
return key();
} else if constexpr (I == 1) {
return value();
}
}
: key(k)
, value(v) {}
}; };


class pair_iterator { class pair_iterator {
pair_iterator& operator++() & noexcept { pair_iterator& operator++() & noexcept {
assert(_iter != _end); assert(_iter != _end);
++_iter; ++_iter;
while (_iter != _end && _iter->key() != _key) {
while (_iter != _end && _iter->key != _key) {
++_iter; ++_iter;
} }
return *this; return *this;


const pair* find(const std::string_view& key) const noexcept { const pair* find(const std::string_view& key) const noexcept {
for (auto&& item : items()) { for (auto&& item : items()) {
if (item.key() == key) {
if (item.key == key) {
return &item; return &item;
} }
} }
pair_iterator iter(std::string_view key) const noexcept { pair_iterator iter(std::string_view key) const noexcept {
auto iter = items().begin(); auto iter = items().begin();
const auto end = items().end(); const auto end = items().end();
while (iter != end && iter->key() != key) {
while (iter != end && iter->key != key) {
++iter; ++iter;
} }
return pair_iterator{iter, end, key}; return pair_iterator{iter, end, key};
} }
}; };


class ignore_x_keys {
public:
bool operator()(std::string_view, std::string_view key, std::string_view) const {
return key.find("X-") == 0;
}
};

class reject_unknown { class reject_unknown {
public: public:
int operator()(std::string_view context, std::string_view key, std::string_view) const { int operator()(std::string_view context, std::string_view key, std::string_view) const {
} }


} // namespace lm } // namespace lm

namespace std {

template <>
struct tuple_size<lm::pair> : std::integral_constant<int, 2> {};

template <std::size_t N>
struct tuple_element<N, lm::pair> {
using type = std::string_view;
};

} // namespace std

+ 13
- 13
src/libman/parse.test.cpp 查看文件

kvs = parse_string(lm_src); kvs = parse_string(lm_src);
CHECK(kvs.size() == 1); CHECK(kvs.size() == 1);
REQUIRE(kvs.find("foo")); REQUIRE(kvs.find("foo"));
CHECK(kvs.find("foo")->value() == "bar");
CHECK(kvs.find("foo")->value == "bar");


lm_src = "foo:bar: baz"; lm_src = "foo:bar: baz";
kvs = parse_string(lm_src); kvs = parse_string(lm_src);
CHECK(kvs.size() == 1); CHECK(kvs.size() == 1);
REQUIRE(kvs.find("foo:bar")); REQUIRE(kvs.find("foo:bar"));
CHECK(kvs.find("foo:bar")->value() == "baz");
CHECK(kvs.find("foo:bar")->value == "baz");


CHECK(parse_string("#comment").size() == 0); CHECK(parse_string("#comment").size() == 0);
CHECK(parse_string("\n\n").size() == 0); CHECK(parse_string("\n\n").size() == 0);
kvs = parse_string(s); kvs = parse_string(s);
CHECK(kvs.size() == 1); CHECK(kvs.size() == 1);
REQUIRE(kvs.find("Foo")); REQUIRE(kvs.find("Foo"));
CHECK(kvs.find("Foo")->value() == "");
CHECK(kvs.find("Foo")->value == "");
} }


kvs = parse_string("foo: # Not a comment"); kvs = parse_string("foo: # Not a comment");
CHECK(kvs.size() == 1); CHECK(kvs.size() == 1);
REQUIRE(kvs.find("foo")); REQUIRE(kvs.find("foo"));
CHECK(kvs.find("foo")->value() == "# Not a comment");
CHECK(kvs.find("foo")->value == "# Not a comment");
} }


void test_multi() { void test_multi() {
auto kvs = parse_string("Foo: bar\nbaz: qux"); auto kvs = parse_string("Foo: bar\nbaz: qux");
CHECK(kvs.size() == 2); CHECK(kvs.size() == 2);
REQUIRE(kvs.find("Foo")); REQUIRE(kvs.find("Foo"));
CHECK(kvs.find("Foo")->value() == "bar");
CHECK(kvs.find("Foo")->value == "bar");
REQUIRE(kvs.find("baz")); REQUIRE(kvs.find("baz"));
CHECK(kvs.find("baz")->value() == "qux");
CHECK(kvs.find("baz")->value == "qux");


kvs = parse_string("foo: first\nfoo: second\n"); kvs = parse_string("foo: first\nfoo: second\n");
CHECK(kvs.size() == 2); CHECK(kvs.size() == 2);
auto iter = kvs.iter("foo"); auto iter = kvs.iter("foo");
REQUIRE(iter); REQUIRE(iter);
CHECK(iter->key() == "foo");
CHECK(iter->value() == "first");
CHECK(iter->key == "foo");
CHECK(iter->value == "first");
++iter; ++iter;
REQUIRE(iter); REQUIRE(iter);
CHECK(iter->key() == "foo");
CHECK(iter->value() == "second");
CHECK(iter->key == "foo");
CHECK(iter->value == "second");
++iter; ++iter;
CHECK(!iter); CHECK(!iter);


CHECK(result.primary == "Foo"); CHECK(result.primary == "Foo");
CHECK(result.pairs.size() == 1); CHECK(result.pairs.size() == 1);
REQUIRE(result.pairs.find("bar")); REQUIRE(result.pairs.find("bar"));
CHECK(result.pairs.find("bar")->value() == "baz");
CHECK(result.pairs.find("bar")->value == "baz");
}; };
check_1("Foo; bar=baz"); check_1("Foo; bar=baz");
check_1("Foo ; bar=baz"); check_1("Foo ; bar=baz");
CHECK(result.primary == "Foo bar"); CHECK(result.primary == "Foo bar");
CHECK(result.pairs.size() == 2); CHECK(result.pairs.size() == 2);
REQUIRE(result.pairs.find("baz")); REQUIRE(result.pairs.find("baz"));
CHECK(result.pairs.find("baz")->value() == "meow");
CHECK(result.pairs.find("baz")->value == "meow");
REQUIRE(result.pairs.find("quux")); REQUIRE(result.pairs.find("quux"));
CHECK(result.pairs.find("quux")->value() == "");
CHECK(result.pairs.find("quux")->value == "");
}; };


check_3("Foo bar; baz=meow quux"); check_3("Foo bar; baz=meow quux");

+ 11
- 8
tools/bootstrap.py 查看文件

EXE_SUFFIX = '.exe' if os.name == 'nt' else '' EXE_SUFFIX = '.exe' if os.name == 'nt' else ''




def _run_quiet(args) -> None:
cmd = [str(s) for s in args]
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
def _run_quiet(cmd, **kwargs) -> None:
cmd = [str(s) for s in cmd]
res = subprocess.run(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
if res.returncode != 0: if res.returncode != 0:
print(f'Subprocess command {cmd} failed ' print(f'Subprocess command {cmd} failed '
f'[{res.returncode}]:\n{res.stdout.decode()}') f'[{res.returncode}]:\n{res.stdout.decode()}')




def _clone_bootstrap_phase(ph: str) -> Path: def _clone_bootstrap_phase(ph: str) -> Path:
print(f'Cloning: {ph}')
print(f'Clone revision: {ph}')
bts_dir = BOOTSTRAP_BASE_DIR / ph bts_dir = BOOTSTRAP_BASE_DIR / ph
if bts_dir.exists(): if bts_dir.exists():
shutil.rmtree(bts_dir) shutil.rmtree(bts_dir)
return bts_dir return bts_dir




def _build_bootstrap_phase(ph: str, bts_dir: Path, args: argparse.Namespace) -> None:
print(f'Running build: {ph} (Please wait a moment...)')
def _build_bootstrap_phase(ph: str, bts_dir: Path,
args: argparse.Namespace) -> None:
print(f'Build revision: {ph} [This may take a moment]')
env = os.environ.copy() env = os.environ.copy()
env['DDS_BOOTSTRAP_PREV_EXE'] = str(PREBUILT_DIR / 'dds') env['DDS_BOOTSTRAP_PREV_EXE'] = str(PREBUILT_DIR / 'dds')
subprocess.check_call(
_run_quiet(
[ [
sys.executable, sys.executable,
'-u', '-u',
parser.add_argument( parser.add_argument(
'--cxx', help='The C++ compiler to use for the build', required=True) '--cxx', help='The C++ compiler to use for the build', required=True)
args = parser.parse_args(argv) args = parser.parse_args(argv)
for phase in BOOTSTRAP_PHASES:
for idx, phase in enumerate(BOOTSTRAP_PHASES):
print(f'Bootstrap phase [{idx+1}/{len(BOOTSTRAP_PHASES)}]')
exe = _run_boot_phase(phase, args) exe = _run_boot_phase(phase, args)


print(f'A bootstrapped DDS executable has been generated: {exe}') print(f'A bootstrapped DDS executable has been generated: {exe}')

+ 46
- 12
tools/ci.py 查看文件

import argparse import argparse
import os
import sys import sys
from pathlib import Path from pathlib import Path
from typing import Sequence, NamedTuple from typing import Sequence, NamedTuple
import subprocess import subprocess
import urllib.request


HERE = Path(__file__).parent.absolute() HERE = Path(__file__).parent.absolute()
TOOLS_DIR = HERE TOOLS_DIR = HERE




class CIOptions(NamedTuple): class CIOptions(NamedTuple):
skip_bootstrap: bool
cxx: Path cxx: Path
toolchain: str toolchain: str




def _do_bootstrap(opts: CIOptions) -> None:
print('Running bootstrap')
def _do_bootstrap_build(opts: CIOptions) -> None:
print('Bootstrapping by a local build of prior versions...')
subprocess.check_call([ subprocess.check_call([
sys.executable, sys.executable,
'-u', '-u',
]) ])




def _do_bootstrap_download() -> None:
filename = {
'win32': 'dds-win-x64.exe',
'linux': 'dds-linux-x64',
'darwin': 'dds-macos-x64',
}.get(sys.platform)
if filename is None:
raise RuntimeError(f'We do not have a prebuilt DDS binary for the "{sys.platform}" platform')
url = f'https://github.com/vector-of-bool/dds/releases/download/bootstrap-p2/{filename}'

print(f'Downloading prebuilt DDS executable: {url}')
stream = urllib.request.urlopen(url)
PREBUILT_DDS.parent.mkdir(exist_ok=True, parents=True)
with PREBUILT_DDS.open('wb') as fd:
while True:
buf = stream.read(1024 * 4)
if not buf:
break
fd.write(buf)

if os.name != 'nt':
# Mark the binary executable. By default it won't be
mode = PREBUILT_DDS.stat().st_mode
mode |= 0b001_001_001
PREBUILT_DDS.chmod(mode)


def main(argv: Sequence[str]) -> int: def main(argv: Sequence[str]) -> int:
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
'--skip-bootstrap',
action='store_true',
'-B',
'--bootstrap-with',
help= help=
'Skip the prebuild-bootstrap step. This requires a _prebuilt/dds to exist!', 'Skip the prebuild-bootstrap step. This requires a _prebuilt/dds to exist!',
choices=('download', 'build'),
required=True,
) )
parser.add_argument( parser.add_argument(
'--cxx', '--cxx',
help='The toolchain to use for the CI process', help='The toolchain to use for the CI process',
required=True) required=True)
args = parser.parse_args(argv) args = parser.parse_args(argv)
opts = CIOptions(
skip_bootstrap=args.skip_bootstrap,
cxx=Path(args.cxx),
toolchain=args.toolchain)
if not opts.skip_bootstrap:
_do_bootstrap(opts)

opts = CIOptions(cxx=Path(args.cxx), toolchain=args.toolchain)

if args.bootstrap_with == 'build':
_do_bootstrap_build(opts)
elif args.bootstrap_with == 'download':
_do_bootstrap_download()
else:
assert False, 'impossible'


subprocess.check_call([ subprocess.check_call([
str(PREBUILT_DDS), str(PREBUILT_DDS),
f'-T{opts.toolchain}', f'-T{opts.toolchain}',
]) ])


exe_suffix = '.exe' if os.name == 'nt' else ''
subprocess.check_call([ subprocess.check_call([
sys.executable, sys.executable,
'-u', '-u',
str(TOOLS_DIR / 'test.py'), str(TOOLS_DIR / 'test.py'),
f'--exe={PROJECT_ROOT / "_build/dds"}',
f'--exe={PROJECT_ROOT / f"_build/dds{exe_suffix}"}',
f'-T{opts.toolchain}', f'-T{opts.toolchain}',
]) ])



+ 2
- 2
tools/msvc.dds 查看文件

Compiler-ID: MSVC Compiler-ID: MSVC
C++-Version: C++17
Flags: /experimental:preprocessor /D FMT_HEADER_ONLY=1 /wd5105
# C++-Version: C++17
Flags: /experimental:preprocessor /D FMT_HEADER_ONLY=1 /wd5105 /std:c++latest
Link-Flags: rpcrt4.lib Link-Flags: rpcrt4.lib
Optimize: True Optimize: True

正在加载...
取消
保存