Skip to content

Args::Instance constructed from Args for better segregation #203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Mar 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a096302
Code cleanup
coder137 Mar 28, 2022
4177e77
Code cleanup
coder137 Mar 28, 2022
13cce14
Update args.cpp
coder137 Mar 28, 2022
e77a8d2
Update args.cpp
coder137 Mar 28, 2022
8534c81
Updated args with initial instance apis
coder137 Mar 28, 2022
b9408c2
Update test_args.cpp
coder137 Mar 28, 2022
006b5f3
Update test_register.cpp
coder137 Mar 28, 2022
b5aada9
Removed static functions from Args
coder137 Mar 28, 2022
787440e
Update build.cpp
coder137 Mar 28, 2022
10070cc
Update build.cpp
coder137 Mar 28, 2022
7aa0114
Update build.cpp
coder137 Mar 28, 2022
b591bf7
Update build.cpp
coder137 Mar 28, 2022
af9fcb5
Update build.cpp
coder137 Mar 28, 2022
5b8ba36
Update build.main.cpp
coder137 Mar 28, 2022
4834028
Update build.main.cpp
coder137 Mar 28, 2022
b545250
Update build.cpp
coder137 Mar 28, 2022
ca950fd
Update build.main.cpp
coder137 Mar 28, 2022
7766654
Updated buildexe
coder137 Mar 28, 2022
30187f0
Update main.buildcc.cpp
coder137 Mar 28, 2022
8ca8aa2
Updated args with AddCustomData API
coder137 Mar 28, 2022
c35877a
Removed ConstRef
coder137 Mar 28, 2022
0e20e0c
Update test_args.cpp
coder137 Mar 28, 2022
dc860e9
Updated Args with AddCustomCallback API
coder137 Mar 28, 2022
96c802e
Update args setup
coder137 Mar 29, 2022
e13f418
Update build.cpp
coder137 Mar 29, 2022
e1145f3
Update args
coder137 Mar 29, 2022
66d7eb7
Updated args setup
coder137 Mar 29, 2022
8e67cee
Update test_args.cpp
coder137 Mar 29, 2022
2eafd97
Update args.h
coder137 Mar 29, 2022
b0be6c7
Update args.rst
coder137 Mar 29, 2022
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
7 changes: 3 additions & 4 deletions bootstrap/main.buildcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ static void hybrid_simple_example_cb(BaseTarget &target,
const BaseTarget &libbuildcc);

int main(int argc, char **argv) {
Args::Init();
ArgToolchain custom_toolchain_arg;
Args::AddToolchain("host", "Host Toolchain", custom_toolchain_arg);
Args::Parse(argc, argv);
Args::Init()
.AddToolchain("host", "Host Toolchain", custom_toolchain_arg)
.Parse(argc, argv);

Register reg;
;
reg.Clean(clean_cb);

BaseToolchain toolchain = custom_toolchain_arg.ConstructToolchain();
Expand Down
104 changes: 61 additions & 43 deletions buildcc/lib/args/include/args/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,57 +85,71 @@ struct ArgTarget {
std::string link_command{""};
};

struct ArgCustom {
virtual void Add(CLI::App &app) = 0;
};

class Args {
public:
private:
class Instance {
public:
/**
* @brief Parse command line information to CLI11
*
* @param argc from int main(int argc, char ** argv)
* @param argv from int main(int argc, char ** argv)
*/
static void Parse(int argc, const char *const *argv);

/**
* @brief Add toolchain with a unique name and description
*
* @param out Receive the toolchain information through the CLI
* @param initial Set the default toolchain information as a fallback
*/
Instance &AddToolchain(const std::string &name,
const std::string &description, ArgToolchain &out,
const ArgToolchain &initial = ArgToolchain());

/**
* @brief Add toolchain with a unique name and description
*
* @param out Receive the toolchain information through the CLI
* @param initial Set the default toolchain information as a fallback
*/
Instance &AddTarget(const std::string &name, const std::string &description,
ArgTarget &out, const ArgTarget &initial = ArgTarget());

/**
* @brief Custom callback for data
*
* @param add_cb Add callback that exposes underlying CLI::App
*/
Instance &AddCustomCallback(const std::function<void(CLI::App &)> &add_cb);

/**
* @brief Add custom data
*
* @param data Derive from `buildcc::ArgCustom` and override the `Add` API
*/
Instance &AddCustomData(ArgCustom &data);
};

struct Internal {
Instance instance;
CLI::App app{"BuildCC Buildsystem"};
CLI::App *toolchain{nullptr};
CLI::App *target{nullptr};
};

public:
Args() = delete;
Args(const Args &) = delete;
Args(Args &&) = delete;

static void Init();
static Instance &Init();
static void Deinit();

/**
* @brief Parse command line information to CLI11
*
* @param argc from int main(int argc, char ** argv)
* @param argv from int main(int argc, char ** argv)
*/
static void Parse(int argc, const char *const *argv);

/**
* @brief Modifiable reference to CLI::App (CLI11)
*/
static CLI::App &Ref();

/**
* @brief Constant reference to CLI::App (CLI11)
*/
static const CLI::App &ConstRef();

// Setters

/**
* @brief Add toolchain with a unique name and description
*
* @param out Receive the toolchain information through the CLI
* @param initial Set the default toolchain information as a fallback
*/
static void AddToolchain(const std::string &name,
const std::string &description, ArgToolchain &out,
const ArgToolchain &initial = ArgToolchain());

/**
* @brief Add Target config commands with a unique name and description
*
* @param out Receive the target command information through the CLI
* @param initial Set the default target command information as a fallback
*
* TODO, Update with other options for TargetConfig
*/
static void AddTarget(const std::string &name, const std::string &description,
ArgTarget &out, const ArgTarget &initial = ArgTarget());

// Getters
static bool Clean();
static env::LogLevel GetLogLevel();
Expand All @@ -145,6 +159,10 @@ class Args {

private:
static void RootArgs();
static CLI::App &Ref();

private:
static std::unique_ptr<Internal> internal_;
};

} // namespace buildcc
Expand Down
3 changes: 0 additions & 3 deletions buildcc/lib/args/include/args/register.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ namespace buildcc {

class Register {
public:
// Register(const Args &args) : args_(args) { Initialize(); }
Register() { Initialize(); }
Register(const Register &) = delete;

Expand Down Expand Up @@ -155,8 +154,6 @@ class Register {
void BuildStoreTask(const std::string &unique_id, const tf::Task &task);

private:
// const Args &args_;

// Build
tf::Taskflow build_tf_{"Targets"};

Expand Down
2 changes: 1 addition & 1 deletion buildcc/lib/args/mock/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace buildcc {

void Args::Parse(int argc, const char *const *argv) {
void Args::Instance::Parse(int argc, const char *const *argv) {
try {
Ref().parse(argc, argv);
} catch (const CLI::ParseError &e) {
Expand Down
132 changes: 76 additions & 56 deletions buildcc/lib/args/src/args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,52 +90,72 @@ buildcc::env::LogLevel loglevel_{buildcc::env::LogLevel::Info};
fs::path project_root_dir_{""};
fs::path project_build_dir_{"_internal"};

// Internal
// std::unique_ptr<CLI::App> app_;
// CLI::App *toolchain_{nullptr};
// CLI::App *target_{nullptr};

struct ArgsInstance {
CLI::App app_{"BuildCC Buildsystem"};
CLI::App *toolchain_{nullptr};
CLI::App *target_{nullptr};
};

std::unique_ptr<ArgsInstance> args_instance_;

} // namespace

namespace buildcc {

void Args::Init() {
if (!args_instance_) {
args_instance_ = std::make_unique<ArgsInstance>();
args_instance_->toolchain_ =
std::unique_ptr<Args::Internal> Args::internal_;

Args::Instance &Args::Init() {
if (!internal_) {
internal_ = std::make_unique<Internal>();
internal_->toolchain =
Ref().add_subcommand(kToolchainSubcommand, kToolchainDesc);
args_instance_->target_ =
Ref().add_subcommand(kTargetSubcommand, kTargetDesc);
internal_->target = Ref().add_subcommand(kTargetSubcommand, kTargetDesc);
RootArgs();
}
return internal_->instance;
}

void Args::Deinit() { args_instance_.reset(nullptr); }

CLI::App &Args::Ref() { return args_instance_->app_; }
const CLI::App &Args::ConstRef() { return args_instance_->app_; }
void Args::Deinit() { internal_.reset(nullptr); }

bool Args::Clean() { return clean_; }
env::LogLevel Args::GetLogLevel() { return loglevel_; }

const fs::path &Args::GetProjectRootDir() { return project_root_dir_; }
const fs::path &Args::GetProjectBuildDir() { return project_build_dir_; }

void Args::AddToolchain(const std::string &name, const std::string &description,
ArgToolchain &out, const ArgToolchain &initial) {
CLI::App *toolchain_ = args_instance_->toolchain_;
env::assert_fatal(toolchain_ != nullptr,
// Private

void Args::RootArgs() {
auto &app = Ref();
app.set_help_all_flag(kHelpAllParam, kHelpAllDesc);

app.set_config(kConfigParam, "", kConfigDesc)->expected(kMinFiles, kMaxFiles);

// Root flags
auto *root_group = app.add_option_group(kRootGroup);

root_group->add_flag(kCleanParam, clean_, kCleanDesc);
root_group->add_option(kLoglevelParam, loglevel_, kLoglevelDesc)
->transform(CLI::CheckedTransformer(kLogLevelMap, CLI::ignore_case));

// Dir flags
root_group->add_option(kRootDirParam, project_root_dir_, kRootDirDesc)
->required();
root_group->add_option(kBuildDirParam, project_build_dir_, kBuildDirDesc)
->required();
}

CLI::App &Args::Ref() { return internal_->app; }

// Args::Instance

/**
* @brief Add toolchain with a unique name and description
*
* @param out Receive the toolchain information through the CLI
* @param initial Set the default toolchain information as a fallback
*/
Args::Instance &Args::Instance::AddToolchain(const std::string &name,
const std::string &description,
ArgToolchain &out,
const ArgToolchain &initial) {
CLI::App *toolchain = internal_->toolchain;
env::assert_fatal(toolchain != nullptr,
"Initialize Args using the Args::Init API");
CLI::App *t_user =
toolchain_->add_subcommand(name, description)->group(kToolchainGroup);
toolchain->add_subcommand(name, description)->group(kToolchainGroup);
t_user->add_flag(kToolchainBuildParam, out.state.build);
t_user->add_flag(kToolchainTestParam, out.state.test);

Expand All @@ -153,42 +173,42 @@ void Args::AddToolchain(const std::string &name, const std::string &description,
->default_val(initial.executables.archiver);
t_user->add_option(kToolchainLinkerParam, out.executables.linker)
->default_val(initial.executables.linker);
return *this;
}

void Args::AddTarget(const std::string &name, const std::string &description,
ArgTarget &out, const ArgTarget &initial) {
CLI::App *target_ = args_instance_->target_;
env::assert_fatal(target_ != nullptr,
/**
* @brief Add toolchain with a unique name and description
*
* @param out Receive the toolchain information through the CLI
* @param initial Set the default toolchain information as a fallback
*/
Args::Instance &Args::Instance::AddTarget(const std::string &name,
const std::string &description,
ArgTarget &out,
const ArgTarget &initial) {
CLI::App *target = internal_->target;
env::assert_fatal(target != nullptr,
"Initialize Args using the Args::Init API");
CLI::App *target_user =
target_->add_subcommand(name, description)->group(kTargetGroup);
target_user->add_option(kTargetCompileCommandParam, out.compile_command)
CLI::App *targetuser =
target->add_subcommand(name, description)->group(kTargetGroup);
targetuser->add_option(kTargetCompileCommandParam, out.compile_command)
->default_val(initial.compile_command);
target_user->add_option(kTargetLinkCommandParam, out.link_command)
targetuser->add_option(kTargetLinkCommandParam, out.link_command)
->default_val(initial.link_command);
return *this;
}

// Private

void Args::RootArgs() {
Ref().set_help_all_flag(kHelpAllParam, kHelpAllDesc);

Ref()
.set_config(kConfigParam, "", kConfigDesc)
->expected(kMinFiles, kMaxFiles);

// Root flags
auto *root_group = Ref().add_option_group(kRootGroup);

root_group->add_flag(kCleanParam, clean_, kCleanDesc);
root_group->add_option(kLoglevelParam, loglevel_, kLoglevelDesc)
->transform(CLI::CheckedTransformer(kLogLevelMap, CLI::ignore_case));
Args::Instance &Args::Instance::AddCustomCallback(
const std::function<void(CLI::App &)> &add_cb) {
auto &app = Ref();
add_cb(app);
return *this;
}

// Dir flags
root_group->add_option(kRootDirParam, project_root_dir_, kRootDirDesc)
->required();
root_group->add_option(kBuildDirParam, project_build_dir_, kBuildDirDesc)
->required();
Args::Instance &Args::Instance::AddCustomData(ArgCustom &data) {
auto &app = Ref();
data.Add(app);
return *this;
}

} // namespace buildcc
7 changes: 4 additions & 3 deletions buildcc/lib/args/src/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@

namespace buildcc {

void Args::Parse(int argc, const char *const *argv) {
void Args::Instance::Parse(int argc, const char *const *argv) {
auto &app = Ref();
try {
Ref().parse(argc, argv);
app.parse(argc, argv);
} catch (const CLI::ParseError &e) {
exit(ConstRef().exit(e));
exit(app.exit(e));
}
}

Expand Down
Loading