Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
e96addc
Add skeleton for command-line binary
okofish Feb 26, 2021
ee699ed
Add validation and default to initcount option
okofish Feb 26, 2021
2ffa0b5
Add basic iteration to chase mode
okofish Feb 26, 2021
77bbfde
Adjust formatting
okofish Feb 26, 2021
69fd7bf
Silence the linting demons
okofish Feb 26, 2021
b56cf9b
Add framework for parsing (later serializing) data files, starting wi…
okofish Feb 27, 2021
744341a
Add sample crib file
okofish Feb 27, 2021
c4e78e9
Return immediately after printing help
okofish Feb 27, 2021
85211da
Build CLI in CI job
okofish Feb 27, 2021
bbe77ae
Change Boost dependencies for CI
okofish Feb 27, 2021
5a13942
Add a Dockerfile for building the CLI and a CMake option to enable a …
okofish Feb 27, 2021
c608bb4
If --cribfile was specified, load its contents into the CheckpointSpe…
okofish Feb 27, 2021
7f1d6b1
Include head state in crib file format; deserialize crib files direct…
okofish Feb 27, 2021
c99aaf2
Add --initoffset option for use in array jobs (e.g. Charity Engine CE…
okofish Feb 27, 2021
22f6e34
Add documentation on file formats
okofish Feb 27, 2021
f789218
Add PostTagFileWriter class; move file version and magic number enums…
okofish Feb 27, 2021
b3cf08e
Add PostTagResultFile and writer class (file format will change once …
okofish Feb 28, 2021
5273988
Refactor PostTagFileVersion::V1 to Version1
okofish Feb 28, 2021
2574ef5
Arguments tweaks
okofish Feb 28, 2021
20c72a4
Initialize `last_byte` in PostTagFileWriter::write_bits
okofish Feb 28, 2021
25591e1
Add a --version flag
okofish Feb 28, 2021
7e92803
Add init file format and reader
okofish Feb 28, 2021
c451858
Change prescribed file extensions for crib and result files
okofish Feb 28, 2021
0fff8d7
Address some review comments
okofish Feb 28, 2021
cc76117
Give Dockerfile ENTRYPOINT in list form
okofish Feb 28, 2021
0e260fc
Remote stray printf
okofish Feb 28, 2021
0fc32ee
Make test crib and init files more comprehensive
okofish Feb 28, 2021
3ed66f8
Add CLI build to the other Linux CI test job
okofish Feb 28, 2021
1c02c5a
Build Docker image with Release configuration
okofish Feb 28, 2021
d45f781
Install Boost in cpp-32-test build
okofish Feb 28, 2021
b141658
Set CMAKE_BUILD_TYPE in Dockerfile build
okofish Feb 28, 2021
cf19479
Use PRIu64 macro when printing uint64_t for cross-architecture compat…
okofish Feb 28, 2021
927c8b8
PostTagState -> TagState
okofish Mar 1, 2021
ca2f7b2
Change init file format to use a packed bit array instead of a u64
okofish Mar 1, 2021
c0cf71b
Add (currently unused) methods for reading and writing bit arrays as …
okofish Mar 1, 2021
2f57e3d
Add explicit values to ConclusionReason enum
okofish Mar 1, 2021
8b5f81b
Revise and document result file format
okofish Mar 1, 2021
79c8a62
Make --maxsize and --maxsteps into general arguments; other misc. arg…
okofish Mar 1, 2021
41a3d62
Ignore .postcrib, .postinit, and .postresult files in lint script
okofish Mar 1, 2021
ebe3526
Include Boost with quotes to silence cpplint
okofish Mar 1, 2021
937316f
Implement chase mode using searcher API
okofish Mar 1, 2021
a27b97b
Exclude final states from results files if they're too big or irrelev…
okofish Mar 1, 2021
6bee078
Please the linting gods
okofish Mar 1, 2021
5b1fe44
Add WL code for parsing/serializing file formats; consolidate everyth…
okofish Mar 1, 2021
e5b0721
Remove leftover files in TestDatafiles directory
okofish Mar 1, 2021
909fa3d
Save a few bytes
okofish Mar 1, 2021
6bce283
Attempt to fix some compiler warnings in the Windows CLI buils
okofish Mar 1, 2021
f897959
Add Windows CLI build
okofish Mar 1, 2021
9f96195
Make initsize a uint16_t, because C++ tries to read a uint8_t as a si…
okofish Mar 1, 2021
6019801
Add pounce implementation; restructure main.cpp somewhat
okofish Mar 1, 2021
5b2b91e
Take variable_map as reference
okofish Mar 1, 2021
0ec8148
Remote old TestDatafiles directory from linting exclusion list
okofish Mar 1, 2021
8bf7dda
Add --maxoutsize option to skip saving final state tapes above a cert…
okofish Mar 1, 2021
c2896f4
Combine Windows CLI build job with main Windows build job
okofish Mar 1, 2021
fda7401
Adjust arguments and printed messages per review
okofish Mar 1, 2021
5bc4bfe
Remove init/crib file writer syntax with default head state; update s…
okofish Mar 1, 2021
b9ed2f9
Remove reference to windows-cli-build CI job
okofish Mar 1, 2021
569e19c
In Windows build job, build CLI in a separate step from the library
okofish Mar 2, 2021
0b292f4
Clear build directory before building CLI
okofish Mar 2, 2021
24cbb19
Merge branch 'master' into feature/cli
okofish Mar 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ jobs:
- run:
name: Install Required Tools
command: |
apk add --no-cache bash git g++ make cmake clang py-pip shellcheck shfmt grep npm
apk add --no-cache \
bash boost-dev boost-static git g++ make cmake \
clang py-pip shellcheck shfmt grep npm
pip install cpplint
npm install -g markdownlint-cli

Expand All @@ -83,6 +85,7 @@ jobs:
mkdir build
cd build
cmake .. -DPOST_TAG_SYSTEM_BUILD_TESTING=ON \
-DPOST_TAG_SYSTEM_BUILD_CLI=ON \
-DPOST_TAG_SYSTEM_ENABLE_ALLWARNINGS=ON
cmake --build .

Expand All @@ -105,14 +108,15 @@ jobs:

- run:
name: Install Required Tools
command: apk add --no-cache bash git g++ make cmake
command: apk add --no-cache bash boost-dev boost-static git g++ make cmake

- run:
name: Build
command: |
mkdir build
cd build
cmake .. -DPOST_TAG_SYSTEM_BUILD_TESTING=ON \
-DPOST_TAG_SYSTEM_BUILD_CLI=ON \
-DPOST_TAG_SYSTEM_ENABLE_ALLWARNINGS=ON
cmake --build .

Expand Down Expand Up @@ -170,6 +174,19 @@ jobs:
cmakeDir=$(dir -1 | findstr -i cmake-*)
echo "export PATH=\"$(pwd)/$cmakeDir/bin:$PATH\"" >> $BASH_ENV

- run:
name: Install Boost headers and build libraries
command: |
boostURL="https://dl.bintray.com/boostorg/release/1.72.0/source/boost_1_72_0.zip"
curl -L --output boost.zip $boostURL
unzip -q boost.zip
boostDir=$(dir -1 | findstr -i boost_*)
echo "export BOOST_ROOT=\"$(pwd)/$boostDir\"" >> $BASH_ENV
grep BOOST_ $BASH_ENV
cd $boostDir
./bootstrap.bat
./b2 --with-program_options

- run:
name: Build
command: scripts/buildLibraryResources.sh
Expand All @@ -182,6 +199,22 @@ jobs:
- store_artifacts:
path: ./LibraryResources/

- run:
name: Build
command: |
rm -rf build
mkdir -p build
cd build
cmake .. \
-DPOST_TAG_SYSTEM_ENABLE_ALLWARNINGS=ON \
-DPOST_TAG_SYSTEM_BUILD_CLI=ON \
-DPOST_TAG_SYSTEM_CLI_STATIC_BUILD=ON \
-DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release

- store_artifacts:
path: ./build/CLI/Release

workflows:
version: 2
build-and-test:
Expand Down
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/
*.xcodeproj/
39 changes: 39 additions & 0 deletions CLI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
option(POST_TAG_SYSTEM_CLI_STATIC_BUILD "Build command-line interface as a statically linked executable." OFF)

if(POST_TAG_SYSTEM_CLI_STATIC_BUILD)
set(Boost_USE_STATIC_LIBS ON)
endif()

find_package(Boost 1.67
COMPONENTS program_options
REQUIRED)

set(_link_libraries
PostTagSystem
${Boost_LIBRARIES}
)

add_executable(wolfram-postproject
main.cpp arguments.cpp
files/PostTagFileReader.cpp files/PostTagFileWriter.cpp
files/PostTagCribFile.cpp files/PostTagInitFile.cpp
files/PostTagResultFile.cpp
)

target_include_directories(wolfram-postproject PRIVATE
${Boost_INCLUDE_DIR})

target_compile_options(wolfram-postproject PRIVATE
${POST_TAG_SYSTEM_COMPILE_OPTIONS})

target_compile_definitions(wolfram-postproject PRIVATE
POST_TAG_VERSION_MAJOR=${CMAKE_PROJECT_VERSION_MAJOR}
POST_TAG_VERSION_MINOR=${CMAKE_PROJECT_VERSION_MINOR}
POST_TAG_VERSION_PATCH=${CMAKE_PROJECT_VERSION_PATCH}
)

if(POST_TAG_SYSTEM_CLI_STATIC_BUILD)
target_link_options(wolfram-postproject PUBLIC "-static")
endif()

target_link_libraries(wolfram-postproject ${_link_libraries})
122 changes: 122 additions & 0 deletions CLI/arguments.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "arguments.hpp"

#include <iostream>
#include <string>

namespace po = boost::program_options;

auto validator_uint_greater_equal(const char* const option_name, uint64_t min) {
return [option_name, min](auto n) {
if (n < min) {
throw po::validation_error(
po::validation_error::invalid_option_value, option_name, std::to_string(static_cast<uint64_t>(n)));
}
};
}

auto validator_uint_between(const char* const option_name, uint64_t min, uint64_t max) {
return [option_name, min, max](auto n) {
if (n < min || n > max) {
throw po::validation_error(
po::validation_error::invalid_option_value, option_name, std::to_string(static_cast<uint64_t>(n)));
}
};
}

void validate_option_existence(const po::variables_map& args, const char* const option_name) {
if (args.count(option_name) == 0) {
// TODO(jessef): better exception
throw po::validation_error(po::validation_error::at_least_one_value_required, option_name);
}
}

void mode_validate_chase(const po::variables_map& args) {
validate_option_existence(args, "initsize");
validate_option_existence(args, "initstart");
validate_option_existence(args, "initcount");
}

void mode_validate_pounce(const po::variables_map& args) { validate_option_existence(args, "initfile"); }

po::variables_map parse_arguments(int argc, char** argv) {
po::options_description general_options("General options");
po::options_description chase_options("Chase-mode options");
po::options_description pounce_options("Pounce-mode options");

// clang-format off
general_options.add_options()
("help,h", po::bool_switch(),
"Print help text")
("version,v", po::bool_switch(),
"Print program version")
("chase,c", po::bool_switch(),
"Chase mode (range search)")
("pounce,p", po::bool_switch(),
"Pounce mode (file search)")
("outfile,o", po::value<std::string>()->default_value("./output.postresult")->value_name("path.postresult"),
"Path to output file")
("maxsize,x", po::value<uint64_t>()->default_value(static_cast<uint64_t>(1e9), "10^9")->value_name("size"),
"Maximum tape length to evaluate each initial condition to (0 = no limit)")
("maxoutsize,z", po::value<uint64_t>()->value_name("size"),
"Maximum tape length to include in output file entries (0 = never write final tapes; omit for no limit)")
("maxsteps,m", po::value<uint64_t>()->default_value(static_cast<uint64_t>(1e10), "10^10")->value_name("steps"),
"Maximum number of steps to evaluate each initial condition to (0 = no limit)")
("timeout,t", po::value<uint32_t>()->default_value(0)->value_name("secs"),
"Total execution time constraint (seconds) (0 = no limit)");

chase_options.add_options()
("cribfile,f", po::value<std::string>()->value_name("path.postcrib"),
"Path to crib file (list of known sequences)")
("initsize,l", po::value<uint16_t>()->value_name("size")
->notifier(validator_uint_between("initsize", 1, 64)),
"Size of initial condition tapes")
("initstart,s", po::value<uint64_t>()->value_name("start"),
"Starting initial condition tape (as decimal integer)")
("initcount,n", po::value<uint64_t>()->default_value(1)->value_name("count")
->notifier(validator_uint_greater_equal("initcount", 1)),
"Number of initial condition tapes to evaluate")
("initoffset,e", po::value<uint64_t>()->default_value(0)->value_name("offset"),
"Shifts starting condition by offset * count (for use with zero-indexed array jobs)");

pounce_options.add_options()
("initfile,i", po::value<std::string>()->value_name("path.postinit"),
"Path to file of initial conditions");
// clang-format on

po::options_description all_options;
all_options.add(general_options).add(chase_options).add(pounce_options);

po::variables_map args;
po::store(po::command_line_parser(argc, argv).options(all_options).run(), args);
po::notify(args);

if (args["help"].as<bool>()) {
std::cout << all_options << "\n";
return args;
}

if (args["version"].as<bool>()) {
#if defined(POST_TAG_VERSION_MAJOR) && defined(POST_TAG_VERSION_MINOR) && defined(POST_TAG_VERSION_PATCH)
printf("wolfram-postproject v%u.%u.%u =^._.^=\n",
POST_TAG_VERSION_MAJOR,
POST_TAG_VERSION_MINOR,
POST_TAG_VERSION_PATCH);
#else
printf("wolfram-postproject unknown version =^._.^=\n");
#endif

return args;
}

if (args["chase"].as<bool>() && args["pounce"].as<bool>()) {
throw std::runtime_error("Only one of --chase or --pounce may be specified");
} else if (args["chase"].as<bool>()) {
mode_validate_chase(args);
} else if (args["pounce"].as<bool>()) {
mode_validate_pounce(args);
} else {
throw std::runtime_error("One of --chase or --pounce must be specified");
}

return args;
}
8 changes: 8 additions & 0 deletions CLI/arguments.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef CLI_ARGUMENTS_HPP_
#define CLI_ARGUMENTS_HPP_

#include "boost/program_options.hpp"

boost::program_options::variables_map parse_arguments(int argc, char** argv);

#endif // CLI_ARGUMENTS_HPP_
45 changes: 45 additions & 0 deletions CLI/files/PostTagCribFile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "PostTagCribFile.hpp"

#include "boost/format.hpp"

using PostTagSystem::TagState;

PostTagCribFile PostTagCribFileReader::read_file() {
uint8_t file_magic = read_u8();
PostTagFileMagic format_magic = CribFileMagic;

if (file_magic != format_magic) {
throw std::runtime_error((boost::format("File magic number 0x%X did not match expected 0x%X") %
static_cast<unsigned int>(file_magic) % static_cast<unsigned int>(format_magic))
.str());
}

uint8_t version = read_u8();
switch (version) {
case Version1:
return read_file_V1();

default:
throw std::runtime_error(
(boost::format("Unsupported file version %u") % static_cast<unsigned int>(version)).str());
}
}

PostTagCribFile PostTagCribFileReader::read_file_V1() {
PostTagCribFile file;
file.version = Version1;
file.checkpoint_count = read_u64();
file.checkpoints = read_checkpoints(file.checkpoint_count);

return file;
}

std::vector<TagState> PostTagCribFileReader::read_checkpoints(uint64_t checkpoint_count) {
std::vector<TagState> checkpoints(checkpoint_count);
for (size_t i = 0; i < checkpoint_count; i++) {
checkpoints[i].headState = read_u8();
checkpoints[i].tape = read_prefixed_bits();
}

return checkpoints;
}
30 changes: 30 additions & 0 deletions CLI/files/PostTagCribFile.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef CLI_FILES_POSTTAGCRIBFILE_HPP_
#define CLI_FILES_POSTTAGCRIBFILE_HPP_

#include <fstream>
#include <vector>

#include "PostTagFile.hpp"
#include "PostTagFileReader.hpp"
#include "TagState.hpp"

struct PostTagCribFile {
PostTagFileVersion version;

uint64_t checkpoint_count;
std::vector<PostTagSystem::TagState> checkpoints;
};

class PostTagCribFileReader : public PostTagFileReader {
public:
using PostTagFileReader::PostTagFileReader;

PostTagCribFile read_file();

private:
PostTagCribFile read_file_V1();

std::vector<PostTagSystem::TagState> read_checkpoints(uint64_t checkpoint_count);
};

#endif // CLI_FILES_POSTTAGCRIBFILE_HPP_
8 changes: 8 additions & 0 deletions CLI/files/PostTagFile.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef CLI_FILES_POSTTAGFILE_HPP_
#define CLI_FILES_POSTTAGFILE_HPP_

enum PostTagFileVersion : uint8_t { Version1 = 1 };

enum PostTagFileMagic : uint8_t { CribFileMagic = 'C', InitFileMagic = 'I', ResultFileMagic = 'R' };

#endif // CLI_FILES_POSTTAGFILE_HPP_
Loading