Giter VIP home page Giter VIP logo

cmkr's Introduction

cmkr

cmkr, pronounced "cmaker", is a modern build system based on CMake and TOML.

cmkr parses cmake.toml files and generates a modern, idiomatic CMakeLists.txt for you. A minimal example:

[project]
name = "cmkr_for_beginners"

[target.hello_world]
type = "executable"
sources = ["src/main.cpp"]

cmkr can bootstrap itself and you only need CMake and a C++ compiler to use it.

Getting started

To get started, run the following commands from your project directory:

curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake
cmake -P cmkr.cmake

After the bootstrapping process finishes, customize cmake.toml for your project and run CMake:

cmake -B build
cmake --build build

Once bootstrapped, cmkr does not introduce extra steps to your workflow. After modifying cmake.toml you simply build/configure your CMake project and cmkr will automatically regenerate CMakeLists.txt when necessary.

Note: The cmake.toml project file, generated CMakeLists.txt and cmkr.cmake bootstrapping script are all intended to be added to source control.

In CI environments the cmkr bootstrapping process is skipped, so there is no additional overhead in your pipelines.

Template repositories

Another way to get started is to use the cmkr_for_beginners template repository. Either open it in Gitpod, or clone the repository and run:

cmake -B build
cmake --build build

Check out the cmkr topic, the build-cpp organization or the tests for more examples and templates.

Command line

Optionally you can put a cmkr release in your PATH and use it as a utility from the command line:

Usage: cmkr [arguments]
arguments:
    init    [executable|library|shared|static|interface] Create a project.
    gen                                                  Generates CMakeLists.txt file.
    build   <extra cmake args>                           Run cmake and build.
    install                                              Run cmake --install.
    clean                                                Clean the build directory.
    help                                                 Show help.
    version                                              Current cmkr version.

Credits

cmkr's People

Contributors

anthonyprintup avatar cursey avatar darknessxk avatar gmh5225 avatar moalyousef avatar mrexodia avatar pmeerw avatar zehmatt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmkr's Issues

[feature] Add 'type = "msvc-static"'

There are times when we want to use /MT instead of /MD
The following code can do this by replacing /MD with /MT

# Enable static msvc runtime.
if (MSVC)
    set(CompilerFlags
        CMAKE_CXX_FLAGS
        CMAKE_CXX_FLAGS_DEBUG
        CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL
        CMAKE_CXX_FLAGS_RELWITHDEBINFO
        CMAKE_C_FLAGS
        CMAKE_C_FLAGS_DEBUG
        CMAKE_C_FLAGS_RELEASE
        CMAKE_C_FLAGS_MINSIZEREL
        CMAKE_C_FLAGS_RELWITHDEBINFO
        )
    foreach(CompilerFlag ${CompilerFlags})
        string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
        string(REPLACE "/MDd" "/MTd" ${CompilerFlag} "${${CompilerFlag}}")
        set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE)
        message("MSVC flags: ${CompilerFlag}:${${CompilerFlag}}")
    endforeach()
endif(MSVC)

But it's too much trouble to copy and paste every time
If possible, add an msvc-static type, it would be much easier :)

[target.hello_world]
type = "msvc-static"
sources = ["src/main.cpp"]

cmkr.cmake is not being executed by CMakeLists

CMakeLists.txt

# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/build-cpp/cmkr for more information

cmake_minimum_required(VERSION 3.15)


message("hello from cmakelists")


if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
	message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
endif()

set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
	set(CMKR_ROOT_PROJECT ON)

	# Bootstrap cmkr and automatically regenerate CMakeLists.txt
	include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
	if(CMKR_INCLUDE_RESULT)
		cmkr()
	endif()

	# Enable folder support
	set_property(GLOBAL PROPERTY USE_FOLDERS ON)

	# Create a configure-time dependency on cmake.toml to improve IDE support
	configure_file(cmake.toml cmake.toml COPYONLY)
endif()

project(deps)

cmkr.cmake
message("hello from cmkr.cmake)

"hello from cmakelists" printed but "hello from cmkr.cmake" not printed

Write missing documentation

  • Guide on migrating to cmkr
  • Add more examples (links to projects that use cmkr)
  • Incorporate feedback from users
  • Basics of TOML
  • High level explanation of cmake terms (project, target, packages) -> overview/glossary
  • Bump all example repositories to 0.2.x
  • Description of internals (CMKR_ variables)
  • Design philosophy

Add additional layer of verification in `CMKR_TAG`

Currently you have to trust that the cmkr repository does not force push the same tag with new untrusted code.

You can already (trivially) point cmkr.cmake to your own infrastructure, but it would be good to also (optionally) verify the tag.

Perhaps v0.2.1:hash. Another option is to git checkout hash but tags have the advantage that they are human-readable and (more importantly) you can do a shallow clone which speeds up configure times.

An additional feature should be that unpinned tags are immediately pinned (cmkr.cmake should modify itself). This will ensure that everyone benefits from this security.

[bug] msvc-runtime

In fact, target.static-runtime is still a dynamic runtime
image

[project]
name = "msvc-runtime"
description = "Static MSVC runtime"
msvc-runtime = "static"

# This target will compile with a static runtime 
[target.static-runtime]
type = "executable"
sources = ["src/main.cpp"]

# This target overrides the [project].msvc-runtime
[target.dynamic-runtime]
type = "executable"
sources = ["src/main.cpp"]
msvc-runtime = "dynamic"

The following is ok

[project]
name = "msvc-runtime"
description = "Static MSVC runtime"
msvc-runtime = "static"

# This target will compile with a static runtime 
[target.static-runtime]
type = "executable"
sources = ["src/main.cpp"]
msvc-runtime = "static"

# This target overrides the [project].msvc-runtime
[target.dynamic-runtime]
type = "executable"
sources = ["src/main.cpp"]
msvc-runtime = "dynamic"

But it's clear that it doesn't match the original meaning of the code

Fails to run when directory has `+` in its name

Hi! I love this tool, but I ran into an issue when someone tried to compile a program:

cmkr fails to run when the path to the directory it's in has a + in its name, with the following error:

RegularExpression::compile(): Nested *?+.
RegularExpression::compile(): Error in compile.

CMake Error at cmkr.cmake:53 (if):
  if given arguments:

    "NOT" "CMKR_CACHED_EXECUTABLE" "STREQUAL" "CMKR_EXECUTABLE" "AND" "CMKR_EXECUTABLE" "MATCHES" "^/home/apm/Documents/C++/ReverseAbductionSimulator/build/_cmkr"

  Regular expression "^/home/apm/Documents/C++/ReverseAbductionSimulator/build/_cmkr" cannot compile
Call Stack (most recent call first):
  CMakeLists.txt:12 (include)


-- Configuring incomplete, errors occurred!

Improve `cmkr.cmake` error handling

image

This could be handled better by redirecting the cmkr stdout and printing with message(FATAL_ERROR ...). Perhaps CLion also recognizes a syntax to link to the cmake.toml file?

Automate release process

Currently you need to do the following tasks by hand:

  • Change the [project].version in cmake.toml
  • Change CMKR_TAG in cmkr.cmake
  • Run cmkr gen
  • Create a new version tag
  • Generate release notes (pull requests + direct commits)

How can I pass one linker option on one platform and another for a different platform?

I'm compiling VTIL with cmkr, and VTIL has absolutely obscene stack usage (1.4 megabytes in a single frame, and that's before even executing main!) so I need to use the linker flag for increasing stack size. Anyway am preparing to get a laptop with linux on it (because windows performance is intolerable on subpar hardware) so I would like a way that's cross platform and picks the relevant linker flag based on what compiler is chosen. tysm

Replace PMM with `vcpkg.json` generation + bootstrapping

PMM is awfully complicated and does not work properly. Replace it with modern vcpkg.

[project]
name = "my_project"
version = "1.2"

[vcpkg]
version = "2021.05.12"
packages = ["fmt", "sqlite3"]

Should generate vcpkg.json (take care of the vcpkg identifiers not allowing capital letters or underscores):

{
  "name": "vcpkg_template",
  "version": "0.0.1",
  "dependencies": ["fmt", "sqlite3"]
}

And (right after the project):

include(FetchContent)

message(STATUS "Fetching vcpkg...")
FetchContent_Declare(
	vcpkg
	URL
		https://github.com/microsoft/vcpkg/archive/refs/tags/2021.05.12.tar.gz
)
FetchContent_MakeAvailable(vcpkg)

include(${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake)

See: https://github.com/build-cpp/vcpkg_template/tree/simplified-vscode. It also needs some kind of handling for subprojects (that scenario is not supported by vcpkg according to one of the authors) and it would be best if you get error messages that certain packages need to be specified in the root project for it to work.

Find a way to unify documentation

Currently the cmkr executable has it's own hardcoded documentation built-in. It would be best if there could be a single source of documentation that is somehow generated into the project to decrease the maintenance burden.

Print usage information for vcpkg

Currently you can find packages on https://vcpkg.io, but there is no usage information on the website.

The following command works:

vcpkg x-package-info --x-json --x-installed glfw3:x64-windows
{
  "results": {
    "glfw3:x64-windows": {
      "version-string": "3.3.4",
      "port-version": 0,
      "triplet": "x64-windows",
      "abi": "fe01dfbeb9b872d7b6d1927f68aded832c717f0e",
      "usage": "The package glfw3:x64-windows provides CMake targets:\n\n    find_package(glfw3 CONFIG REQUIRED)\n    target_link_libraries(main PRIVATE glfw)\n\n",
      "owns": [
        "x64-windows/",
        "x64-windows/bin/",
        "x64-windows/bin/glfw3.dll",
        "x64-windows/bin/glfw3.pdb",
        "x64-windows/debug/",
        "x64-windows/debug/bin/",
        "x64-windows/debug/bin/glfw3.dll",
        "x64-windows/debug/bin/glfw3.pdb",
        "x64-windows/debug/lib/",
        "x64-windows/debug/lib/glfw3dll.lib",
        "x64-windows/debug/lib/pkgconfig/",
        "x64-windows/debug/lib/pkgconfig/glfw3.pc",
        "x64-windows/include/",
        "x64-windows/include/GLFW/",
        "x64-windows/include/GLFW/glfw3.h",
        "x64-windows/include/GLFW/glfw3native.h",
        "x64-windows/lib/",
        "x64-windows/lib/glfw3dll.lib",
        "x64-windows/lib/pkgconfig/",
        "x64-windows/lib/pkgconfig/glfw3.pc",
        "x64-windows/share/",
        "x64-windows/share/glfw3/",
        "x64-windows/share/glfw3/copyright",
        "x64-windows/share/glfw3/glfw3Config.cmake",
        "x64-windows/share/glfw3/glfw3ConfigVersion.cmake",
        "x64-windows/share/glfw3/glfw3Targets-debug.cmake",
        "x64-windows/share/glfw3/glfw3Targets-release.cmake",
        "x64-windows/share/glfw3/glfw3Targets.cmake",
        "x64-windows/share/glfw3/vcpkg_abi_info.txt"
      ]
    }
  }
}

Reference: microsoft/vcpkg-tool#82 (comment)

Add `headers` option

Multiple people so far were confused about having to put their header files in the sources option. A simple solution would be to just add a headers key that is internally appended to the sources

Improve `source_group`

Before calling source_group make sure that the files are actually in a subfolder of the repository.

[feature] Add an 'SET' option

Now I want to use set(CMAKE_GENERATOR_TOOLSET, "llvm-msvc").
But I didn't find a way to use it in the cmkr project.
Is it possible to consider adding a SET = ["CMAKE_GENERATOR_TOOLSET"="llvm-msvc"]

Implement Windows kernel driver type

[fetch-content]
FindWDK = { git = "https://github.com/SergiusTheBest/FindWDK" }

# TODO: inject ${FindWDK_SOURCE_DIR}/cmake in the CMAKE_MODULE_PATH

[find-package]
WDK = {}

Then generate:

wdk_add_library(KmdfCppLib STATIC 
    KMDF 1.15
    WINVER 0x0602
    KmdfCppLib.h 
    KmdfCppLib.cpp
    )

Upgrade cmkr to C++17/20 ?

Hey. I've stumbled upon this repo and find the concept very interesting. I may give it a try on some of my projects

But I'm wondering, why use C++11? Some parts of the code could be made more modern using a more recent version of C++. Is there any reason to keep an old version?

Error when there are no source files added for the specified language

[project]
name = "blah"

[target.foo]
type = "executable"

This will cause an error at generation time, because foo does not have any sources so CMake cannot determine which linker to use. It's important to look for .cpp .c files, headers would not trigger a language detection in CMake either.

[options] should also be conditions

Currently you need to do extra work:

[options]
PROJECT_BUILD_TESTS = false

[conditions]
tests = "PROJECT_BUILD_TESTS"

[target.tests]
condition = "tests"
sources = ["src/tests.cpp"]

This could be:

[options]
PROJECT_BUILD_TESTS = false

[target.tests]
condition = "PROJECT_BUILD_TESTS"
sources = ["src/tests.cpp"]

Add offline mode to `cmkr.cmake`

Add an option to use cmkr.exe from the repository:

set(CMKR_PREBUILT_PATH "${CMAKE_PROJECT_SOURCE_DIR}")

This should use ${CMAKE_PROJECT_SOURCE_DIR}/cmkr.exe instead of cloning from git. If the prebuilt is not found it should built it there. To aid with version updates there should be a version check too.

Implement seamless packaging

Ideally writing

[project]
name = "example"
version = "1.0"

[find-package]
fmt = {}

[target.mylib]
type = "static"
sources = ["..."]
link-libraries = ["fmt::fmt"]

[target.otherlib]
type = "static"
sources = ["..."]

[target.mytool]
type = "static"
sources = ["..."]
link-libraries = ["mylib", "otherlib"]

[package]
targets = ["mylib", "otherlib", "mytool"]
dependency-packages = ["fmt"]

Should automatically generate a modern CMake example (project.name) package with a exampleConfig.cmake file that has IMPORTED targets, versioning and the relevant find_package calls. This library can then be consumed with:

[find-package]
example = { version = "1.0" }

Perhaps this could be used? https://github.com/TheLartians/PackageProject.cmake

Support object libraries

[target.myobjectlib]
type = "object"
sources = ["src/*.cpp"]

[target.myexecutable]
type = "executable"
link-libraries = ["myobjectlib"]

This is supported since CMake 3.12

Add support for grepping based on a variable

Currently ${xxx_SOURCE_DIR}/blah/*.cpp doesn't work because the file doesn't exist in the cmkr universe. Most likely this would have to be expanded to a GLOB expression (which is not ideal)

Implement `cmkr vendor`

The idea would be to automate https://github.com/MoAlyousef/cmkr/tree/7fdafa41894e5509d03756e3017978ac393e5e13/third_party by declaring it in your cmake.toml:

[project]
name = "vendoring_example"

[vendor]
filesystem = { folder = "third_party/filesystem", url = "https://github.com/gulrak/filesystem/archive/refs/tags/v1.5.4.zip" }
ordered-map = { folder = "third_party/filesystem", url = "https://github.com/Tessil/ordered-map/archive/refs/tags/v1.0.0.tar.gz" }
...

Then you can run cmkr vendor (likely a wrapper around a cmake script) to download all the files

Support subprojects

Currently a [project] causes automatic regeneration to stop (for consistency reasons, you don't want to regenerate another cmkr project's files). Can be solved like this:

[project]
name = "root"

[subdir.project1]
[project]
name = "project1"
subproject = true
parent = "root"

Either the subproject or the parent project could make it so root would work. The downside of using subproject is that accidentally setting it in a root project would falsely cause regeneration across different repositories.

Flatten the build directory

I want to copy a dll generated by a subdirectory into the path of my main binary. Is this possible with cmkr? If not pls implement

Improve the error message for `[fetch-content]` subkeys

# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[project]
name = "ConsoleApplication1"

# TODO: define a target for each of your executables/libraries like this:
#[target.myexecutable]
#type = "executable" # static, shared
#sources = ["src/ConsoleApplication1/*.cpp", "include/ConsoleApplication1/*.hpp"]
#include-directories = ["include"]
#compile-features = ["cxx_std_11"]
#link-libraries = ["target-or-library"]

[fetch-content]
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" }


compile-features = ["cxx_std_20"]
[target.example]
type = "executable"
sources = ["src/Source.cpp"]
link-libraries = ["fmt::fmt"]

The error is:

[error] toml::value::contains(key): bad_cast to table
 --> D:\CodeBlocks\cmkr-atul\cmake.toml
    |
 17 | compile-features = ["cxx_std_20"]
    |                    ~~~~~~~~~~~~~~ the actual type is array

Support conditional properties

This would allow:

[target.example]
type = "executable"
sources = ["..."]

[target.example.properties]
win32.COMPILE_PDB_OUTPUT_DIRECTORY = "foo"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.