update 0.1.1

self-hosting v0.1.1
Mohammed Alyousef 4 years ago
parent 18034af6ce
commit 4e55489845

3
.gitignore vendored

@ -3,4 +3,5 @@ bin2
compile_commands.json
.clangd
temp.*
.vs
.vs
.cache

@ -1,9 +1,11 @@
# CHANGELOG
## 0.1.0 - Unreleased
## 0.1.1 - 2020-11-19
- Add support for globbing.
- Add support for find_package components.
- Add options.
- Add installs.
- Support aliases.
- Support interface libs (header-only libs).
- Support testing.
- Support testing.
- Require cmake >= 3.15.

@ -1,10 +1,10 @@
# This file was generated automatically by cmkr.
cmake_minimum_required(VERSION 3.14)
cmake_minimum_required(VERSION 3.15)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(cmkr VERSION 0.1.0)
project(cmkr VERSION 0.1.1)
include(FetchContent)
@ -49,5 +49,10 @@ target_link_libraries(cmkr PUBLIC
cmkrlib
)
install(
TARGETS cmkr
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
)

@ -4,7 +4,7 @@ cmkr, pronounced "cmaker", is A CMakeLists.txt generator from TOML.
## Building
cmkr requires a C++17 compiler, cmake >= 3.14.
cmkr requires a C++17 compiler, cmake >= 3.15.
```
git clone https://github.com/moalyousef/cmkr
cd cmkr
@ -16,7 +16,7 @@ cmake --build bin
cmkr parses cmake.toml files (using toml11 by Toru Niina) at the project directory. A basic hello world format with the minimum required fields:
```toml
[cmake]
minimum = "3.14"
minimum = "3.15"
[project]
name = "app"
@ -31,14 +31,14 @@ sources = ["src/main.cpp"]
This project's cmake.toml:
```toml
[cmake]
minimum = "3.14"
minimum = "3.15"
[project]
name = "cmkr"
version = "0.1.0"
[fetch-content]
toml11 = { GIT_REPOSITORY = "https://github.com/ToruNiina/toml11" }
toml11 = { git = "https://github.com/ToruNiina/toml11" }
[[bin]]
name = "cmkrlib"
@ -53,12 +53,16 @@ name = "cmkr"
type = "exe"
sources = ["src/main.cpp", "src/args.cpp"]
link-libs = ["cmkrlib"]
[[install]]
targets = ["cmkr"]
destination = "${CMAKE_INSTALL_PREFIX}/bin"
```
Currently supported fields:
```toml
[cmake] # required for top-level project
minimum = "3.14" # required
minimum = "3.15" # required
subdirs = [] # optional
bin-dir = "bin" # optional
cpp-flags = [] # optional
@ -76,7 +80,7 @@ Boost = { version = "1.74.0", required = false, components = ["system"] } # opti
spdlog = "*"
[fetch-content] # optional, runs fetchContent
toml11 = { GIT_REPOSITORY = "https://github.com/ToruNiina/toml11", GIT_TAG = "v3.5.0" } # optional
toml11 = { git = "https://github.com/ToruNiina/toml11", tag = "v3.5.0" } # optional
[options] # optional
APP_BUILD_STUFF = false # optional
@ -92,10 +96,17 @@ features = [] # optional
defines = [] # optional
link-libs = [] # optional
[[test]] # optional
[[test]] # optional, can define several
name = "test1" # required
command = "app" # required
arguments = ["arg1", "arg2"] # optional
[[install]] # optional, can define several
targets = ["app"] # optional
files = ["include/*.h"] # optional
dirs = [] # optional
configs = [] # optional (Release|Debug...etc)
destination = "${CMAKE_INSTALL_PREFIX}/bin" # required
```
The cmkr executable can be run from the command-line:
@ -105,6 +116,7 @@ arguments:
init [exe|lib|shared|static|interface] Starts a new project in the same directory.
gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges.
clean Clean the build directory.
help Show help.
version Current cmkr version.

@ -1,12 +1,12 @@
[cmake]
minimum = "3.14"
minimum = "3.15"
[project]
name = "cmkr"
version = "0.1.0"
version = "0.1.1"
[fetch-content]
toml11 = { GIT_REPOSITORY = "https://github.com/ToruNiina/toml11" }
toml11 = { git = "https://github.com/ToruNiina/toml11" }
[[bin]]
name = "cmkrlib"
@ -22,3 +22,6 @@ type = "exe"
sources = ["src/main.cpp", "src/args.cpp"]
link-libs = ["cmkrlib"]
[[install]]
targets = ["cmkr"]
destination = "${CMAKE_INSTALL_PREFIX}/bin"

@ -8,6 +8,8 @@ int run(int argc, char **argv);
int clean();
int install();
} // namespace cmkr::build
extern "C" {
#endif
@ -16,6 +18,8 @@ int cmkr_build_run(int argc, char **argv);
int cmkr_build_clean(void);
int cmkr_build_install(void);
#ifdef __cplusplus
}
#endif

@ -10,6 +10,8 @@ struct Status {
InitError,
GenerationError,
BuildError,
CleanError,
InstallError,
};
Status(Code ec) noexcept;
operator int() const noexcept;

@ -7,11 +7,12 @@ int %s() {
std::cout << "Hello World!\n";
return 0;
}
)lit";
const char *cmake_toml = R"lit(
[cmake]
minimum = "3.14"
minimum = "3.15"
# subdirs = []
# bin-dir = ""
# cpp-flags = []
@ -39,4 +40,9 @@ include-dirs = ["include"]
# features = []
# defines = []
# link-libs = []
[[install]]
%s = ["%s"]
destination = "${CMAKE_INSTALL_PREFIX}/%s"
)lit";

@ -28,9 +28,10 @@ const char *handle_args(int argc, char **argv) {
} else if (main_arg == "version") {
return cmkr::help::version();
} else if (main_arg == "init") {
if (args.size() < 3)
return "Please provide a project type!";
auto ret = cmkr::gen::generate_project(args[2].c_str());
std::string typ = "exe";
if (args.size() > 2)
typ = args[2];
auto ret = cmkr::gen::generate_project(typ.c_str());
if (ret)
return "Initialization failure!";
return "Directory initialized!";
@ -39,6 +40,11 @@ const char *handle_args(int argc, char **argv) {
if (ret)
return "CMake build error!";
return "CMake run completed!";
} else if (main_arg == "install") {
auto ret = build::install();
if (ret)
return "CMake install error!";
return "CMake install completed!";
} else if (main_arg == "clean") {
auto ret = build::clean();
if (ret)

@ -57,6 +57,12 @@ int clean() {
return !ret;
}
int install() {
cmake::CMake cmake(".", false);
auto cmd = "cmake --install " + cmake.bin_dir;
return ::system(cmd.c_str());
}
} // namespace cmkr::build
int cmkr_build_run(int argc, char **argv) {
@ -75,6 +81,16 @@ int cmkr_build_clean(void) {
} catch (const std::system_error &e) {
return e.code().value();
} catch (...) {
return cmkr::error::Status(cmkr::error::Status::Code::BuildError);
return cmkr::error::Status(cmkr::error::Status::Code::CleanError);
}
}
int cmkr_build_install(void) {
try {
return cmkr::build::install();
} catch (const std::system_error &e) {
return e.code().value();
} catch (...) {
return cmkr::error::Status(cmkr::error::Status::Code::InstallError);
}
}

@ -131,8 +131,6 @@ CMake::CMake(const std::string &path, bool build) {
b.sources = detail::to_string_vec(toml::find(bin, "sources").as_array());
b.alias = toml::find(bin, "alias").as_string();
if (bin.contains("include-dirs")) {
b.include_dirs =
detail::to_string_vec(toml::find(bin, "include-dirs").as_array());
@ -149,6 +147,11 @@ CMake::CMake(const std::string &path, bool build) {
if (bin.contains("defines")) {
b.defines = detail::to_string_vec(toml::find(bin, "defines").as_array());
}
if (bin.contains("alias")) {
b.alias = toml::find(bin, "alias").as_string();
}
binaries.push_back(b);
}
}
@ -165,6 +168,27 @@ CMake::CMake(const std::string &path, bool build) {
tests.push_back(test);
}
}
if (toml.contains("install")) {
const auto &ts = toml::find(toml, "install").as_array();
for (const auto &t : ts) {
Install inst;
if (t.contains("targets")) {
inst.targets = detail::to_string_vec(toml::find(t, "targets").as_array());
}
if (t.contains("files")) {
inst.files = detail::to_string_vec(toml::find(t, "files").as_array());
}
if (t.contains("dirs")) {
inst.dirs = detail::to_string_vec(toml::find(t, "dirs").as_array());
}
if (t.contains("configs")) {
inst.configs = detail::to_string_vec(toml::find(t, "configs").as_array());
}
inst.destination = toml::find(t, "destination").as_string();
installs.push_back(inst);
}
}
}
}
} // namespace cmkr::cmake

@ -36,8 +36,16 @@ struct Test {
std::vector<std::string> args;
};
struct Install {
std::vector<std::string> targets;
std::vector<std::string> files;
std::vector<std::string> dirs;
std::vector<std::string> configs;
std::string destination;
};
struct CMake {
std::string cmake_version = "3.14";
std::string cmake_version = "3.15";
std::string bin_dir = "bin";
std::string generator;
std::vector<std::string> subdirs;
@ -53,6 +61,7 @@ struct CMake {
std::map<std::string, std::map<std::string, std::string>> contents;
std::vector<Bin> binaries;
std::vector<Test> tests;
std::vector<Install> installs;
CMake(const std::string &path, bool build);
};

@ -39,6 +39,21 @@ std::string format(const char *fmt, Args... args) {
return temp;
}
std::vector<fs::path> expand_path(const fs::path &p) {
std::vector<fs::path> temp;
if (p.filename().stem().string() == "*") {
auto ext = p.extension();
for (const auto &f : fs::directory_iterator(p.parent_path())) {
if (f.path().extension() == ext) {
temp.push_back(f.path());
}
}
} else {
temp.push_back(p);
}
return temp;
}
} // namespace detail
int generate_project(const char *str) {
@ -46,19 +61,31 @@ int generate_project(const char *str) {
fs::create_directory("include");
const auto dir_name = fs::current_path().stem().string();
std::string mainbuf;
const auto tomlbuf =
detail::format(cmake_toml, dir_name.c_str(), dir_name.c_str(), str);
std::string installed;
std::string target;
std::string dest;
if (!strcmp(str, "exe")) {
mainbuf = detail::format(hello_world, "main");
installed = "targets";
target = dir_name;
dest = "bin";
} else if (!strcmp(str, "static") || !strcmp(str, "shared") || !strcmp(str, "lib")) {
mainbuf = detail::format(hello_world, "test");
installed = "targets";
target = dir_name;
dest = "lib";
} else if (!strcmp(str, "interface")) {
// Nothing special!
installed = "files";
target = "include/*.h";
dest = "include/" + dir_name;
} else {
throw std::runtime_error(
"Unknown project type. Types are exe, lib, shared, static, interface!");
}
const auto tomlbuf = detail::format(cmake_toml, dir_name.c_str(), dir_name.c_str(), str,
installed.c_str(), target.c_str(), dest.c_str());
if (strcmp(str, "interface")) {
std::ofstream ofs("src/main.cpp");
if (ofs.is_open()) {
@ -149,7 +176,23 @@ int generate_cmake(const char *path) {
for (const auto &dep : cmake.contents) {
ss << "FetchContent_Declare(\n\t" << dep.first << "\n";
for (const auto &arg : dep.second) {
ss << "\t" << arg.first << " " << arg.second << "\n";
std::string first_arg = arg.first;
if (first_arg == "git") {
first_arg = "GIT_REPOSITORY";
} else if (first_arg == "tag") {
first_arg = "GIT_TAG";
} else if (first_arg == "svn") {
first_arg == "SVN_REPOSITORY";
} else if (first_arg == "rev") {
first_arg == "SVN_REVISION";
} else if (first_arg == "url") {
first_arg = "URL";
} else if (first_arg == "hash") {
first_arg = "URL_HASH";
} else {
// don't change arg
}
ss << "\t" << first_arg << " " << arg.second << "\n";
}
ss << "\t)\n\n"
<< "FetchContent_MakeAvailable(" << dep.first << ")\n\n";
@ -188,15 +231,9 @@ int generate_cmake(const char *path) {
ss << "set(" << detail::to_upper(bin.name) << "_SOURCES\n";
for (const auto &src : bin.sources) {
auto path = fs::path(src);
if (path.filename().stem().string() == "*") {
auto ext = path.extension();
for (const auto &f : fs::directory_iterator(path.parent_path())) {
if (f.path().extension() == ext) {
ss << "\t" << f.path() << "\n";
}
}
} else {
ss << "\t" << path << "\n";
auto expanded = detail::expand_path(path);
for (const auto &f : expanded) {
ss << "\t" << f << "\n";
}
}
ss << "\t)\n\n";
@ -262,6 +299,39 @@ int generate_cmake(const char *path) {
}
}
if (!cmake.installs.empty()) {
for (const auto &inst : cmake.installs) {
ss << "install(\n";
if (!inst.targets.empty()) {
ss << "\tTARGETS ";
for (const auto &target : inst.targets) {
ss << target << " ";
}
}
if (!inst.dirs.empty()) {
ss << "\tDIRS ";
for (const auto &dir : inst.dirs) {
ss << dir << " ";
}
}
if (!inst.files.empty()) {
ss << "\tFILES ";
for (const auto &file : inst.files) {
auto path = detail::expand_path(fs::path(file));
for (const auto &f : path)
ss << f << " ";
}
}
if (!inst.configs.empty()) {
ss << "\tCONFIGURATIONS";
for (const auto &conf : inst.configs) {
ss << conf << " ";
}
}
ss << "\n\tDESTINATION " << inst.destination << "\n\t)\n\n";
}
}
ss << "\n\n";
// printf("%s\n", ss.str().c_str());

@ -11,6 +11,7 @@ arguments:
init [exe|lib|shared|static|interface] Starts a new project in the same directory.
gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges.
clean Clean the build directory.
help Show help.
version Current cmkr version.

Loading…
Cancel
Save