build-cpp / cmkr Goto Github PK
View Code? Open in Web Editor NEWModern build system based on CMake and TOML.
Home Page: https://cmkr.build
License: MIT License
Modern build system based on CMake and TOML.
Home Page: https://cmkr.build
License: MIT License
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
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!
I imagine it should look something like this:
[subdir.asmjit]
compile_definitions = [
"ASMJIT_STATIC"
]
[find-package.GTest]
condition = "tests"
It appears PMM is unmaintained (vector-of-bool/pmm#50), so fork it and get rid of the auto-update mechanisms. This would allow it to be moved to the cmkr
repo as a separate working tree. This way you will only have to mirror the cmkr
repository into your organization's git server and nothing else.
Should perhaps be:
Unknown key 'compile-feature', did you mean 'compile-features'
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
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
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"]
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.
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"]
Currently if you do:
[project]
languages = ["Nonsense"]
There is no error. At the very least this should warn. Related: https://gitlab.kitware.com/cmake/cmake/-/issues/24340
[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
)
Measuring the code coverage of the tests would help improve the quality of the project and (hopefully) reduce the amount of bugs introduced in the future
The idea would be to have $CMKR_CACHE/_cmkr_archive_xxxxxxxx
instead of build/_cmkr_archive_xxxxxxxx
to not constantly recompile cmkr when bootstrapping.
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)
compiler-features
should error (and potentially suggest compile-features
)
[project]
name = "myproject"
[target.foo]
type = "executable"
sources = ["**.cpp"]
This can include files downloaded/generated in the build
directory and should error.
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?
Having
[settings]
MSVC_RUNTIME_LIBRARY = "MultiThreaded$<$<CONFIG:Debug>:Debug>"
Should generate:
set(MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
instead of
set(MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>)
While cmkr is a very small project it can already be noticed in single-threaded docker containers that the compilation is quite slow. Measure with clang's -ftime-trace
to see if there is any low hanging fruit to pick.
Useful tool: https://github.com/aras-p/ClangBuildAnalyzer
In fact, target.static-runtime
is still a dynamic runtime
[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
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.
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
Before calling source_group
make sure that the files are actually in a subfolder of the repository.
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.
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)
[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.
Inspiration: https://github.com/friendlyanon/cmake-init
CMKR_
variables)This corresponds to the SOURCE_SUBDIR
option of FetchContent
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
Would like to add an add-definitions option. Sometimes compile-definitions doesn't work so well.
Currently you need to do the following tasks by hand:
[project].version
in cmake.toml
CMKR_TAG
in cmkr.cmake
cmkr gen
@MoAlyousef could you give me admin access to this repository so I can manage the settings?
Supposedly it explodes.
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"]
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.
I used cmkr
to create a qt msvc static template that may be useful to some people.
Thanks cmkr
:)
QT5:
https://github.com/gmh5225/cmkr-qt5-msvc-static-template
QT6:
https://github.com/gmh5225/cmkr-qt6-msvc-static-template
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
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.
This would allow:
[target.example]
type = "executable"
sources = ["..."]
[target.example.properties]
win32.COMPILE_PDB_OUTPUT_DIRECTORY = "foo"
# 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
[target.myobjectlib]
type = "object"
sources = ["src/*.cpp"]
[target.myexecutable]
type = "executable"
link-libraries = ["myobjectlib"]
This is supported since CMake 3.12
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.