Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Allow for escaped compiler and link optional parameters #33

Merged
merged 4 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
621 changes: 621 additions & 0 deletions .pylintrc

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ if (ANTLER_PROJ_BUILD_TESTS)
# TODO renable when add to test code is completed:
#add_cli_test(add_to_project_tests add_to_tests.py)
add_cli_test(init_tests init_tests.py)
add_cli_test(add_and_update add_and_update.py)
endif()
16 changes: 9 additions & 7 deletions tools/add_to.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace antler {
system::info_log("Valid names are of the form [a-zA-Z][_a-zA-Z0-9]+");
return false;
}

// TODO for the next release we will remove the C++ restrictions
const auto& is_valid_cpp_lang = [](auto l) {
return l == "cpp" ||
Expand Down Expand Up @@ -115,7 +115,7 @@ namespace antler {
system::error_log("Dependency: {0} is invalid.", dep_name);
return false;
}

obj.upsert_dependency(std::move(dep));

// We have values, so query the user if they want to apply.
Expand Down Expand Up @@ -147,8 +147,10 @@ namespace antler {
app_subcommand = subcommand->add_subcommand("app", "Add a new app to your project.");
app_subcommand->add_option("-n, name", obj_name, "The name of the app to add.")->required();
app_subcommand->add_option("-l, lang", lang, "Language this app will use.")->required();
app_subcommand->add_option("--comp, compile_options", copts, "Options for the compiler for this app.");
app_subcommand->add_option("--link, link_options", lopts, "Options for the linker for this app.");
app_subcommand->add_option("--comp, compile_options", copts, "Options for the compiler for this app.")
->transform(escape_transform);
app_subcommand->add_option("--link, link_options", lopts, "Options for the linker for this app.")
->transform(escape_transform);

lib_subcommand = subcommand->add_subcommand("lib", "Add a new library to your project.");
lib_subcommand->add_option("-n, name", obj_name, "The name of the library to add.")->required();
Expand All @@ -163,7 +165,7 @@ namespace antler {
dep_subcommand->add_option("-t, tag", tag, "Tag associated with the dependency.");
dep_subcommand->add_option("-r, release", release, "Release version of the depedency.");
dep_subcommand->add_option("--digest, hash", hash, "Hash of the dependency.");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general suggestion, please avoid whitespace only changes, it just messing history and makes changes more verbose. Not necessary to fix it for now as it is already there, so just for future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I didn't actually notice I'd done it until AFTER Mikal had reviewed. Auto-updated in my editor. I generally agree, white space changes are to be avoided.

/* TODO Add back after this release when we have the testing framework finished
test_subcommand = subcommand->add_subcommand("test", "Add a new test to the project.");
test_subcommand->add_option("-n, name", obj_name, "The name of the test to add.")->required();
Expand Down Expand Up @@ -198,7 +200,7 @@ namespace antler {
proj.sync();
return 0;
}

CLI::App* subcommand;
CLI::App* app_subcommand;
CLI::App* dep_subcommand;
Expand All @@ -216,4 +218,4 @@ namespace antler {
std::string lopts;
std::string cmd;
};
} // namespace antler
} // namespace antler
19 changes: 17 additions & 2 deletions tools/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,28 @@

namespace antler {

/// Remove escape sequence character from input.
/// @note This is a SIMPLE algorithm that ONLY removes the first `\` in a 2 charachter sequence.
/// @todo Consider implementing more complicated transforms (e.g. convert "\t" to 0x09 or "\xFF" to 0xFF, etc).
/// @param input Input string that may or may not contain escape characters.
/// @return The transformed string.
std::string escape_transform(std::string input) {
for(auto i=input.begin(); i != input.end(); ++i) {
// Only remove this char *if* there is a char following.
// Note: erase plus increment effectively steps over the char follwing the erased `\` (e.g. "\\-O2" becomes "\-O2").
if(*i == '\\' && i+1 != input.end())
i = input.erase(i);
}
return input;
}

inline project::project load_project(const system::fs::path& path) {
auto p = system::fs::canonical(system::fs::path(path));
ANTLER_CHECK(project::project::update_path(p),
"path either did not exist or no `project.yml` file cound be found.");
project::project proj;
ANTLER_CHECK(proj.from_yaml(project::yaml::load(p)),
"error while loading project.yml file");
"error while loading project.yml file");
proj.path(p.parent_path());
return proj;
}
Expand All @@ -32,4 +47,4 @@ namespace antler {

return last_pop_time < last_manifest_time;
}
}
}
136 changes: 136 additions & 0 deletions tools/tests/add_and_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#! /usr/bin/env python3

""" Test `antler-proj add` and `antler proj update` commands. """

import os
import shutil

from util import antler_in_proj_cmd, load_project
from init_tests import init_project

PROJECT_NAME="aou_project"
PROJECT_PATH=os.path.join("./",PROJECT_NAME)

def expect_subvalue(array_of_lists, name, tag, value):
""" Inside array_of_lists, find the list that contains `name` and test the value
stored in that list for the given tag against value.


:param array_of_lists An array of lists.
:param name The name to search for.
:tag The tag that contains the value we to test.
:value The expected value.

"""

for i in array_of_lists:
if i["name"] == name:
return i[tag] == value
return False


def setup_project():
"""Setup the project ensuring there is a fresh project file.
"""

shutil.rmtree(PROJECT_PATH, ignore_errors=True)
init_project(PROJECT_NAME, "v1.0.0", PROJECT_PATH)
assert os.path.isdir(PROJECT_PATH)


def test_app_compile_options():
"""Add an application to the project and test its compile options can be updated.
"""

out, _ = antler_in_proj_cmd(PROJECT_PATH, "add app App1 C++ \\\\-O1")
ScottBailey marked this conversation as resolved.
Show resolved Hide resolved
print(out)
project = load_project(PROJECT_PATH)
assert expect_subvalue(project["apps"], "App1", "compile_options", "-O1")

out, _ = antler_in_proj_cmd(PROJECT_PATH, "update app App1 C++ \\\\-O2")
print(out)
project = load_project(PROJECT_PATH)
assert expect_subvalue(project["apps"], "App1", "compile_options", "-O2")


def test_app_link_options():
"""Add an application to the project and test its compile and link options can be updated.
"""

out, _ = antler_in_proj_cmd(PROJECT_PATH, "add app App2 C++ \"\\-O1\" \\\\-t")
print(out)
project = load_project(PROJECT_PATH)
assert expect_subvalue(project["apps"], "App2", "compile_options", "-O1")
assert expect_subvalue(project["apps"], "App2", "link_options", "-t")

out, _ = antler_in_proj_cmd(PROJECT_PATH, "update app App2 C++ \"\\-O2\" \\\\-s")
print(out)
project = load_project(PROJECT_PATH)
assert expect_subvalue(project["apps"], "App2", "compile_options", "-O2")
assert expect_subvalue(project["apps"], "App2", "link_options", "-s")


def test_app_update_options():
"""Add an application to the project and test its compile and link options
can be updated with flags.
"""

out, _ = antler_in_proj_cmd(PROJECT_PATH, "add app App3 C++")
print(out)
project = load_project(PROJECT_PATH)
assert expect_subvalue(project["apps"], "App3", "compile_options", "")
assert expect_subvalue(project["apps"], "App3", "link_options", "")

out, _ = antler_in_proj_cmd(PROJECT_PATH, "update app App3 --comp \\\\-O1")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["apps"], "App3", "compile_options", "-O1")
out, _ = antler_in_proj_cmd(PROJECT_PATH, "update app App3 --comp \"\\-O2\"")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["apps"], "App3", "compile_options", "-O2")

out, _ = antler_in_proj_cmd(PROJECT_PATH, "update app App3 --link \\\\-s")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["apps"], "App3", "link_options", "-s")
out, _ = antler_in_proj_cmd(PROJECT_PATH, "update app App3 --link \"\\-t\"")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["apps"], "App3", "link_options", "-t")

assert expect_subvalue(load_project(PROJECT_PATH)["apps"], "App3", "compile_options", "-O2")


def test_lib_options():
"""Add a library to the project and test its compile and link options can be updated with flags.
"""

out, _ = antler_in_proj_cmd(PROJECT_PATH, "add lib Lib1 C++")
print(out)
project = load_project(PROJECT_PATH)
assert expect_subvalue(project["libs"], "Lib1", "compile_options", "")
assert expect_subvalue(project["libs"], "Lib1", "link_options", "")

out, _ = antler_in_proj_cmd(PROJECT_PATH, "update lib Lib1 --comp -O1")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["libs"], "Lib1", "compile_options", "-O1")
out, _ = antler_in_proj_cmd(PROJECT_PATH, "update lib Lib1 --comp \"-O2\"")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["libs"], "Lib1", "compile_options", "-O2")

out, _ = antler_in_proj_cmd(PROJECT_PATH, "update lib Lib1 --link -s")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["libs"], "Lib1", "link_options", "-s")
out, _ = antler_in_proj_cmd(PROJECT_PATH, "update lib Lib1 --link \"-t\"")
print(out)
assert expect_subvalue(load_project(PROJECT_PATH)["libs"], "Lib1", "link_options", "-t")

assert expect_subvalue(load_project(PROJECT_PATH)["libs"], "Lib1", "compile_options", "-O2")





if __name__ == "__main__":
setup_project()
test_app_compile_options()
test_app_link_options()
test_app_update_options()
test_lib_options()
1 change: 1 addition & 0 deletions tools/tests/init_tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#! /usr/bin/env python3

import sys
import shutil

from util import *

Expand Down
33 changes: 23 additions & 10 deletions tools/tests/util.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
#! /usr/bin/env python3

"""Utility functions for antler-proj testing."""

import subprocess
import os
import yaml
import shutil

TEST_PATH = os.path.dirname(os.path.abspath(__file__))
APROJ_EXE = TEST_PATH + "/../antler-proj"

def run_cmd(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
""" Execute `cmd`. """
result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = result.communicate()
return out.decode('utf-8'), err.decode('utf-8')

def antler_proj_cmd(args):
return run_cmd("../antler-proj " + args)
""" Run antler-proj with `args`. """
return run_cmd(APROJ_EXE + " " + args)

def antler_in_proj_cmd(path, args):
""" Change directory to `path` and run antler-proj with `args`. """
return run_cmd("cd " + path + "; " + APROJ_EXE + " " + args)

def load_project(path):
with open("./{0}/project.yml".format(path), "r") as f:
project = yaml.safe_load(f)
""" Load a project.yml file """
with open("./{0}/project.yml".format(path), "r") as file_handle:
project = yaml.safe_load(file_handle)
return project

def expected_cmd(cmd, expected):
out, err = run_cmd(cmd)
""" Test that cmd has an expected result. """
out, _ = run_cmd(cmd)
if out != expected:
print("ERROR: cmd: %s != expected: %s" % (cmd, expected))
assert(False)
assert False

def expected_proj_cmd(cmd, expected):
out, err = antler_proj_cmd(cmd)
""" Test that `antler-proj cmd` has an expected result. """
out, _ = antler_proj_cmd(cmd)
if out != expected:
print("ERROR: cmd: %s != expected: %s" % (cmd, expected))
assert(False)
assert False
16 changes: 9 additions & 7 deletions tools/update.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace antler {
obj.compile_options(copts);
if (!lopts_opt->empty())
obj.link_options(lopts);

system::info_log("Updating object: {0}\n"
"language: {1}\n"
"compile options: {2}\n"
Expand All @@ -42,7 +42,7 @@ namespace antler {
obj.language(),
copts,
lopts);

return true;
} catch(...) {
system::error_log("Object {0} does not exist in the project", obj_name);
Expand Down Expand Up @@ -115,8 +115,10 @@ namespace antler {
app_subcommand = subcommand->add_subcommand("app", "Remove app from the project.");
app_subcommand->add_option("-n, name", obj_name, "The name of the app to remove.")->required();
app_subcommand->add_option("-l, language", lang, "The language of the app.");
app_subcommand->add_option("--comp, compile_options", copts, "The compile options used to build the app.");
app_subcommand->add_option("--link, link_options", lopts, "The link options used to build the app.");
app_subcommand->add_option("--comp, compile_options", copts, "The compile options used to build the app.")
->transform(escape_transform);
app_subcommand->add_option("--link, link_options", lopts, "The link options used to build the app.")
->transform(escape_transform);

lib_subcommand = subcommand->add_subcommand("lib", "Remove lib from the project.");
lib_subcommand->add_option("-n, name", obj_name, "The name of the library to add.")->required();
Expand All @@ -136,7 +138,7 @@ namespace antler {
test_subcommand = subcommand->add_subcommand("test", "Remove a test from the project.");
test_subcommand->add_option("-n, name", dep_name, "The name of the test to remove.")->required();
*/

}

int32_t exec() {
Expand Down Expand Up @@ -167,7 +169,7 @@ namespace antler {
proj.sync();
return 0;
}

CLI::App* subcommand = nullptr;
CLI::App* app_subcommand = nullptr;
CLI::App* dep_subcommand = nullptr;
Expand All @@ -184,4 +186,4 @@ namespace antler {
std::string release = "";
std::string digest = "";
};
} // namespace antler
} // namespace antler