Rename various options to match CMake's naming better and refactor

vcpkg-wip
Duncan Ogilvie 4 years ago
parent df41d3eaff
commit eaa5e62396

@ -9,7 +9,7 @@ endif()
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(cmkr_PROJECT_VERSION 0.1.3) set(cmkr_PROJECT_VERSION 0.1.3)
project(cmkr VERSION ${cmkr_PROJECT_VERSION}) project(cmkr VERSION ${cmkr_PROJECT_VERSION})
@ -19,21 +19,21 @@ include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
filesystem filesystem
GIT_REPOSITORY https://github.com/gulrak/filesystem GIT_REPOSITORY https://github.com/gulrak/filesystem
) )
FetchContent_MakeAvailable(filesystem) FetchContent_MakeAvailable(filesystem)
FetchContent_Declare( FetchContent_Declare(
mpark_variant mpark_variant
URL https://github.com/mpark/variant/archive/v1.4.0.tar.gz URL https://github.com/mpark/variant/archive/v1.4.0.tar.gz
) )
FetchContent_MakeAvailable(mpark_variant) FetchContent_MakeAvailable(mpark_variant)
FetchContent_Declare( FetchContent_Declare(
toml11 toml11
GIT_REPOSITORY https://github.com/ToruNiina/toml11 GIT_REPOSITORY https://github.com/ToruNiina/toml11
) )
FetchContent_MakeAvailable(toml11) FetchContent_MakeAvailable(toml11)
@ -43,7 +43,7 @@ set(CMKRLIB_SOURCES
src/help.cpp src/help.cpp
src/build.cpp src/build.cpp
src/error.cpp src/error.cpp
) )
add_library(cmkrlib STATIC ${CMKRLIB_SOURCES}) add_library(cmkrlib STATIC ${CMKRLIB_SOURCES})
@ -64,9 +64,9 @@ target_compile_features(cmkrlib PUBLIC
set(CMKR_SOURCES set(CMKR_SOURCES
src/main.cpp src/main.cpp
src/args.cpp src/args.cpp
) )
add_executable(cmkr ${CMKR_SOURCES}) add_executable(cmkr ${CMKR_SOURCES})
target_link_libraries(cmkr PUBLIC target_link_libraries(cmkr PUBLIC
cmkrlib cmkrlib
@ -76,7 +76,7 @@ install(
TARGETS cmkr TARGETS cmkr
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
COMPONENT cmkr COMPONENT cmkr
) )

@ -22,9 +22,9 @@ minimum = "3.15"
name = "app" name = "app"
version = "0.1.0" version = "0.1.0"
[[bin]] [[target]]
name = "app" name = "app"
type = "exe" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
``` ```
@ -42,19 +42,19 @@ toml11 = { git = "https://github.com/ToruNiina/toml11" }
filesystem = { git = "https://github.com/gulrak/filesystem" } filesystem = { git = "https://github.com/gulrak/filesystem" }
mpark_variant = { url = "https://github.com/mpark/variant/archive/v1.4.0.tar.gz" } mpark_variant = { url = "https://github.com/mpark/variant/archive/v1.4.0.tar.gz" }
[[bin]] [[target]]
name = "cmkrlib" name = "cmkrlib"
type = "static" type = "static"
sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"] sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"]
include-dirs = ["include"] include-directories = ["include"]
features = ["cxx_std_11"] compile-features = ["cxx_std_11"]
link-libs = ["toml11::toml11", "ghc_filesystem"] link-libraries = ["toml11::toml11", "ghc_filesystem"]
[[bin]] [[target]]
name = "cmkr" name = "cmkr"
type = "exe" type = "executable"
sources = ["src/main.cpp", "src/args.cpp"] sources = ["src/main.cpp", "src/args.cpp"]
link-libs = ["cmkrlib"] link-libraries = ["cmkrlib"]
[[install]] [[install]]
targets = ["cmkr"] targets = ["cmkr"]
@ -66,7 +66,7 @@ Currently supported fields:
[cmake] # required for top-level project [cmake] # required for top-level project
minimum = "3.15" # required minimum = "3.15" # required
subdirs = [] # optional subdirs = [] # optional
bin-dir = "bin" # optional build-dir = "build" # optional
cpp-flags = [] # optional cpp-flags = [] # optional
c-flags = [] # optional c-flags = [] # optional
link-flags = [] # optional link-flags = [] # optional
@ -95,15 +95,15 @@ toml11 = { git = "https://github.com/ToruNiina/toml11", tag = "v3.5.0" } # optio
APP_BUILD_STUFF = false # optional APP_BUILD_STUFF = false # optional
APP_OTHER_STUFF = { comment = "does other stuff", value = false } # optional APP_OTHER_STUFF = { comment = "does other stuff", value = false } # optional
[[bin]] # required, can define several binaries [[target]] # required, can define several binaries
name = "app" # required name = "app" # required
type = "exe" # required (exe || lib || shared || static || interface) type = "executable" # required (executable || library || shared || static || interface)
sources = ["src/*.cpp"] # required, supports globbing sources = ["src/*.cpp"] # required, supports globbing
include-dirs = ["include"] # optional include-directories = ["include"] # optional
alias = "" # optional alias = "" # optional
features = [] # optional compile-features = [] # optional
defines = [] # optional compile-definitions = [] # optional
link-libs = [] # optional link-libraries = [] # optional
properties = { PROPERTY1 = "property1", ... } # optional properties = { PROPERTY1 = "property1", ... } # optional
[[test]] # optional, can define several [[test]] # optional, can define several
@ -123,13 +123,13 @@ The cmkr executable can be run from the command-line:
``` ```
Usage: cmkr [arguments] Usage: cmkr [arguments]
arguments: arguments:
init [exe|lib|shared|static|interface] Starts a new project in the same directory. init [executable|library|shared|static|interface] Starts a new project in the same directory.
gen Generates CMakeLists.txt file. gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build. build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges. install Run cmake --install. Needs admin privileges.
clean Clean the build directory. clean Clean the build directory.
help Show help. help Show help.
version Current cmkr version. version Current cmkr version.
``` ```
The build command invokes cmake and the default build-system on your platform (unless a generator is specified), it also accepts extra cmake build arguments: The build command invokes cmake and the default build-system on your platform (unless a generator is specified), it also accepts extra cmake build arguments:
``` ```
@ -138,20 +138,20 @@ cmkr build --config Release
## Binary types ## Binary types
### exe ### executable
Executable binary. Executable binary. Equivalent to [add_executable(name)](https://cmake.org/cmake/help/latest/command/add_executable.html).
### lib ### library
Library, can be static or shared depending on the BUILD_SHARED_LIBS variable. Library, can be static or shared depending on the BUILD_SHARED_LIBS variable. Equivalent to [add_library()](https://cmake.org/cmake/help/latest/command/add_library.html).
### static ### static
Static library/archive. Static library/archive. Equivalent to [add_library(name STATIC)](https://cmake.org/cmake/help/latest/command/add_library.html).
### shared ### shared
Shared/dynamic library. Shared/dynamic library. Equivalent to [add_library(name SHARED)](https://cmake.org/cmake/help/latest/command/add_library.html).
### interface ### interface
Header-only library. Header-only library. Equivalent to [add_library(name INTERFACE)](https://cmake.org/cmake/help/latest/command/add_library.html).
## Roadmap ## Roadmap
- Support more cmake fields. - Support more cmake fields.

@ -10,19 +10,19 @@ toml11 = { git = "https://github.com/ToruNiina/toml11" }
filesystem = { git = "https://github.com/gulrak/filesystem" } filesystem = { git = "https://github.com/gulrak/filesystem" }
mpark_variant = { url = "https://github.com/mpark/variant/archive/v1.4.0.tar.gz" } mpark_variant = { url = "https://github.com/mpark/variant/archive/v1.4.0.tar.gz" }
[[bin]] [[target]]
name = "cmkrlib" name = "cmkrlib"
type = "static" type = "static"
sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"] sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"]
include-dirs = ["include"] include-directories = ["include"]
features = ["cxx_std_11"] compile-features = ["cxx_std_11"]
link-libs = ["toml11::toml11", "ghc_filesystem", "mpark_variant"] link-libraries = ["toml11::toml11", "ghc_filesystem", "mpark_variant"]
[[bin]] [[target]]
name = "cmkr" name = "cmkr"
type = "exe" type = "executable"
sources = ["src/main.cpp", "src/args.cpp"] sources = ["src/main.cpp", "src/args.cpp"]
link-libs = ["cmkrlib"] link-libraries = ["cmkrlib"]
[[install]] [[install]]
targets = ["cmkr"] targets = ["cmkr"]

@ -1,24 +1,25 @@
# This file was generated automatically by cmkr. # This file was generated automatically by cmkr.
# Regenerate CMakeLists.txt file when necessary # Regenerate CMakeLists.txt file when necessary
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT) if(CMKR_INCLUDE_RESULT)
cmkr() cmkr()
endif() endif()
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(example_PROJECT_VERSION 0.1.0)
project(example VERSION ${example_PROJECT_VERSION}) set(example_PROJECT_VERSION 0.1.0)
project(example VERSION ${example_PROJECT_VERSION})
set(EXAMPLE_SOURCES
src/example.cpp set(EXAMPLE_SOURCES
) src/example.cpp
)
add_executable(example ${EXAMPLE_SOURCES})
add_executable(example ${EXAMPLE_SOURCES})

@ -7,7 +7,7 @@ minimum = "3.15"
name = "example" name = "example"
version = "0.1.0" version = "0.1.0"
[[bin]] [[target]]
name = "example" name = "example"
type = "exe" type = "executable"
sources = ["src/example.cpp"] sources = ["src/example.cpp"]

@ -50,23 +50,19 @@ else()
if(NOT EXISTS ${CMKR_EXECUTABLE}) if(NOT EXISTS ${CMKR_EXECUTABLE})
message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'")
endif() endif()
cmkr_exec(${CMKR_EXECUTABLE} version OUTPUT_VARIABLE CMKR_VERSION) cmkr_exec(${CMKR_EXECUTABLE} version)
string(STRIP ${CMKR_VERSION} CMKR_VERSION)
message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}")
else() else()
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
endif() endif()
endif() endif()
execute_process(COMMAND ${CMKR_EXECUTABLE} version execute_process(COMMAND ${CMKR_EXECUTABLE} version
OUTPUT_VARIABLE CMKR_VERSION
RESULT_VARIABLE CMKR_EXEC_RESULT RESULT_VARIABLE CMKR_EXEC_RESULT
) )
if(NOT CMKR_EXEC_RESULT EQUAL 0) if(NOT CMKR_EXEC_RESULT EQUAL 0)
unset(CMKR_EXECUTABLE CACHE) unset(CMKR_EXECUTABLE CACHE)
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
endif() endif()
string(STRIP ${CMKR_VERSION} CMKR_VERSION)
message(STATUS "[cmkr] Using ${CMKR_VERSION}")
# This is the macro that contains black magic # This is the macro that contains black magic
macro(cmkr) macro(cmkr)
@ -83,12 +79,9 @@ macro(cmkr)
set_source_files_properties(${CMAKE_CURRENT_LIST_FILE} PROPERTIES CMKR_INCLUDE_GUARD TRUE) set_source_files_properties(${CMAKE_CURRENT_LIST_FILE} PROPERTIES CMKR_INCLUDE_GUARD TRUE)
# Generate CMakeLists.txt # Generate CMakeLists.txt
cmkr_exec(${CMKR_EXECUTABLE} gen -y cmkr_exec(${CMKR_EXECUTABLE} gen
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE CMKR_GEN_OUTPUT
) )
string(STRIP ${CMKR_GEN_OUTPUT} CMKR_GEN_OUTPUT)
message(STATUS "[cmkr] ${CMKR_GEN_OUTPUT}")
# Copy the now-generated CMakeLists.txt to CMakerLists.txt # Copy the now-generated CMakeLists.txt to CMakerLists.txt
# This is done because you cannot include() a file you are currently in # This is done because you cannot include() a file you are currently in

@ -14,7 +14,7 @@ const char *cmake_toml = R"lit(
[cmake] [cmake]
minimum = "3.15" minimum = "3.15"
# subdirs = [] # subdirs = []
# bin-dir = "" # build-dir = ""
# cpp-flags = [] # cpp-flags = []
# c-flags = [] # c-flags = []
# link-flags = [] # link-flags = []
@ -31,15 +31,15 @@ version = "0.1.0"
# [options] # [options]
[[bin]] [[target]]
name = "%s" name = "%s"
type = "%s" type = "%s"
sources = ["src/*.cpp"] sources = ["src/*.cpp"]
include-dirs = ["include"] include-directories = ["include"]
# alias = "" # alias = ""
# features = [] # compile-features = []
# defines = [] # compile-definitions = []
# link-libs = [] # link-libraries = []
[[install]] [[install]]
%s = ["%s"] %s = ["%s"]

@ -18,23 +18,10 @@ const char *handle_args(int argc, char **argv) {
args.push_back(argv[i]); args.push_back(argv[i]);
if (args.size() < 2) if (args.size() < 2)
return "Please provide command line arguments!"; throw std::runtime_error(cmkr::help::message());
std::string main_arg = args[1]; std::string main_arg = args[1];
if (main_arg == "gen") { if (main_arg == "gen") {
bool cont = false;
if (args.size() > 2 && args[2] == "-y")
cont = true;
auto current_path = fs::current_path(); auto current_path = fs::current_path();
if (fs::exists(current_path / "CMakeLists.txt") && cont == false) {
std::cout
<< "A CMakeLists.txt file already exists in the current directory.\nWould you "
"like to overwrite it?[y/n]"
<< std::endl;
std::string resp;
std::cin >> resp;
if (resp != "y")
return "CMake generation aborted!";
}
auto ret = cmkr::gen::generate_cmake(current_path.string().c_str()); auto ret = cmkr::gen::generate_cmake(current_path.string().c_str());
if (ret) if (ret)
return "CMake generation error!"; return "CMake generation error!";
@ -44,10 +31,10 @@ const char *handle_args(int argc, char **argv) {
} else if (main_arg == "version") { } else if (main_arg == "version") {
return cmkr::help::version(); return cmkr::help::version();
} else if (main_arg == "init") { } else if (main_arg == "init") {
std::string typ = "exe"; std::string type = "executable";
if (args.size() > 2) if (args.size() > 2)
typ = args[2]; type = args[2];
auto ret = cmkr::gen::generate_project(typ.c_str()); auto ret = cmkr::gen::generate_project(type.c_str());
if (ret) if (ret)
return "Initialization failure!"; return "Initialization failure!";
return "Directory initialized!"; return "Directory initialized!";
@ -67,7 +54,7 @@ const char *handle_args(int argc, char **argv) {
return "CMake clean error!"; return "CMake clean error!";
return "Cleaned build directory!"; return "Cleaned build directory!";
} else { } else {
return "Unknown argument!"; throw std::runtime_error(cmkr::help::message());
} }
} }
} // namespace args } // namespace args

@ -24,9 +24,9 @@ int run(int argc, char **argv) {
if (!fs::exists("CMakeLists.txt")) if (!fs::exists("CMakeLists.txt"))
if (gen::generate_cmake(".")) if (gen::generate_cmake("."))
throw std::runtime_error("[cmkr] error: CMake generation failure!"); throw std::runtime_error("CMake generation failure!");
ss << "cmake -S. -B" << cmake.bin_dir << " "; ss << "cmake -S. -B" << cmake.build_dir << " ";
if (!cmake.generator.empty()) { if (!cmake.generator.empty()) {
ss << "-G \"" << cmake.generator << "\" "; ss << "-G \"" << cmake.generator << "\" ";
@ -39,7 +39,7 @@ int run(int argc, char **argv) {
ss << "-D" << arg << " "; ss << "-D" << arg << " ";
} }
} }
ss << "&& cmake --build " << cmake.bin_dir << " --parallel"; ss << "&& cmake --build " << cmake.build_dir << " --parallel";
if (argc > 2) { if (argc > 2) {
for (const auto &arg : cmake.build_args) { for (const auto &arg : cmake.build_args) {
ss << " " << arg; ss << " " << arg;
@ -52,16 +52,16 @@ int run(int argc, char **argv) {
int clean() { int clean() {
bool ret = false; bool ret = false;
cmake::CMake cmake(".", true); cmake::CMake cmake(".", true);
if (fs::exists(cmake.bin_dir)) { if (fs::exists(cmake.build_dir)) {
ret = fs::remove_all(cmake.bin_dir); ret = fs::remove_all(cmake.build_dir);
fs::create_directory(cmake.bin_dir); fs::create_directory(cmake.build_dir);
} }
return !ret; return !ret;
} }
int install() { int install() {
cmake::CMake cmake(".", false); cmake::CMake cmake(".", false);
auto cmd = "cmake --install " + cmake.bin_dir; auto cmd = "cmake --install " + cmake.build_dir;
return ::system(cmd.c_str()); return ::system(cmd.c_str());
} }
} // namespace build } // namespace build

@ -20,7 +20,7 @@ std::vector<std::string> to_string_vec(
CMake::CMake(const std::string &path, bool build) { CMake::CMake(const std::string &path, bool build) {
if (!fs::exists(fs::path(path) / "cmake.toml")) { if (!fs::exists(fs::path(path) / "cmake.toml")) {
throw std::runtime_error("[cmkr] error: No cmake.toml was found!"); throw std::runtime_error("No cmake.toml was found!");
} }
const auto toml = toml::parse((fs::path(path) / "cmake.toml").string()); const auto toml = toml::parse((fs::path(path) / "cmake.toml").string());
if (build) { if (build) {
@ -28,7 +28,11 @@ CMake::CMake(const std::string &path, bool build) {
const auto &cmake = toml::find(toml, "cmake"); const auto &cmake = toml::find(toml, "cmake");
if (cmake.contains("bin-dir")) { if (cmake.contains("bin-dir")) {
bin_dir = toml::find(cmake, "bin-dir").as_string(); throw std::runtime_error("bin-dir has been renamed to build-dir");
}
if (cmake.contains("build-dir")) {
build_dir = toml::find(cmake, "build-dir").as_string();
} }
if (cmake.contains("generator")) { if (cmake.contains("generator")) {
@ -160,42 +164,61 @@ CMake::CMake(const std::string &path, bool build) {
} }
if (toml.contains("bin")) { if (toml.contains("bin")) {
const auto &bins = toml::find(toml, "bin").as_array(); throw std::runtime_error("[[bin]] has been renamed to [[target]]");
}
if (toml.contains("target")) {
const auto &ts = toml::find(toml, "target").as_array();
for (const auto &t : ts) {
Target target;
target.name = toml::find(t, "name").as_string();
target.type = toml::find(t, "type").as_string();
target.sources = detail::to_string_vec(toml::find(t, "sources").as_array());
#define renamed(from, to) \
if (t.contains(from)) { \
throw std::runtime_error(from "has been renamed to " to); \
}
for (const auto &bin : bins) { renamed("include-dirs", "include-directories");
Bin b; renamed("link-libs", "link-libraries");
b.name = toml::find(bin, "name").as_string(); renamed("defines", "compile-definitions");
b.type = toml::find(bin, "type").as_string(); renamed("features", "compile-features");
b.sources = detail::to_string_vec(toml::find(bin, "sources").as_array()); #undef renamed
if (bin.contains("include-dirs")) { if (t.contains("include-directories")) {
b.include_dirs = target.include_directories =
detail::to_string_vec(toml::find(bin, "include-dirs").as_array()); detail::to_string_vec(toml::find(t, "include-directories").as_array());
} }
if (bin.contains("link-libs")) { if (t.contains("link-libraries")) {
b.link_libs = detail::to_string_vec(toml::find(bin, "link-libs").as_array()); target.link_libraries =
detail::to_string_vec(toml::find(t, "link-libraries").as_array());
} }
if (bin.contains("features")) { if (t.contains("compile-features")) {
b.features = detail::to_string_vec(toml::find(bin, "features").as_array()); target.compile_features =
detail::to_string_vec(toml::find(t, "compile-features").as_array());
} }
if (bin.contains("defines")) { if (t.contains("compile-definitions")) {
b.defines = detail::to_string_vec(toml::find(bin, "defines").as_array()); target.compile_definitions =
detail::to_string_vec(toml::find(t, "compile-definitions").as_array());
} }
if (bin.contains("alias")) { if (t.contains("alias")) {
b.alias = toml::find(bin, "alias").as_string(); target.alias = toml::find(t, "alias").as_string();
} }
if (bin.contains("properties")) { if (t.contains("properties")) {
using prop_map = std::map<std::string, std::string>; using prop_map = std::map<std::string, std::string>;
b.properties = toml::find<prop_map>(bin, "properties"); target.properties = toml::find<prop_map>(t, "properties");
} }
binaries.push_back(b); binaries.push_back(target);
} }
} }

@ -30,14 +30,14 @@ struct Package {
std::vector<std::string> components; std::vector<std::string> components;
}; };
struct Bin { struct Target {
std::string name; std::string name;
std::string type; std::string type;
std::vector<std::string> sources; std::vector<std::string> sources;
std::vector<std::string> include_dirs; std::vector<std::string> include_directories;
std::vector<std::string> features; std::vector<std::string> compile_features;
std::vector<std::string> defines; std::vector<std::string> compile_definitions;
std::vector<std::string> link_libs; std::vector<std::string> link_libraries;
std::string alias; std::string alias;
std::map<std::string, std::string> properties; std::map<std::string, std::string> properties;
}; };
@ -57,8 +57,8 @@ struct Install {
}; };
struct CMake { struct CMake {
std::string cmake_version = "3.15"; std::string cmake_version;
std::string bin_dir = "bin"; std::string build_dir = "build";
std::string generator; std::string generator;
std::string config; std::string config;
std::vector<std::string> subdirs; std::vector<std::string> subdirs;
@ -73,7 +73,7 @@ struct CMake {
std::vector<Option> options; std::vector<Option> options;
std::vector<Package> packages; std::vector<Package> packages;
std::map<std::string, std::map<std::string, std::string>> contents; std::map<std::string, std::map<std::string, std::string>> contents;
std::vector<Bin> binaries; std::vector<Target> binaries;
std::vector<Test> tests; std::vector<Test> tests;
std::vector<Install> installs; std::vector<Install> installs;
CMake(const std::string &path, bool build); CMake(const std::string &path, bool build);

@ -32,7 +32,7 @@ std::string format(const char *fmt, Args... args) {
char *buf = new char[sz]; char *buf = new char[sz];
int ret = snprintf(buf, sz, fmt, args...); int ret = snprintf(buf, sz, fmt, args...);
if (ret != sz - 1) if (ret != sz - 1)
throw std::runtime_error("[cmkr] error: Error formatting string!"); throw std::runtime_error("Error formatting string!");
std::string temp(buf, buf + sz - 1); std::string temp(buf, buf + sz - 1);
delete[] buf; delete[] buf;
return temp; return temp;
@ -51,7 +51,7 @@ static std::vector<std::string> expand_cmake_path(const fs::path &p) {
temp.push_back(p.string()); temp.push_back(p.string());
} }
// Normalize all paths to work with CMake (it needs a / on Windows as well) // Normalize all paths to work with CMake (it needs a / on Windows as well)
for(auto& path : temp) { for (auto &path : temp) {
std::replace(path.begin(), path.end(), '\\', '/'); std::replace(path.begin(), path.end(), '\\', '/');
} }
return temp; return temp;
@ -67,12 +67,12 @@ int generate_project(const char *str) {
std::string installed; std::string installed;
std::string target; std::string target;
std::string dest; std::string dest;
if (!strcmp(str, "exe")) { if (!strcmp(str, "executable")) {
mainbuf = detail::format(hello_world, "main"); mainbuf = detail::format(hello_world, "main");
installed = "targets"; installed = "targets";
target = dir_name; target = dir_name;
dest = "bin"; dest = "bin";
} else if (!strcmp(str, "static") || !strcmp(str, "shared") || !strcmp(str, "lib")) { } else if (!strcmp(str, "static") || !strcmp(str, "shared") || !strcmp(str, "library")) {
mainbuf = detail::format(hello_world, "test"); mainbuf = detail::format(hello_world, "test");
installed = "targets"; installed = "targets";
target = dir_name; target = dir_name;
@ -83,7 +83,8 @@ int generate_project(const char *str) {
dest = "include/" + dir_name; dest = "include/" + dir_name;
} else { } else {
throw std::runtime_error( throw std::runtime_error(
"[cmkr] error: Unknown project type. Types are exe, lib, shared, static, interface!"); "Unknown project type " + std::string(str) +
"! Supported types are: executable, library, shared, static, interface");
} }
const auto tomlbuf = detail::format(cmake_toml, dir_name.c_str(), dir_name.c_str(), str, const auto tomlbuf = detail::format(cmake_toml, dir_name.c_str(), dir_name.c_str(), str,
@ -122,11 +123,11 @@ int generate_cmake(const char *path) {
ss << "endif()\n"; ss << "endif()\n";
ss << "\n"; ss << "\n";
if (!cmake.cmake_version.empty()) { ss << "cmake_minimum_required(VERSION " << cmake.cmake_version << ")\n";
ss << "cmake_minimum_required(VERSION " << cmake.cmake_version << ")\n\n"; ss << "\n";
ss << "set(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\n"; ss << "set_property(GLOBAL PROPERTY USE_FOLDERS ON)\n";
} ss << "\n";
if (!cmake.cppflags.empty()) { if (!cmake.cppflags.empty()) {
ss << "set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} \""; ss << "set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} \"";
@ -208,7 +209,7 @@ int generate_cmake(const char *path) {
} }
ss << "\t" << first_arg << " " << arg.second << "\n"; ss << "\t" << first_arg << " " << arg.second << "\n";
} }
ss << "\t)\n\n" ss << ")\n\n"
<< "FetchContent_MakeAvailable(" << dep.first << ")\n\n"; << "FetchContent_MakeAvailable(" << dep.first << ")\n\n";
} }
} }
@ -248,19 +249,20 @@ int generate_cmake(const char *path) {
for (const auto &bin : cmake.binaries) { for (const auto &bin : cmake.binaries) {
std::string bin_type; std::string bin_type;
std::string add_command; std::string add_command;
if (bin.type == "exe") { if (bin.type == "executable") {
bin_type = ""; bin_type = "";
add_command = "add_executable"; add_command = "add_executable";
} else if (bin.type == "shared" || bin.type == "static" || } else if (bin.type == "shared" || bin.type == "static" ||
bin.type == "interface") { bin.type == "interface") {
bin_type = detail::to_upper(bin.type); bin_type = detail::to_upper(bin.type);
add_command = "add_library"; add_command = "add_library";
} else if (bin.type == "lib") { } else if (bin.type == "library") {
bin_type = ""; bin_type = "";
add_command = "add_library"; add_command = "add_library";
} else { } else {
throw std::runtime_error("[cmkr] error: Unknown binary type! Supported types " throw std::runtime_error(
"are exe, lib, shared, static, interface"); "Unknown binary type " + bin.type +
"! Supported types are: executable, library, shared, static, interface");
} }
if (!bin.sources.empty()) { if (!bin.sources.empty()) {
@ -272,10 +274,12 @@ int generate_cmake(const char *path) {
ss << "\t" << f << "\n"; ss << "\t" << f << "\n";
} }
} }
ss << "\t)\n\n"; ss << ")\n\n";
} }
ss << add_command << "(" << bin.name << " " << bin_type; ss << add_command << "(" << bin.name;
if (!bin_type.empty())
ss << " " << bin_type;
if (!bin.sources.empty()) { if (!bin.sources.empty()) {
ss << " ${" << detail::to_upper(bin.name) << "_SOURCES})\n\n"; ss << " ${" << detail::to_upper(bin.name) << "_SOURCES})\n\n";
@ -287,33 +291,33 @@ int generate_cmake(const char *path) {
ss << "add_library(" << bin.alias << " ALIAS " << bin.name << ")\n\n"; ss << "add_library(" << bin.alias << " ALIAS " << bin.name << ")\n\n";
} }
if (!bin.include_dirs.empty()) { if (!bin.include_directories.empty()) {
ss << "target_include_directories(" << bin.name << " PUBLIC\n\t"; ss << "target_include_directories(" << bin.name << " PUBLIC\n\t";
for (const auto &inc : bin.include_dirs) { for (const auto &inc : bin.include_directories) {
ss << fs::path(inc).string() << "\n\t"; ss << fs::path(inc).string() << "\n\t";
} }
ss << ")\n\n"; ss << ")\n\n";
} }
if (!bin.link_libs.empty()) { if (!bin.link_libraries.empty()) {
ss << "target_link_libraries(" << bin.name << " PUBLIC\n\t"; ss << "target_link_libraries(" << bin.name << " PUBLIC\n\t";
for (const auto &l : bin.link_libs) { for (const auto &l : bin.link_libraries) {
ss << l << "\n\t"; ss << l << "\n\t";
} }
ss << ")\n\n"; ss << ")\n\n";
} }
if (!bin.features.empty()) { if (!bin.compile_features.empty()) {
ss << "target_compile_features(" << bin.name << " PUBLIC\n\t"; ss << "target_compile_features(" << bin.name << " PUBLIC\n\t";
for (const auto &feat : bin.features) { for (const auto &feat : bin.compile_features) {
ss << feat << "\n\t"; ss << feat << "\n\t";
} }
ss << ")\n\n"; ss << ")\n\n";
} }
if (!bin.defines.empty()) { if (!bin.compile_definitions.empty()) {
ss << "target_add_definitions(" << bin.name << " PUBLIC\n\t"; ss << "target_add_definitions(" << bin.name << " PUBLIC\n\t";
for (const auto &def : bin.defines) { for (const auto &def : bin.compile_definitions) {
ss << def << "\n\t"; ss << def << "\n\t";
} }
ss << ")\n\n"; ss << ")\n\n";
@ -324,7 +328,7 @@ int generate_cmake(const char *path) {
for (const auto &prop : bin.properties) { for (const auto &prop : bin.properties) {
ss << "\t" << prop.first << " " << prop.second << "\n"; ss << "\t" << prop.first << " " << prop.second << "\n";
} }
ss << "\t)\n\n"; ss << ")\n\n";
} }
} }
} }
@ -374,16 +378,16 @@ int generate_cmake(const char *path) {
} }
ss << "\n\tDESTINATION " << inst.destination << "\n\t"; ss << "\n\tDESTINATION " << inst.destination << "\n\t";
if (!inst.targets.empty()) if (!inst.targets.empty())
ss << "COMPONENT " << inst.targets[0] << "\n\t)\n\n"; ss << "COMPONENT " << inst.targets[0] << "\n)\n\n";
else else
ss << "\n\t)\n\n"; ss << "\n)\n\n";
} }
} }
ss << "\n\n"; ss << "\n\n";
// printf("%s\n", ss.str().c_str()); // printf("%s\n", ss.str().c_str());
std::ofstream ofs(fs::path(path) / "CMakeLists.txt"); std::ofstream ofs(fs::path(path) / "CMakeLists.txt", std::ios_base::binary);
if (ofs.is_open()) { if (ofs.is_open()) {
ofs << ss.rdbuf(); ofs << ss.rdbuf();
} }
@ -395,7 +399,7 @@ int generate_cmake(const char *path) {
generate_cmake(sub.c_str()); generate_cmake(sub.c_str());
} }
} else { } else {
throw std::runtime_error("[cmkr] error: No cmake.toml found!"); throw std::runtime_error("No cmake.toml found!");
} }
return 0; return 0;
} }

@ -9,14 +9,14 @@ const char *message() noexcept {
return R"lit( return R"lit(
Usage: cmkr [arguments] Usage: cmkr [arguments]
arguments: arguments:
init [exe|lib|shared|static|interface] Starts a new project in the same directory. init [executable|library|shared|static|interface] Starts a new project in the same directory.
gen Generates CMakeLists.txt file. gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build. build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges. install Run cmake --install. Needs admin privileges.
clean Clean the build directory. clean Clean the build directory.
help Show help. help Show help.
version Current cmkr version. version Current cmkr version.
)lit"; )lit";
} }
} // namespace help } // namespace help
} // namespace cmkr } // namespace cmkr

@ -6,8 +6,15 @@
int main(int argc, char **argv) try { int main(int argc, char **argv) try {
auto output = cmkr::args::handle_args(argc, argv); auto output = cmkr::args::handle_args(argc, argv);
return fprintf(stdout, "%s\n", output) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; auto format = "[cmkr] %s\n";
if (strchr(output, '\n') != nullptr)
format = "%s\n";
(void)fprintf(stderr, format, output);
return EXIT_SUCCESS;
} catch (const std::exception &e) { } catch (const std::exception &e) {
(void)fprintf(stderr, "%s\n", e.what()); auto format = "[cmkr] error: %s\n";
if (strchr(e.what(), '\n') != nullptr)
format = "%s\n";
(void)fprintf(stderr, format, e.what());
return EXIT_FAILURE; return EXIT_FAILURE;
} }

Loading…
Cancel
Save