diff --git a/README.md b/README.md index 7e2e426..37d1a9b 100644 --- a/README.md +++ b/README.md @@ -1 +1,71 @@ # 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! \ No newline at end of file diff --git a/cmake.toml b/cmake.toml index d419a57..c662dac 100644 --- a/cmake.toml +++ b/cmake.toml @@ -1,27 +1,22 @@ [cmake] # required minimum_required = "3.0" # required -# cpp_flags = [""] # optional -# c_flags = [""] # optional -# linker_flags = [""] # optional +# 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 +# [dependencies] # optional, runs find_package, use "*" to ignore version # boost = "1.74.0" -[[app]] # 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 +# 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 diff --git a/src/args.cpp b/src/args.cpp index 40a1a59..3608971 100644 --- a/src/args.cpp +++ b/src/args.cpp @@ -5,7 +5,7 @@ #include namespace cmkr::args { -std::string handle_args(std::vector args) { +std::string handle_args(std::vector &args) { if (args.size() < 2) throw std::runtime_error("Please provide command line arguments!"); std::string main_arg = args[1]; @@ -21,7 +21,7 @@ std::string handle_args(std::vector args) { throw std::runtime_error("Please provide a project type!"); cmkr::gen::generate_project(args[2]); return "Directory initialized!"; - } else if (main_arg == "run") { + } else if (main_arg == "build") { std::string command = "cmake -S. -Bbin "; if (args.size() > 2) { for (int i = 2; i < args.size(); ++i) { @@ -29,7 +29,7 @@ std::string handle_args(std::vector args) { } } command += "&& cmake --build bin"; - system(command.c_str()); + auto _ = system(command.c_str()); return "Run completed!"; } else { return "Unknown argument!"; diff --git a/src/args.hpp b/src/args.hpp index 6bd4bc0..e022c9e 100644 --- a/src/args.hpp +++ b/src/args.hpp @@ -4,5 +4,5 @@ #include namespace cmkr::args { -std::string handle_args(std::vector args); +std::string handle_args(std::vector &args); } \ No newline at end of file diff --git a/src/gen.cpp b/src/gen.cpp index c11e3d7..15aae78 100644 --- a/src/gen.cpp +++ b/src/gen.cpp @@ -18,12 +18,14 @@ inline std::string to_upper(const std::string &str) { } return temp; } +void handle_bins(std::stringstream &s, const std::string &bin_type) { +} } // namespace detail void generate_project(const std::string &str) { fs::create_directory("src"); auto dir_name = fs::current_path().stem(); - if (str == "app") { + if (str == "exe") { std::ofstream ofs("src/main.cpp"); if (ofs.is_open()) { ofs << "#include \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 = \"" << dir_name.string() << "\"\nversion = " - "\"0.1.0\"\n\n[[app]]\nname = \"" + "\"0.1.0\"\n\n[[exe]]\nname = \"" << dir_name.string() << "\"\nsources = [\"src/main.cpp\"]\n"; } ofs2.flush(); ofs2.close(); - } else if (str == "static") { - std::ofstream ofs2("cmake.toml"); - if (ofs2.is_open()) { - ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \"" - << dir_name.string() - << "\"\nversion = " - "\"0.1.0\"\n\n[[lib]]\nname = \"" - << dir_name.string() << "\"\nsources = [\"src/main.cpp\"]\ntype = \"static\"\n"; + } else if (str == "static" || str == "shared") { + std::ofstream ofs("src/lib.cpp"); + if (ofs.is_open()) { + ofs << "int dll_main() {\n\treturn 0;\n}"; } - ofs2.flush(); - ofs2.close(); - } else if (str == "shared") { + ofs.flush(); + ofs.close(); + std::ofstream ofs2("cmake.toml"); if (ofs2.is_open()) { ofs2 << "[cmake]\nminimum_required = \"3.0\"\n\n[project]\nname = \"" << dir_name.string() << "\"\nversion = " "\"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.close(); } 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"; } + 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")) { std::map deps = toml::find>(toml, "dependencies"); @@ -125,11 +131,24 @@ void generate_cmake() { ss << "\n"; - if (toml.contains("app")) { - const auto &bins = toml::find(toml, "app").as_array(); + if (toml.contains("bin")) { + const auto &bins = toml::find(toml, "bin").as_array(); for (const auto &bin : bins) { 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(); ss << "set(" << detail::to_upper(bin_name) << "_SOURCES\n"; @@ -137,8 +156,8 @@ void generate_cmake() { ss << "\t" << src << "\n"; } ss << "\t)\n\n" - << "add_executable(" << bin_name << " ${" << detail::to_upper(bin_name) - << "_SOURCES})\n\n"; + << add_command << "(" << bin_name << " " << bin_type << " ${" + << detail::to_upper(bin_name) << "_SOURCES})\n\n"; if (bin.contains("include_directories")) { const auto includes = toml::find(bin, "include_directories").as_array(); @@ -167,50 +186,7 @@ void generate_cmake() { } } - if (toml.contains("lib")) { - 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"; - } - } - } + ss << "\n\n"; std::ofstream ofs("CMakeLists.txt"); if (ofs.is_open()) { diff --git a/src/help.hpp b/src/help.hpp index b3b39b4..f3390c6 100644 --- a/src/help.hpp +++ b/src/help.hpp @@ -7,11 +7,11 @@ const char *version = "cmkr version 0.1.0"; const char *help_msg = R"lit( Usage: cmkr [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. - run [cmake args...] Run cmake. + build [cmake args...] Run cmake and build. help Show help. version Current cmkr version. )lit"; - -} + +} // namespace cmkr::help diff --git a/src/main.cpp b/src/main.cpp index 9100236..a973ddb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,16 +4,12 @@ #include int main(int argc, char **argv) try { - std::vector args; - for (int i = 0; i < argc; ++i) args.push_back(argv[i]); auto output = cmkr::args::handle_args(args); - std::cout << output << std::endl; - return 0; } catch (const std::exception &e) { std::cerr << e.what() << std::endl;