merge bin types to one

self-hosting
MoAlyousef 4 years ago
parent 497f06b0f3
commit d59a238338

@ -1 +1,71 @@
# cmkr # cmkr
A CMakeLists.txt generator from TOML. Still WIP.
## Building
```
git clone https://github.com/moalyousef/cmkr
cd cmkr
cmake -S. -Bbin
cmake --build bin
```
## Usage
cmkr parses cmake.toml files at the project directory. A basic hello world format with the minimum required fields:
```toml
[cmake]
minimum_required = "3.0"
[project]
name = "cmkr"
version = "0.1.0"
[[bin]]
name = "cmkr"
type = "exe"
sources = ["src/main.cpp"]
```
Currently supported fields:
```toml
[cmake] # required
minimum_required = "3.0" # required
# cpp_flags = [] # optional
# c_flags = [] # optional
# linker_flags = [] # optional
# subdirs = [] # optional
[project] # required
name = "cmkr" # required
version = "0.1.0" # required
[dependencies] # optional, runs find_package, use "*" to ignore version
boost = "1.74.0" # optional
[[bin]] # required
name = "cmkr" # required
type = "exe" # required (exe || shared || static)
sources = ["src/main.cpp", "src/args.cpp", "src/gen.cpp"] # required
include_directories = ["vendor"] # optional
compile_features = ["cxx_std_17"] # optional
# link_libraries = [] # optional
```
The cmkr executable can be run from the command-line:
```
Usage: cmkr [arguments]
arguments:
init [exe|shared|static] Starts a new project in the same directory.
gen Generates CMakeLists.txt file.
build [cmake args...] Run cmake and build.
help Show help.
version Current cmkr version.
```
The build command invokes cmake and the default build-system on your platform, it also accepts extra cmake arguments:
```
cmkr build -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain -DCMAKE_BUILD_TYPE=Release
```
## Roadmap
- Support more fields.
- Support conditional cmake args somehow!

@ -1,27 +1,22 @@
[cmake] # required [cmake] # required
minimum_required = "3.0" # required minimum_required = "3.0" # required
# cpp_flags = [""] # optional # cpp_flags = [] # optional
# c_flags = [""] # optional # c_flags = [] # optional
# linker_flags = [""] # optional # linker_flags = [] # optional
# subdirs = [] # optional
[project] # required [project] # required
name = "cmkr" # required name = "cmkr" # required
version = "0.1.0" # required version = "0.1.0" # required
# [dependencies] # optional, runs find_package # [dependencies] # optional, runs find_package, use "*" to ignore version
# boost = "1.74.0" # boost = "1.74.0"
[[app]] # optional [[bin]] # required
name = "cmkr" # required name = "cmkr" # required
type = "exe" # required (exe || shared || static)
sources = ["src/main.cpp", "src/args.cpp", "src/gen.cpp"] # required sources = ["src/main.cpp", "src/args.cpp", "src/gen.cpp"] # required
include_directories = ["vendor"] # optional include_directories = ["vendor"] # optional
compile_features = ["cxx_std_17"] # optional compile_features = ["cxx_std_17"] # optional
# link_libraries = [""] # optional # link_libraries = [] # optional
# [[lib]] # optional
# name = "cmkr" # required
# type = "shared" # required (shared, static)
# sources = ["src/args.cpp", "src/gen.cpp"] # required
# include_directories = ["vendor"] # optional
# compile_features = ["cxx_std_17"] # optional
# link_libraries = [""] # optional

@ -5,7 +5,7 @@
#include <stdexcept> #include <stdexcept>
namespace cmkr::args { namespace cmkr::args {
std::string handle_args(std::vector<std::string> args) { std::string handle_args(std::vector<std::string> &args) {
if (args.size() < 2) if (args.size() < 2)
throw std::runtime_error("Please provide command line arguments!"); throw std::runtime_error("Please provide command line arguments!");
std::string main_arg = args[1]; std::string main_arg = args[1];
@ -21,7 +21,7 @@ std::string handle_args(std::vector<std::string> args) {
throw std::runtime_error("Please provide a project type!"); throw std::runtime_error("Please provide a project type!");
cmkr::gen::generate_project(args[2]); cmkr::gen::generate_project(args[2]);
return "Directory initialized!"; return "Directory initialized!";
} else if (main_arg == "run") { } else if (main_arg == "build") {
std::string command = "cmake -S. -Bbin "; std::string command = "cmake -S. -Bbin ";
if (args.size() > 2) { if (args.size() > 2) {
for (int i = 2; i < args.size(); ++i) { for (int i = 2; i < args.size(); ++i) {
@ -29,7 +29,7 @@ std::string handle_args(std::vector<std::string> args) {
} }
} }
command += "&& cmake --build bin"; command += "&& cmake --build bin";
system(command.c_str()); auto _ = system(command.c_str());
return "Run completed!"; return "Run completed!";
} else { } else {
return "Unknown argument!"; return "Unknown argument!";

@ -4,5 +4,5 @@
#include <vector> #include <vector>
namespace cmkr::args { namespace cmkr::args {
std::string handle_args(std::vector<std::string> args); std::string handle_args(std::vector<std::string> &args);
} }

@ -18,12 +18,14 @@ inline std::string to_upper(const std::string &str) {
} }
return temp; return temp;
} }
void handle_bins(std::stringstream &s, const std::string &bin_type) {
}
} // namespace detail } // namespace detail
void generate_project(const std::string &str) { void generate_project(const std::string &str) {
fs::create_directory("src"); fs::create_directory("src");
auto dir_name = fs::current_path().stem(); auto dir_name = fs::current_path().stem();
if (str == "app") { if (str == "exe") {
std::ofstream ofs("src/main.cpp"); std::ofstream ofs("src/main.cpp");
if (ofs.is_open()) { if (ofs.is_open()) {
ofs << "#include <iostream>\n\nint main() {\n\tstd::cout << \"Hello world!\" << " ofs << "#include <iostream>\n\nint main() {\n\tstd::cout << \"Hello world!\" << "
@ -37,35 +39,31 @@ void generate_project(const std::string &str) {
ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \"" ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \""
<< dir_name.string() << dir_name.string()
<< "\"\nversion = " << "\"\nversion = "
"\"0.1.0\"\n\n[[app]]\nname = \"" "\"0.1.0\"\n\n[[exe]]\nname = \""
<< dir_name.string() << "\"\nsources = [\"src/main.cpp\"]\n"; << dir_name.string() << "\"\nsources = [\"src/main.cpp\"]\n";
} }
ofs2.flush(); ofs2.flush();
ofs2.close(); ofs2.close();
} else if (str == "static") { } else if (str == "static" || str == "shared") {
std::ofstream ofs2("cmake.toml"); std::ofstream ofs("src/lib.cpp");
if (ofs2.is_open()) { if (ofs.is_open()) {
ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \"" ofs << "int dll_main() {\n\treturn 0;\n}";
<< dir_name.string()
<< "\"\nversion = "
"\"0.1.0\"\n\n[[lib]]\nname = \""
<< dir_name.string() << "\"\nsources = [\"src/main.cpp\"]\ntype = \"static\"\n";
} }
ofs2.flush(); ofs.flush();
ofs2.close(); ofs.close();
} else if (str == "shared") {
std::ofstream ofs2("cmake.toml"); std::ofstream ofs2("cmake.toml");
if (ofs2.is_open()) { if (ofs2.is_open()) {
ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \"" ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \""
<< dir_name.string() << dir_name.string()
<< "\"\nversion = " << "\"\nversion = "
"\"0.1.0\"\n\n[[lib]]\nname = \"" "\"0.1.0\"\n\n[[lib]]\nname = \""
<< dir_name.string() << "\"\nsources = [\"src/main.cpp\"]\ntype = \"shared\"\n"; << dir_name.string() << "\"\nsources = [\"src/lib.cpp\"]\ntype = \"" << str << "\"\n";
} }
ofs2.flush(); ofs2.flush();
ofs2.close(); ofs2.close();
} else { } else {
throw std::runtime_error("Unknown project type. Types are app, shared, static!"); throw std::runtime_error("Unknown project type. Types are exe, shared, static!");
} }
} }
@ -110,6 +108,14 @@ void generate_cmake() {
ss << ")\n\n"; ss << ")\n\n";
} }
if (cmake.contains("subdirs")) {
const auto dirs = toml::find(cmake, "subdirs").as_array();
for (const auto &dir : dirs) {
ss << "add_subdirectory(" << dir << ")\n";
}
ss << "\n\n";
}
if (toml.contains("dependencies")) { if (toml.contains("dependencies")) {
std::map<std::string, std::string> deps = std::map<std::string, std::string> deps =
toml::find<std::map<std::string, std::string>>(toml, "dependencies"); toml::find<std::map<std::string, std::string>>(toml, "dependencies");
@ -125,11 +131,24 @@ void generate_cmake() {
ss << "\n"; ss << "\n";
if (toml.contains("app")) { if (toml.contains("bin")) {
const auto &bins = toml::find(toml, "app").as_array(); const auto &bins = toml::find(toml, "bin").as_array();
for (const auto &bin : bins) { for (const auto &bin : bins) {
const std::string bin_name = toml::find(bin, "name").as_string(); const std::string bin_name = toml::find(bin, "name").as_string();
const std::string type = toml::find(bin, "type").as_string();
std::string bin_type;
std::string add_command;
if (type == "exe") {
bin_type = "";
add_command = "add_executable";
} else if (type == "shared" || type == "static") {
bin_type = detail::to_upper(type);
add_command = "add_library";
} else {
throw std::runtime_error(
"Unknown binary type! Supported types are exe, shared and static");
}
const auto srcs = toml::find(bin, "sources").as_array(); const auto srcs = toml::find(bin, "sources").as_array();
ss << "set(" << detail::to_upper(bin_name) << "_SOURCES\n"; ss << "set(" << detail::to_upper(bin_name) << "_SOURCES\n";
@ -137,8 +156,8 @@ void generate_cmake() {
ss << "\t" << src << "\n"; ss << "\t" << src << "\n";
} }
ss << "\t)\n\n" ss << "\t)\n\n"
<< "add_executable(" << bin_name << " ${" << detail::to_upper(bin_name) << add_command << "(" << bin_name << " " << bin_type << " ${"
<< "_SOURCES})\n\n"; << detail::to_upper(bin_name) << "_SOURCES})\n\n";
if (bin.contains("include_directories")) { if (bin.contains("include_directories")) {
const auto includes = toml::find(bin, "include_directories").as_array(); const auto includes = toml::find(bin, "include_directories").as_array();
@ -167,50 +186,7 @@ void generate_cmake() {
} }
} }
if (toml.contains("lib")) { ss << "\n\n";
const auto &libs = toml::find(toml, "lib").as_array();
for (const auto &lib : libs) {
const std::string lib_name = toml::find(lib, "name").as_string();
const std::string type = toml::find(lib, "type").as_string();
const auto srcs = toml::find(lib, "sources").as_array();
ss << "set(" << detail::to_upper(lib_name) << "_SOURCES\n";
for (const auto &src : srcs) {
ss << "\t" << src << "\n";
}
ss << "\t)\n\n"
<< "add_library(" << lib_name << " " << detail::to_upper(type) << " ${"
<< detail::to_upper(lib_name) << "_SOURCES})\n\n";
if (lib.contains("include_directories")) {
const auto includes = toml::find(lib, "include_directories").as_array();
ss << "target_include_directories(" << lib_name << " PUBLIC\n\t";
for (const auto &inc : includes) {
ss << inc << "\n\t";
}
ss << ")\n\n";
}
if (lib.contains("link_libraries")) {
const auto ls = toml::find(lib, "link_libraries").as_array();
ss << "target_link_libraries(" << lib_name << " PUBLIC\n\t";
for (const auto &l : ls) {
ss << l << "\n\t";
}
ss << ")\n\n";
}
if (lib.contains("compile_features")) {
const auto feats = toml::find(lib, "compile_features").as_array();
ss << "target_compile_features(" << lib_name << " PUBLIC\n\t";
for (const auto &feat : feats) {
ss << feat << "\n\t";
}
ss << ")\n\n";
}
}
}
std::ofstream ofs("CMakeLists.txt"); std::ofstream ofs("CMakeLists.txt");
if (ofs.is_open()) { if (ofs.is_open()) {

@ -7,11 +7,11 @@ const char *version = "cmkr version 0.1.0";
const char *help_msg = R"lit( const char *help_msg = R"lit(
Usage: cmkr [arguments] Usage: cmkr [arguments]
arguments: arguments:
init [app|shared|static] Starts a new project in the same directory. init [exe|shared|static] Starts a new project in the same directory.
gen Generates CMakeLists.txt file. gen Generates CMakeLists.txt file.
run [cmake args...] Run cmake. build [cmake args...] Run cmake and build.
help Show help. help Show help.
version Current cmkr version. version Current cmkr version.
)lit"; )lit";
} } // namespace cmkr::help

@ -4,16 +4,12 @@
#include <vector> #include <vector>
int main(int argc, char **argv) try { int main(int argc, char **argv) try {
std::vector<std::string> args; std::vector<std::string> args;
for (int i = 0; i < argc; ++i) for (int i = 0; i < argc; ++i)
args.push_back(argv[i]); args.push_back(argv[i]);
auto output = cmkr::args::handle_args(args); auto output = cmkr::args::handle_args(args);
std::cout << output << std::endl; std::cout << output << std::endl;
return 0; return 0;
} catch (const std::exception &e) { } catch (const std::exception &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;

Loading…
Cancel
Save