Compare commits

..

13 Commits

Author SHA1 Message Date
MoAlyousef f8ab24e0a2 bump 0.1.3 2020-11-27 17:46:32 +03:00
MoAlyousef 16e68d7542 fix C++11 build 2020-11-27 17:38:40 +03:00
MoAlyousef 5dc71f9ba1 support building with C++11, adding linux github actions 2020-11-27 17:29:57 +03:00
MoAlyousef ba2c52dd39 unify error messages 2020-11-27 14:48:15 +03:00
MoAlyousef 41b00b4f98 reflect gen code in new CMakeLists.txt 2020-11-27 14:35:11 +03:00
Mohammed Alyousef b016d7139c Update cmkr.cmake 2020-11-27 14:23:12 +03:00
Mohammed Alyousef 473926bcfd Merge pull request #2 from mrexodia/cmake-integration
Implement CMake integration + bootstrapping
2020-11-27 14:22:17 +03:00
Duncan Ogilvie f29f9fa365 Implement CMake bootstrapping + integration 2020-11-26 23:51:25 +01:00
Duncan Ogilvie 4c59ca75da Ignore build*/ folders 2020-11-26 23:44:19 +01:00
Duncan Ogilvie 1114aaca94 Add cmkr COMPONENT when installing 2020-11-26 20:05:29 +01:00
Mohammed Alyousef 887f9e4ece add prompt if CMakeLists.txt already exists 2020-11-20 19:28:15 +03:00
Mohammed Alyousef fa510bb00e bump 0.1.2 2020-11-20 18:51:08 +03:00
MoAlyousef 31bf4e3e96 fix == error 2020-11-19 01:36:51 +03:00
23 changed files with 444 additions and 69 deletions
+2 -2
View File
@@ -11,9 +11,9 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macos-10.15]
os: [windows-latest, macos-10.15, ubuntu-18.04]
steps:
- uses: actions/checkout@v2
- name: Build
run: cmake -S. -Bbin && cmake --build bin --config $BUILD_TYPE
run: cmake -S. -Bbin && cmake --build bin --parallel --config $BUILD_TYPE
+2 -1
View File
@@ -4,4 +4,5 @@ compile_commands.json
.clangd
temp.*
.vs
.cache
.cache
build*/
+14 -3
View File
@@ -1,11 +1,22 @@
# CHANGELOG
## 0.1.3 - 2020-11-27
- Support building with C++11.
- @mrexodia implemented CMake integration and bootstrapping.
- Add dependency on ghc_filesystem which is fetched automatically using FetchContent.
## 0.1.2 - 2020-11-20
- Add support for target properties.
- Add installs.
- Require cmake >= 3.15.
- Support settings and caching settings.
- Support config when running cmkr build.
- Add prompt prior to CMakeLists.txt generation if already existent in the current dir.
## 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.
- Require cmake >= 3.15.
- Support testing.
+19 -3
View File
@@ -1,13 +1,28 @@
# This file was generated automatically by cmkr.
# Regenerate CMakeLists.txt file when necessary
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
cmake_minimum_required(VERSION 3.15)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(cmkr VERSION 0.1.1)
set(cmkr_PROJECT_VERSION 0.1.3)
project(cmkr VERSION ${cmkr_PROJECT_VERSION})
include(FetchContent)
FetchContent_Declare(
filesystem
GIT_REPOSITORY https://github.com/gulrak/filesystem
)
FetchContent_MakeAvailable(filesystem)
FetchContent_Declare(
toml11
GIT_REPOSITORY https://github.com/ToruNiina/toml11
@@ -15,7 +30,6 @@ FetchContent_Declare(
FetchContent_MakeAvailable(toml11)
set(CMKRLIB_SOURCES
"src/cmake.cpp"
"src/gen.cpp"
@@ -32,10 +46,11 @@ target_include_directories(cmkrlib PUBLIC
target_link_libraries(cmkrlib PUBLIC
toml11::toml11
ghc_filesystem
)
target_compile_features(cmkrlib PUBLIC
cxx_std_17
cxx_std_11
)
set(CMKR_SOURCES
@@ -52,6 +67,7 @@ target_link_libraries(cmkr PUBLIC
install(
TARGETS cmkr
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
COMPONENT cmkr
)
+15 -6
View File
@@ -9,7 +9,7 @@ cmkr requires a C++17 compiler, cmake >= 3.15.
git clone https://github.com/moalyousef/cmkr
cd cmkr
cmake -Bbin
cmake --build bin
cmake --build bin --parallel
```
## Usage
@@ -35,18 +35,19 @@ minimum = "3.15"
[project]
name = "cmkr"
version = "0.1.0"
version = "0.1.3"
[fetch-content]
toml11 = { git = "https://github.com/ToruNiina/toml11" }
filesystem = { git = "https://github.com/gulrak/filesystem" }
[[bin]]
name = "cmkrlib"
type = "static"
sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"]
include-dirs = ["include"]
features = ["cxx_std_17"]
link-libs = ["toml11::toml11"]
features = ["cxx_std_11"]
link-libs = ["toml11::toml11", "ghc_filesystem"]
[[bin]]
name = "cmkr"
@@ -68,8 +69,15 @@ bin-dir = "bin" # optional
cpp-flags = [] # optional
c-flags = [] # optional
link-flags = [] # optional
generator = "Ninja" # optional
arguments = ["CMAKE_TOOLCHAIN_FILE=/path/to/toolchain"] # optional
generator = "Ninja" # optional, only valid when run using: cmkr build
config = "Release" # optional, only valid when run using: cmkr build
arguments = ["CMAKE_TOOLCHAIN_FILE=/path/to/toolchain"] # optional, valid when run using: cmkr build
[settings] # optional
CMAKE_BUILD_TYPE = "Release"
TOML_BUILD_TESTS = false # optional
TOML_BUILD_DOCS = { value = false, comment = "builds dependency docs", cache = true, force = true } # optional
OLD_VERSION = "0.1.1" # optional
[project] # required per project
name = "app" # required
@@ -95,6 +103,7 @@ alias = "" # optional
features = [] # optional
defines = [] # optional
link-libs = [] # optional
properties = { PROPERTY1 = "property1", ... } # optional
[[test]] # optional, can define several
name = "test1" # required
+4 -3
View File
@@ -3,18 +3,19 @@ minimum = "3.15"
[project]
name = "cmkr"
version = "0.1.1"
version = "0.1.3"
[fetch-content]
toml11 = { git = "https://github.com/ToruNiina/toml11" }
filesystem = { git = "https://github.com/gulrak/filesystem" }
[[bin]]
name = "cmkrlib"
type = "static"
sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"]
include-dirs = ["include"]
features = ["cxx_std_17"]
link-libs = ["toml11::toml11"]
features = ["cxx_std_11"]
link-libs = ["toml11::toml11", "ghc_filesystem"]
[[bin]]
name = "cmkr"
+23
View File
@@ -0,0 +1,23 @@
# This file was generated automatically by cmkr.
# Regenerate CMakeLists.txt file when necessary
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
cmake_minimum_required(VERSION 3.15)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(example_PROJECT_VERSION 0.1.0)
project(example VERSION ${example_PROJECT_VERSION})
set(EXAMPLE_SOURCES
"src/example.cpp"
)
add_executable(example ${EXAMPLE_SOURCES})
+13
View File
@@ -0,0 +1,13 @@
# This is a minimal example project used for testing the cmkr bootstrapping process
[cmake]
minimum = "3.15"
[project]
name = "example"
version = "0.1.0"
[[bin]]
name = "example"
type = "exe"
sources = ["src/example.cpp"]
+112
View File
@@ -0,0 +1,112 @@
include_guard()
# Disable cmkr if no cmake.toml file is found
if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/cmake.toml)
message(STATUS "[cmkr] Not found: ${CMAKE_CURRENT_LIST_DIR}/cmake.toml")
macro(cmkr)
endmacro()
return()
endif()
# Add a build-time dependency on the contents of cmake.toml to regenerate the CMakeLists.txt when modified
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake.toml ${CMAKE_CURRENT_BINARY_DIR}/cmake.toml COPYONLY)
# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher)
macro(cmkr_exec)
execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})")
endif()
endmacro()
# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment)
if(WIN32)
set(CMKR_EXECUTABLE_NAME "cmkr.exe")
else()
set(CMKR_EXECUTABLE_NAME "cmkr")
endif()
# Use cached cmkr if found
if(DEFINED CACHE{CMKR_EXECUTABLE} AND EXISTS ${CMKR_EXECUTABLE})
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
else()
if(DEFINED CACHE{CMKR_EXECUTABLE})
message(VERBOSE "[cmkr] '${CMKR_EXECUTABLE}' not found")
endif()
set(CMKR_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_cmkr)
set(CMKR_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/_cmkr/bin/${CMKR_EXECUTABLE_NAME} CACHE INTERNAL "Full path to cmkr executable")
if(NOT EXISTS ${CMKR_EXECUTABLE})
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
message(STATUS "[cmkr] Fetching cmkr...")
if(EXISTS ${CMKR_DIRECTORY})
cmkr_exec(${CMAKE_COMMAND} -E rm -rf ${CMKR_DIRECTORY})
endif()
find_package(Git QUIET REQUIRED)
set(CMKR_REPO "https://github.com/moalyousef/cmkr")
cmkr_exec(${GIT_EXECUTABLE} clone ${CMKR_REPO} ${CMKR_DIRECTORY})
cmkr_exec(${CMAKE_COMMAND} ${CMKR_DIRECTORY} -B${CMKR_DIRECTORY}/build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY})
cmkr_exec(${CMAKE_COMMAND} --build ${CMKR_DIRECTORY}/build --parallel --config Release)
cmkr_exec(${CMAKE_COMMAND} --install ${CMKR_DIRECTORY}/build --config Release --prefix ${CMKR_DIRECTORY} --component cmkr)
if(NOT EXISTS ${CMKR_EXECUTABLE})
message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'")
endif()
cmkr_exec(${CMKR_EXECUTABLE} version OUTPUT_VARIABLE CMKR_VERSION)
string(STRIP ${CMKR_VERSION} CMKR_VERSION)
message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}")
else()
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
endif()
endif()
execute_process(COMMAND ${CMKR_EXECUTABLE} version
OUTPUT_VARIABLE CMKR_VERSION
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
unset(CMKR_EXECUTABLE CACHE)
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
endif()
string(STRIP ${CMKR_VERSION} CMKR_VERSION)
message(STATUS "[cmkr] Using ${CMKR_VERSION}")
# This is the macro that contains black magic
macro(cmkr)
# When this macro is called from the generated file, fake some internal CMake variables
get_source_file_property(CMKR_CURRENT_LIST_FILE ${CMAKE_CURRENT_LIST_FILE} CMKR_CURRENT_LIST_FILE)
if(CMKR_CURRENT_LIST_FILE)
set(CMAKE_CURRENT_LIST_FILE ${CMKR_CURRENT_LIST_FILE})
get_filename_component(CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY)
endif()
# File-based include guard (include_guard is not documented to work)
get_source_file_property(CMKR_INCLUDE_GUARD ${CMAKE_CURRENT_LIST_FILE} CMKR_INCLUDE_GUARD)
if(NOT CMKR_INCLUDE_GUARD)
set_source_files_properties(${CMAKE_CURRENT_LIST_FILE} PROPERTIES CMKR_INCLUDE_GUARD TRUE)
# Generate CMakeLists.txt
cmkr_exec(${CMKR_EXECUTABLE} gen -y
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
# This is done because you cannot include() a file you are currently in
set(CMKR_TEMP_FILE ${CMAKE_CURRENT_LIST_DIR}/CMakerLists.txt)
configure_file(CMakeLists.txt ${CMKR_TEMP_FILE} COPYONLY)
# Add the macro required for the hack at the start of the cmkr macro
set_source_files_properties(${CMKR_TEMP_FILE} PROPERTIES
CMKR_CURRENT_LIST_FILE ${CMAKE_CURRENT_LIST_FILE}
)
# 'Execute' the newly-generated CMakeLists.txt
include(${CMKR_TEMP_FILE})
# Delete the generated file
file(REMOVE ${CMKR_TEMP_FILE})
# Do not execute the rest of the original CMakeLists.txt
return()
endif()
endmacro()
+6
View File
@@ -0,0 +1,6 @@
#include <cstdio>
int main()
{
puts("Hello from cmkr!");
}
+5 -2
View File
@@ -1,10 +1,13 @@
#pragma once
#ifdef __cplusplus
namespace cmkr::args {
namespace cmkr {
namespace args {
const char *handle_args(int argc, char **argv);
}
} // namespace args
} // namespace cmkr
extern "C" {
#endif
+4 -2
View File
@@ -2,7 +2,8 @@
#ifdef __cplusplus
namespace cmkr::build {
namespace cmkr {
namespace build {
int run(int argc, char **argv);
@@ -10,7 +11,8 @@ int clean();
int install();
} // namespace cmkr::build
} // namespace build
} // namespace cmkr
extern "C" {
#endif
+4 -2
View File
@@ -1,7 +1,8 @@
#pragma once
#ifdef __cplusplus
namespace cmkr::error {
namespace cmkr {
namespace error {
struct Status {
enum class Code {
@@ -21,7 +22,8 @@ struct Status {
Code ec_ = Code::Success;
};
} // namespace cmkr::error
} // namespace error
} // namespace cmkr
extern "C" {
#endif
+4 -2
View File
@@ -1,13 +1,15 @@
#pragma once
#ifdef __cplusplus
namespace cmkr::gen {
namespace cmkr {
namespace gen {
int generate_project(const char *typ);
int generate_cmake(const char *path);
} // namespace cmkr::gen
} // namespace gen
} // namespace cmkr
extern "C" {
#endif
+4 -2
View File
@@ -1,13 +1,15 @@
#pragma once
#ifdef __cplusplus
namespace cmkr::help {
namespace cmkr {
namespace help {
const char *version() noexcept;
const char *message() noexcept;
} // namespace cmkr::help
} // namespace help
} // namespace cmkr
extern "C" {
#endif
+21 -4
View File
@@ -3,13 +3,15 @@
#include "gen.h"
#include "help.h"
#include "fs.hpp"
#include <exception>
#include <filesystem>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
namespace cmkr::args {
namespace cmkr {
namespace args {
const char *handle_args(int argc, char **argv) {
std::vector<std::string> args;
for (int i = 0; i < argc; ++i)
@@ -19,7 +21,21 @@ const char *handle_args(int argc, char **argv) {
return "Please provide command line arguments!";
std::string main_arg = args[1];
if (main_arg == "gen") {
auto ret = cmkr::gen::generate_cmake(std::filesystem::current_path().string().c_str());
bool cont = false;
if (args.size() > 2 && args[2] == "-y")
cont = true;
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());
if (ret)
return "CMake generation error!";
return "CMake generation successful!";
@@ -54,7 +70,8 @@ const char *handle_args(int argc, char **argv) {
return "Unknown argument!";
}
}
} // namespace cmkr::args
} // namespace args
} // namespace cmkr
const char *cmkr_args_handle_args(int argc, char **argv) {
try {
+10 -8
View File
@@ -3,16 +3,15 @@
#include "error.h"
#include "gen.h"
#include <filesystem>
#include "fs.hpp"
#include <sstream>
#include <stddef.h>
#include <stdexcept>
#include <stdlib.h>
#include <system_error>
namespace fs = std::filesystem;
namespace cmkr::build {
namespace cmkr {
namespace build {
int run(int argc, char **argv) {
cmake::CMake cmake(".", true);
@@ -25,19 +24,22 @@ int run(int argc, char **argv) {
if (!fs::exists("CMakeLists.txt"))
if (gen::generate_cmake("."))
throw std::runtime_error("CMake generation failure!");
throw std::runtime_error("[cmkr] error: CMake generation failure!");
ss << "cmake -S. -B" << cmake.bin_dir << " ";
if (!cmake.generator.empty()) {
ss << "-G \"" << cmake.generator << "\" ";
}
if (!cmake.config.empty()) {
ss << "-DCMAKE_BUILD_TYPE=" << cmake.config << " ";
}
if (!cmake.gen_args.empty()) {
for (const auto &arg : cmake.gen_args) {
ss << "-D" << arg << " ";
}
}
ss << "&& cmake --build " << cmake.bin_dir;
ss << "&& cmake --build " << cmake.bin_dir << " --parallel";
if (argc > 2) {
for (const auto &arg : cmake.build_args) {
ss << " " << arg;
@@ -62,8 +64,8 @@ int install() {
auto cmd = "cmake --install " + cmake.bin_dir;
return ::system(cmd.c_str());
}
} // namespace cmkr::build
} // namespace build
} // namespace cmkr
int cmkr_build_run(int argc, char **argv) {
try {
+50 -6
View File
@@ -1,12 +1,11 @@
#include "cmake.hpp"
#include <filesystem>
#include "fs.hpp"
#include <stdexcept>
#include <toml.hpp>
namespace fs = std::filesystem;
namespace cmkr::cmake {
namespace cmkr {
namespace cmake {
namespace detail {
std::vector<std::string> to_string_vec(
@@ -21,7 +20,7 @@ std::vector<std::string> to_string_vec(
CMake::CMake(const std::string &path, bool build) {
if (!fs::exists(fs::path(path) / "cmake.toml")) {
throw std::runtime_error("No cmake.toml was found!");
throw std::runtime_error("[cmkr] error: No cmake.toml was found!");
}
const auto toml = toml::parse((fs::path(path) / "cmake.toml").string());
if (build) {
@@ -36,6 +35,10 @@ CMake::CMake(const std::string &path, bool build) {
generator = toml::find(cmake, "generator").as_string();
}
if (cmake.contains("config")) {
config = toml::find(cmake, "config").as_string();
}
if (cmake.contains("arguments")) {
gen_args = detail::to_string_vec(toml::find(cmake, "arguments").as_array());
}
@@ -68,6 +71,41 @@ CMake::CMake(const std::string &path, bool build) {
proj_version = toml::find(project, "version").as_string();
}
if (toml.contains("settings")) {
using set_map =
std::map<std::string, toml::basic_value<toml::discard_comments, std::unordered_map,
std::vector>>;
const auto &sets = toml::find<set_map>(toml, "settings");
for (const auto set : sets) {
Setting s;
s.name = set.first;
if (set.second.is_boolean()) {
s.val = set.second.as_boolean();
} else if (set.second.is_string()) {
s.val = set.second.as_string();
} else {
if (set.second.contains("comment")) {
s.comment = toml::find(set.second, "comment").as_string();
}
if (set.second.contains("value")) {
auto v = toml::find(set.second, "value");
if (v.is_boolean()) {
s.val = v.as_boolean();
} else {
s.val = v.as_string();
}
}
if (set.second.contains("cache")) {
s.cache = toml::find(set.second, "cache").as_boolean();
}
if (set.second.contains("force")) {
s.force = toml::find(set.second, "force").as_boolean();
}
}
settings.push_back(s);
}
}
if (toml.contains("options")) {
using opts_map =
std::map<std::string, toml::basic_value<toml::discard_comments, std::unordered_map,
@@ -152,6 +190,11 @@ CMake::CMake(const std::string &path, bool build) {
b.alias = toml::find(bin, "alias").as_string();
}
if (bin.contains("properties")) {
using prop_map = std::map<std::string, std::string>;
b.properties = toml::find<prop_map>(bin, "properties");
}
binaries.push_back(b);
}
}
@@ -191,4 +234,5 @@ CMake::CMake(const std::string &path, bool build) {
}
}
}
} // namespace cmkr::cmake
} // namespace cmake
} // namespace cmkr
+45 -2
View File
@@ -1,10 +1,49 @@
#pragma once
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
namespace cmkr::cmake {
namespace cmkr {
namespace cmake {
namespace detail {
template <typename T, typename O>
struct Variant {
T first;
O second;
Variant() {}
Variant(const T &t) : first(t), tag(0) {}
Variant(const O &o) : second(o), tag(1) {}
Variant &operator=(const T &t) {
tag = 0;
first = t;
return *this;
}
Variant &operator=(const O &o) {
tag = 1;
second = o;
return *this;
}
char index() const {
if (tag == -1)
throw std::runtime_error("[cmkr] error: Internal error!");
return tag;
}
private:
char tag = -1;
};
} // namespace detail
struct Setting {
std::string name;
std::string comment;
detail::Variant<bool, std::string> val;
bool cache = false;
bool force = false;
};
struct Option {
std::string name;
@@ -28,6 +67,7 @@ struct Bin {
std::vector<std::string> defines;
std::vector<std::string> link_libs;
std::string alias;
std::map<std::string, std::string> properties;
};
struct Test {
@@ -48,6 +88,7 @@ struct CMake {
std::string cmake_version = "3.15";
std::string bin_dir = "bin";
std::string generator;
std::string config;
std::vector<std::string> subdirs;
std::vector<std::string> cppflags;
std::vector<std::string> cflags;
@@ -56,6 +97,7 @@ struct CMake {
std::vector<std::string> build_args;
std::string proj_name;
std::string proj_version;
std::vector<Setting> settings;
std::vector<Option> options;
std::vector<Package> packages;
std::map<std::string, std::map<std::string, std::string>> contents;
@@ -65,4 +107,5 @@ struct CMake {
CMake(const std::string &path, bool build);
};
} // namespace cmkr::cmake
} // namespace cmake
} // namespace cmkr
+4 -2
View File
@@ -2,7 +2,8 @@
#include <assert.h>
namespace cmkr::error {
namespace cmkr {
namespace error {
Status::Status(Code ec) noexcept : ec_(ec) {}
@@ -10,7 +11,8 @@ Status::operator int() const noexcept { return static_cast<int>(ec_); }
Status::Code Status::code() const noexcept { return ec_; }
} // namespace cmkr::error
} // namespace error
} // namespace cmkr
const char *err_string[] = {
"Success", "Runtime error", "Initialization error", "CMake generation error", "Build error",
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || \
(defined(__cplusplus) && __cplusplus >= 201703L)) && \
defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs = std::filesystem;
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
#endif
+63 -16
View File
@@ -3,7 +3,7 @@
#include "error.h"
#include "literals.h"
#include <filesystem>
#include "fs.hpp"
#include <fstream>
#include <new>
#include <sstream>
@@ -12,9 +12,8 @@
#include <string.h>
#include <string>
namespace fs = std::filesystem;
namespace cmkr::gen {
namespace cmkr {
namespace gen {
namespace detail {
@@ -33,7 +32,7 @@ std::string format(const char *fmt, Args... args) {
char *buf = new char[sz];
int ret = snprintf(buf, sz, fmt, args...);
if (ret != sz - 1)
throw std::runtime_error("Error formatting string!");
throw std::runtime_error("[cmkr] error: Error formatting string!");
std::string temp(buf, buf + sz - 1);
delete[] buf;
return temp;
@@ -80,7 +79,7 @@ int generate_project(const char *str) {
dest = "include/" + dir_name;
} else {
throw std::runtime_error(
"Unknown project type. Types are exe, lib, shared, static, interface!");
"[cmkr] 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,
@@ -109,7 +108,15 @@ int generate_cmake(const char *path) {
if (fs::exists(fs::path(path) / "cmake.toml")) {
cmake::CMake cmake(path, false);
std::stringstream ss;
ss << "# This file was generated automatically by cmkr.\n\n";
ss << "# This file was generated automatically by cmkr.\n";
ss << "\n";
ss << "# Regenerate CMakeLists.txt file when necessary\n";
ss << "include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)\n\n";
ss << "if(CMKR_INCLUDE_RESULT)\n";
ss << "\tcmkr()\n";
ss << "endif()\n";
ss << "\n";
if (!cmake.cmake_version.empty()) {
ss << "cmake_minimum_required(VERSION " << cmake.cmake_version << ")\n\n";
@@ -149,7 +156,10 @@ int generate_cmake(const char *path) {
}
if (!cmake.proj_name.empty() && !cmake.proj_version.empty()) {
ss << "project(" << cmake.proj_name << " VERSION " << cmake.proj_version << ")\n\n";
ss << "set(" << cmake.proj_name << "_PROJECT_VERSION " << cmake.proj_version << ")\n"
<< "project(" << cmake.proj_name << " VERSION "
<< "${" << cmake.proj_name << "_PROJECT_VERSION}"
<< ")\n\n";
}
if (!cmake.packages.empty()) {
@@ -182,9 +192,9 @@ int generate_cmake(const char *path) {
} else if (first_arg == "tag") {
first_arg = "GIT_TAG";
} else if (first_arg == "svn") {
first_arg == "SVN_REPOSITORY";
first_arg = "SVN_REPOSITORY";
} else if (first_arg == "rev") {
first_arg == "SVN_REVISION";
first_arg = "SVN_REVISION";
} else if (first_arg == "url") {
first_arg = "URL";
} else if (first_arg == "hash") {
@@ -202,11 +212,33 @@ int generate_cmake(const char *path) {
if (!cmake.options.empty()) {
for (const auto &opt : cmake.options) {
ss << "option(" << opt.name << " \"" << opt.comment << "\" "
<< (opt.val ? "ON" : "OFF") << ")\n";
<< (opt.val ? "ON" : "OFF") << ")\n\n";
}
}
ss << "\n";
if (!cmake.settings.empty()) {
for (const auto &set : cmake.settings) {
std::string set_val;
if (set.val.index() == 1) {
set_val = set.val.second;
} else {
set_val = set.val.first ? "ON" : "OFF";
}
ss << "set(" << set.name << " " << set_val;
;
if (set.cache) {
std::string typ;
if (set.val.index() == 1)
typ = "STRING";
else
typ = "BOOL";
ss << " CACHE " << typ << " \"" << set.comment << "\"";
if (set.force)
ss << " FORCE";
}
ss << ")\n\n";
}
}
if (!cmake.binaries.empty()) {
for (const auto &bin : cmake.binaries) {
@@ -223,8 +255,8 @@ int generate_cmake(const char *path) {
bin_type = "";
add_command = "add_library";
} else {
throw std::runtime_error(
"Unknown binary type! Supported types are exe, shared and static");
throw std::runtime_error("[cmkr] error: Unknown binary type! Supported types "
"are exe, lib, shared, static, interface");
}
if (!bin.sources.empty()) {
@@ -282,6 +314,14 @@ int generate_cmake(const char *path) {
}
ss << ")\n\n";
}
if (!bin.properties.empty()) {
ss << "set_target_properties(" << bin.name << " PROPERTIES\n";
for (const auto &prop : bin.properties) {
ss << "\t" << prop.first << " " << prop.second << "\n";
}
ss << "\t)\n\n";
}
}
}
@@ -328,7 +368,11 @@ int generate_cmake(const char *path) {
ss << conf << " ";
}
}
ss << "\n\tDESTINATION " << inst.destination << "\n\t)\n\n";
ss << "\n\tDESTINATION " << inst.destination << "\n\t";
if (!inst.targets.empty())
ss << "COMPONENT " << inst.targets[0] << "\n\t)\n\n";
else
ss << "\n\t)\n\n";
}
}
@@ -346,10 +390,13 @@ int generate_cmake(const char *path) {
if (fs::exists(fs::path(sub) / "cmake.toml"))
generate_cmake(sub.c_str());
}
} else {
throw std::runtime_error("[cmkr] error: No cmake.toml found!");
}
return 0;
}
} // namespace cmkr::gen
} // namespace gen
} // namespace cmkr
int cmkr_gen_generate_project(const char *typ) {
try {
+5 -3
View File
@@ -1,8 +1,9 @@
#include "help.h"
namespace cmkr::help {
namespace cmkr {
namespace help {
const char *version() noexcept { return "cmkr version 0.1.0"; }
const char *version() noexcept { return "cmkr version 0.1.3"; }
const char *message() noexcept {
return R"lit(
@@ -17,7 +18,8 @@ arguments:
version Current cmkr version.
)lit";
}
} // namespace cmkr::help
} // namespace help
} // namespace cmkr
const char *cmkr_help_version(void) { return cmkr::help::version(); }