mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d607b9028c | |||
| 099b14552c | |||
| 771c80a41a | |||
| 58c7de1d60 | |||
| a61e4bb999 | |||
| 47aaeaf8ce | |||
| 62609a0088 | |||
| e0d8a085db | |||
| 56da4144ae | |||
| 9388b3f29d | |||
| 079644cfeb | |||
| a7ca9f04c0 | |||
| 339c2aac94 | |||
| c573c9a76d | |||
| b24a0a2fdc | |||
| 854e8817c4 | |||
| 1c2947b2fc | |||
| 19e61aa1aa | |||
| bfa1e1fe0d | |||
| 56bd78f7ad | |||
| 4362b3547f | |||
| 08204d9847 | |||
| 2202aa8173 | |||
| d3829fb6cd | |||
| 3fb095210a | |||
| 9f99365a25 | |||
| be387141b5 | |||
| 09ded38f70 | |||
| ad90b1ad3e | |||
| 5bfa03d311 | |||
| bdd9d393d6 | |||
| 1deaec2b41 | |||
| cfee3bbc14 | |||
| bcaa60cabe | |||
| 7b1d33395e | |||
| 240fafc102 | |||
| 7a7ddf2699 | |||
| 605a04e72d | |||
| fd7f078127 | |||
| ee0e0d71d9 | |||
| 9d6897b572 | |||
| f8c34e5545 | |||
| e6d783ea20 | |||
| ee7fe38a7b | |||
| 66b2aad843 |
+2
-2
@@ -19,7 +19,7 @@ AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
@@ -72,7 +72,7 @@ PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
[*.{c,h,cpp,hpp,toml}]
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
|
||||
[{CMakeLists.txt, *.cmake}]
|
||||
indent_style = tab
|
||||
tab_width = 8
|
||||
insert_final_newline = true
|
||||
|
||||
# Exclude the third_party folder
|
||||
[/third_party/**]
|
||||
charset = unset
|
||||
end_of_line = unset
|
||||
insert_final_newline = unset
|
||||
trim_trailing_whitespace = unset
|
||||
indent_style = unset
|
||||
indent_size = unset
|
||||
@@ -1,22 +1,29 @@
|
||||
name: CMake
|
||||
name: build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
cmake:
|
||||
# Skip building pull requests from the same repository
|
||||
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-2019, macos-10.15, ubuntu-20.04]
|
||||
os: [windows-2022, macos-11, ubuntu-20.04]
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
BUILD_TYPE: 'Release'
|
||||
CMAKE_GENERATOR: 'Ninja'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@6263846cf3c17009dfc81604efabae16044fc074 # master
|
||||
|
||||
- name: Visual Studio Development Environment
|
||||
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
|
||||
|
||||
- name: Tag cmkr.cmake
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
run: cmake -P "cmake/replace_tag.cmake"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
name: lint
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: clang-format
|
||||
id: clang-format
|
||||
uses: DoozyX/clang-format-lint-action@c3b2c943e924028b93a707a5b1b017976ab8d50c # v0.15
|
||||
with:
|
||||
exclude: './third_party'
|
||||
extensions: 'c,h,cpp,hpp'
|
||||
clangFormatVersion: 15
|
||||
style: file
|
||||
|
||||
- name: clang-format instructions
|
||||
if: ${{ failure() && steps.clang-format.outcome == 'failure' }}
|
||||
run: |
|
||||
# Instructions for fixing the formatting errors
|
||||
echo -e "\n\033[0;31mTo fix the formatting, run:\nclang-format -style=file -i \$(git ls-files \"*.c\" \"*.h\" \"*.cpp\" \"*.hpp\")\033[0m\n"
|
||||
exit 1
|
||||
|
||||
editorconfig:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run editorconfig-checker
|
||||
uses: editorconfig-checker/action-editorconfig-checker@d4fca16fc71adef10fbe101903b654449fa9570c # master 2022-03-15
|
||||
+2
-1
@@ -9,4 +9,5 @@ build*/
|
||||
.idea/
|
||||
cmake-build*/
|
||||
CMakeLists.txt.user
|
||||
.vscode/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
Generated
+1
-3
@@ -22,7 +22,7 @@ project(cmkr
|
||||
LANGUAGES
|
||||
CXX
|
||||
VERSION
|
||||
0.2.22
|
||||
0.2.26
|
||||
DESCRIPTION
|
||||
"CMakeLists generator from TOML"
|
||||
)
|
||||
@@ -61,14 +61,12 @@ set(cmkr_SOURCES
|
||||
"src/arguments.cpp"
|
||||
"src/build.cpp"
|
||||
"src/cmake_generator.cpp"
|
||||
"src/error.cpp"
|
||||
"src/help.cpp"
|
||||
"src/main.cpp"
|
||||
"src/project_parser.cpp"
|
||||
"include/arguments.hpp"
|
||||
"include/build.hpp"
|
||||
"include/cmake_generator.hpp"
|
||||
"include/error.hpp"
|
||||
"include/fs.hpp"
|
||||
"include/help.hpp"
|
||||
"include/literals.hpp"
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ cmkr-include = false
|
||||
|
||||
[project]
|
||||
name = "cmkr"
|
||||
version = "0.2.22"
|
||||
version = "0.2.26"
|
||||
description = "CMakeLists generator from TOML"
|
||||
languages = ["CXX"]
|
||||
include-after = [
|
||||
|
||||
+77
-77
@@ -1,78 +1,78 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
if(NOT CMAKE_SCRIPT_MODE_FILE)
|
||||
message(FATAL_ERROR "Usage: cmake -P bump_version.cmake [1.2.3]")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
|
||||
message(FATAL_ERROR "Cannot find cmake.toml")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake")
|
||||
message(FATAL_ERROR "Cannot find cmkr.cmake")
|
||||
endif()
|
||||
|
||||
# Validate branch
|
||||
find_package(Git REQUIRED)
|
||||
execute_process(COMMAND "${GIT_EXECUTABLE}" branch --show-current OUTPUT_VARIABLE GIT_BRANCH)
|
||||
string(STRIP "${GIT_BRANCH}" GIT_BRANCH)
|
||||
if(NOT GIT_BRANCH STREQUAL "main")
|
||||
message(FATAL_ERROR "You need to be on the main branch, you are on: ${GIT_BRANCH}")
|
||||
endif()
|
||||
|
||||
file(READ "${CMAKE_SOURCE_DIR}/cmake.toml" CMAKE_TOML)
|
||||
string(FIND "${CMAKE_TOML}" "[project]" PROJECT_INDEX)
|
||||
string(SUBSTRING "${CMAKE_TOML}" ${PROJECT_INDEX} -1 CMAKE_TOML_PROJECT)
|
||||
set(SEMVER_REGEX "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
||||
set(VERSION_REGEX "version = \"${SEMVER_REGEX}\"")
|
||||
if(CMAKE_TOML_PROJECT MATCHES "${VERSION_REGEX}")
|
||||
set(MAJOR "${CMAKE_MATCH_1}")
|
||||
set(MINOR "${CMAKE_MATCH_2}")
|
||||
set(PATCH "${CMAKE_MATCH_3}")
|
||||
set(OLDVERSION "${MAJOR}.${MINOR}.${PATCH}")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to match semantic version in cmake.toml")
|
||||
endif()
|
||||
|
||||
if(CMAKE_ARGV3)
|
||||
if(NOT CMAKE_ARGV3 MATCHES "${SEMVER_REGEX}")
|
||||
message(FATAL_ERROR "Invalid semantic version number '${CMAKE_ARGV3}'")
|
||||
endif()
|
||||
set(NEWVERSION "${CMAKE_ARGV3}")
|
||||
else()
|
||||
math(EXPR NEWPATCH "${PATCH} + 1")
|
||||
set(NEWVERSION "${MAJOR}.${MINOR}.${NEWPATCH}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Version ${OLDVERSION} -> ${NEWVERSION}")
|
||||
|
||||
find_program(CMKR_EXECUTABLE "cmkr" PATHS "${CMAKE_SOURCE_DIR}/build" PATH_SUFFIXES Debug Release RelWithDebInfo MinSizeRel NO_CACHE REQUIRED)
|
||||
message(STATUS "Found cmkr: ${CMKR_EXECUTABLE}")
|
||||
|
||||
# Replace version in cmake.toml
|
||||
string(REPLACE "version = \"${OLDVERSION}\"" "version = \"${NEWVERSION}\"" CMAKE_TOML "${CMAKE_TOML}")
|
||||
file(CONFIGURE
|
||||
OUTPUT "${CMAKE_SOURCE_DIR}/cmake.toml"
|
||||
CONTENT "${CMAKE_TOML}"
|
||||
@ONLY
|
||||
NEWLINE_STYLE LF
|
||||
)
|
||||
|
||||
# Run cmkr gen
|
||||
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen RESULT_VARIABLE CMKR_EXEC_RESULT)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "cmkr gen failed (exit code ${CMKR_EXEC_RESULT})")
|
||||
endif()
|
||||
|
||||
# Replace version in cmkr.cmake
|
||||
file(READ "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake" CMKR_CMAKE)
|
||||
string(REGEX REPLACE "CMKR_TAG \"[^\"]+\"" "CMKR_TAG \"v${NEWVERSION}\"" CMKR_CMAKE "${CMKR_CMAKE}")
|
||||
file(CONFIGURE
|
||||
OUTPUT "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake"
|
||||
CONTENT "${CMKR_CMAKE}"
|
||||
@ONLY
|
||||
NEWLINE_STYLE LF
|
||||
)
|
||||
|
||||
# Print git commands
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
if(NOT CMAKE_SCRIPT_MODE_FILE)
|
||||
message(FATAL_ERROR "Usage: cmake -P bump_version.cmake [1.2.3]")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
|
||||
message(FATAL_ERROR "Cannot find cmake.toml")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake")
|
||||
message(FATAL_ERROR "Cannot find cmkr.cmake")
|
||||
endif()
|
||||
|
||||
# Validate branch
|
||||
find_package(Git REQUIRED)
|
||||
execute_process(COMMAND "${GIT_EXECUTABLE}" branch --show-current OUTPUT_VARIABLE GIT_BRANCH)
|
||||
string(STRIP "${GIT_BRANCH}" GIT_BRANCH)
|
||||
if(NOT GIT_BRANCH STREQUAL "main")
|
||||
message(FATAL_ERROR "You need to be on the main branch, you are on: ${GIT_BRANCH}")
|
||||
endif()
|
||||
|
||||
file(READ "${CMAKE_SOURCE_DIR}/cmake.toml" CMAKE_TOML)
|
||||
string(FIND "${CMAKE_TOML}" "[project]" PROJECT_INDEX)
|
||||
string(SUBSTRING "${CMAKE_TOML}" ${PROJECT_INDEX} -1 CMAKE_TOML_PROJECT)
|
||||
set(SEMVER_REGEX "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
||||
set(VERSION_REGEX "version = \"${SEMVER_REGEX}\"")
|
||||
if(CMAKE_TOML_PROJECT MATCHES "${VERSION_REGEX}")
|
||||
set(MAJOR "${CMAKE_MATCH_1}")
|
||||
set(MINOR "${CMAKE_MATCH_2}")
|
||||
set(PATCH "${CMAKE_MATCH_3}")
|
||||
set(OLDVERSION "${MAJOR}.${MINOR}.${PATCH}")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to match semantic version in cmake.toml")
|
||||
endif()
|
||||
|
||||
if(CMAKE_ARGV3)
|
||||
if(NOT CMAKE_ARGV3 MATCHES "${SEMVER_REGEX}")
|
||||
message(FATAL_ERROR "Invalid semantic version number '${CMAKE_ARGV3}'")
|
||||
endif()
|
||||
set(NEWVERSION "${CMAKE_ARGV3}")
|
||||
else()
|
||||
math(EXPR NEWPATCH "${PATCH} + 1")
|
||||
set(NEWVERSION "${MAJOR}.${MINOR}.${NEWPATCH}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Version ${OLDVERSION} -> ${NEWVERSION}")
|
||||
|
||||
find_program(CMKR_EXECUTABLE "cmkr" PATHS "${CMAKE_SOURCE_DIR}/build" PATH_SUFFIXES Debug Release RelWithDebInfo MinSizeRel NO_CACHE REQUIRED)
|
||||
message(STATUS "Found cmkr: ${CMKR_EXECUTABLE}")
|
||||
|
||||
# Replace version in cmake.toml
|
||||
string(REPLACE "version = \"${OLDVERSION}\"" "version = \"${NEWVERSION}\"" CMAKE_TOML "${CMAKE_TOML}")
|
||||
file(CONFIGURE
|
||||
OUTPUT "${CMAKE_SOURCE_DIR}/cmake.toml"
|
||||
CONTENT "${CMAKE_TOML}"
|
||||
@ONLY
|
||||
NEWLINE_STYLE LF
|
||||
)
|
||||
|
||||
# Run cmkr gen
|
||||
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen RESULT_VARIABLE CMKR_EXEC_RESULT)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "cmkr gen failed (exit code ${CMKR_EXEC_RESULT})")
|
||||
endif()
|
||||
|
||||
# Replace version in cmkr.cmake
|
||||
file(READ "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake" CMKR_CMAKE)
|
||||
string(REGEX REPLACE "CMKR_TAG \"[^\"]+\"" "CMKR_TAG \"v${NEWVERSION}\"" CMKR_CMAKE "${CMKR_CMAKE}")
|
||||
file(CONFIGURE
|
||||
OUTPUT "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake"
|
||||
CONTENT "${CMKR_CMAKE}"
|
||||
@ONLY
|
||||
NEWLINE_STYLE LF
|
||||
)
|
||||
|
||||
# Print git commands
|
||||
message(STATUS "Git commands to create new version:\ngit commit -a -m \"Bump to ${NEWVERSION}\"\ngit tag v${NEWVERSION}\ngit push origin main v${NEWVERSION}")
|
||||
+1
-1
@@ -2,7 +2,7 @@ include_guard()
|
||||
|
||||
# Change these defaults to point to your infrastructure if desired
|
||||
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
|
||||
set(CMKR_TAG "v0.2.22" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_TAG "v0.2.26" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
|
||||
|
||||
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
|
||||
|
||||
@@ -15,7 +15,7 @@ function(generate_documentation)
|
||||
message(FATAL_ERROR "This should not happen (wrong regex?)")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
||||
# Delete previously generated examples
|
||||
set(example_folder "${PROJECT_SOURCE_DIR}/docs/examples")
|
||||
file(GLOB example_files "${example_folder}/*.md")
|
||||
@@ -41,21 +41,21 @@ function(generate_documentation)
|
||||
# Read cmake.toml file
|
||||
file(READ "${test_toml}" test_contents NO_HEX_CONVERSION)
|
||||
string(LENGTH "${test_contents}" toml_length)
|
||||
|
||||
|
||||
# Extract header text
|
||||
string(REGEX MATCH "^(\n*(#[^\n]+\n)+\n*)" EXAMPLE_HEADER "${test_contents}")
|
||||
string(LENGTH "${EXAMPLE_HEADER}" header_length)
|
||||
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
|
||||
string(REGEX REPLACE "\n# ?" "\n\n" EXAMPLE_HEADER "\n${EXAMPLE_HEADER}")
|
||||
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
|
||||
|
||||
|
||||
# Extract footer text
|
||||
string(REGEX MATCH "(((#[^\n]+)(\n+|$))+)$" EXAMPLE_FOOTER "${test_contents}")
|
||||
string(LENGTH "${EXAMPLE_FOOTER}" footer_length)
|
||||
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
|
||||
string(REGEX REPLACE "\n# ?" "\n\n" EXAMPLE_FOOTER "\n${EXAMPLE_FOOTER}")
|
||||
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
|
||||
|
||||
|
||||
# Extract toml body
|
||||
math(EXPR toml_length "${toml_length}-${header_length}-${footer_length}")
|
||||
string(SUBSTRING "${test_contents}" ${header_length} ${toml_length} EXAMPLE_TOML)
|
||||
@@ -64,7 +64,7 @@ function(generate_documentation)
|
||||
# Extract title from description
|
||||
if("${EXAMPLE_TOML}" MATCHES "description *= *\"([^\"]+)\"")
|
||||
set(EXAMPLE_TITLE "${CMAKE_MATCH_1}")
|
||||
|
||||
|
||||
# Generate documentation markdown page
|
||||
configure_file("${PROJECT_SOURCE_DIR}/cmake/example.md.in" "${example_folder}/${EXAMPLE_PERMALINK}.md" @ONLY NEWLINE_STYLE LF)
|
||||
else()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace cmkr {
|
||||
namespace resources {
|
||||
|
||||
static const char* @RESOURCE_NAME@ = R"RESOURCE(@RESOURCE_CONTENTS@)RESOURCE";
|
||||
|
||||
}
|
||||
namespace cmkr {
|
||||
namespace resources {
|
||||
|
||||
static const char* @RESOURCE_NAME@ = R"RESOURCE(@RESOURCE_CONTENTS@)RESOURCE";
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
cmkr.build
|
||||
cmkr.build
|
||||
|
||||
+34
-2
@@ -39,6 +39,32 @@ include-before = ["cmake/before-project.cmake"]
|
||||
include-after = ["cmake/after-project.cmake"]
|
||||
```
|
||||
|
||||
### Languages
|
||||
|
||||
Supported languages are (see [`enable_language`](https://cmake.org/cmake/help/latest/command/enable_language.html) for more information):
|
||||
|
||||
- `C`
|
||||
- `CXX` → C++
|
||||
- `CSharp` → C#
|
||||
- `CUDA`
|
||||
- `OBJC` → Objective-C
|
||||
- `OBJCXX` → Objective-C++
|
||||
- `Fortran`
|
||||
- `HIP`
|
||||
- `ISPC`
|
||||
- `Swift`
|
||||
- `ASM`
|
||||
- `ASM_MASM` → [Microsoft Macro Assembler (MASM)](https://learn.microsoft.com/en-US/cpp/assembler/masm/masm-for-x64-ml64-exe)
|
||||
- `ASM_NASM` → [Netwide Assembler (NASM)](https://www.nasm.us)
|
||||
- `ASM_MARMASM` [Microsoft ARM Assembler](https://learn.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-command-line-reference)
|
||||
- `ASM-ATT`
|
||||
- `Java` (undocumented)
|
||||
- `RC` (undocumented)
|
||||
|
||||
After a language is enabled, adding sources files with the corresponding extension to your target will automatically use the appropriate compiler/assembler for it.
|
||||
|
||||
_Note_: It is generally discouraged to disable the `C` language, unless you are absolutely sure it is not used. Sometimes projects added with `fetch-content` implicitly require it and the error messages can be extremely confusing.
|
||||
|
||||
## Conditions
|
||||
|
||||
You can specify your own conditions and use them in any `condition` field:
|
||||
@@ -49,7 +75,7 @@ arch64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
|
||||
arch32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"
|
||||
```
|
||||
|
||||
This will make the `arch64` and `arch32` conditions available with their respective CMake expressions.
|
||||
This will make the `arch64` and `arch32` conditions available with their respective CMake expressions.
|
||||
|
||||
You can also prefix most keys with `condition.` to represent a conditional:
|
||||
|
||||
@@ -72,8 +98,10 @@ unix = "UNIX"
|
||||
bsd = "CMAKE_SYSTEM_NAME MATCHES \"BSD\""
|
||||
linux = "CMAKE_SYSTEM_NAME MATCHES \"Linux\""
|
||||
gcc = "CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_C_COMPILER_ID STREQUAL \"GNU\""
|
||||
clang = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
|
||||
msvc = "MSVC"
|
||||
clang = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
|
||||
clang-cl = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
|
||||
clang-any = "CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_C_COMPILER_ID MATCHES \"Clang\""
|
||||
root = "CMKR_ROOT_PROJECT"
|
||||
x64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
|
||||
x32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"
|
||||
@@ -151,6 +179,8 @@ condition = "mycondition"
|
||||
git = "https://github.com/myuser/gitcontent"
|
||||
tag = "v0.1"
|
||||
shallow = false
|
||||
system = false
|
||||
subdir = ""
|
||||
|
||||
[fetch-content.svncontent]
|
||||
condition = "mycondition"
|
||||
@@ -166,6 +196,8 @@ hash = "SHA1 502a4e25b8b209889c99c7fa0732102682c2e4ff"
|
||||
sha1 = "502a4e25b8b209889c99c7fa0732102682c2e4ff"
|
||||
```
|
||||
|
||||
Table keys that match CMake variable names (`[A-Z_]+`) will be passed to the [`FetchContent_Declare`](https://cmake.org/cmake/help/latest/module/FetchContent.html#command:fetchcontent_declare) command.
|
||||
|
||||
## Targets
|
||||
|
||||
```toml
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
# Automatically generated from tests/compile-options/cmake.toml - DO NOT EDIT
|
||||
layout: default
|
||||
title: Compiler flags
|
||||
permalink: /examples/compile-options
|
||||
parent: Examples
|
||||
nav_order: 9
|
||||
---
|
||||
|
||||
# Compiler flags
|
||||
|
||||
Example project that sets compiler/linker flags for various platforms.
|
||||
|
||||
```toml
|
||||
[project]
|
||||
name = "compile-options"
|
||||
description = "Compiler flags"
|
||||
|
||||
[target.hello]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
msvc.compile-options = ["/W2"]
|
||||
gcc.compile-options = ["-Wall"]
|
||||
clang.compile-options = ["-Wall"]
|
||||
```
|
||||
|
||||
The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags depending on the platform. See the [targets](/cmake-toml/#targets) documentation for other things you can set.
|
||||
|
||||
_Note_: In general you only want to specify flags _required_ to compile your code without errors.
|
||||
|
||||
<sup><sub>This page was automatically generated from [tests/compile-options/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/compile-options/cmake.toml).</sub></sup>
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
layout: null
|
||||
permalink: /getting-started/
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=https://cmkr.build">
|
||||
</head>
|
||||
---
|
||||
layout: null
|
||||
permalink: /getting-started/
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=https://cmkr.build">
|
||||
</head>
|
||||
</html>
|
||||
@@ -11,9 +11,3 @@ int install();
|
||||
|
||||
} // namespace build
|
||||
} // namespace cmkr
|
||||
|
||||
int cmkr_build_run(int argc, char **argv);
|
||||
|
||||
int cmkr_build_clean();
|
||||
|
||||
int cmkr_build_install();
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace cmkr {
|
||||
namespace error {
|
||||
|
||||
struct Status {
|
||||
enum class Code {
|
||||
Success = 0,
|
||||
RuntimeError,
|
||||
InitError,
|
||||
GenerationError,
|
||||
BuildError,
|
||||
CleanError,
|
||||
InstallError,
|
||||
};
|
||||
Status(Code ec) noexcept;
|
||||
operator int() const noexcept;
|
||||
Code code() const noexcept;
|
||||
|
||||
private:
|
||||
Code ec_ = Code::Success;
|
||||
};
|
||||
|
||||
} // namespace error
|
||||
} // namespace cmkr
|
||||
|
||||
const char *cmkr_error_status_string(int);
|
||||
+2
-4
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || \
|
||||
(defined(__cplusplus) && __cplusplus >= 201703L)) && \
|
||||
defined(__has_include)
|
||||
#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>
|
||||
@@ -12,4 +10,4 @@ namespace fs = std::filesystem;
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,3 @@ const char *message() noexcept;
|
||||
|
||||
} // namespace help
|
||||
} // namespace cmkr
|
||||
|
||||
const char *cmkr_help_version(void);
|
||||
|
||||
const char *cmkr_help_message(void);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <mpark/variant.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <mpark/variant.hpp>
|
||||
#include <tsl/ordered_map.h>
|
||||
#include <tsl/ordered_set.h>
|
||||
#include <vector>
|
||||
|
||||
namespace cmkr {
|
||||
namespace parser {
|
||||
@@ -47,6 +48,10 @@ struct Vcpkg {
|
||||
};
|
||||
|
||||
std::vector<Package> packages;
|
||||
|
||||
bool enabled() const {
|
||||
return !packages.empty();
|
||||
}
|
||||
};
|
||||
|
||||
enum TargetType {
|
||||
@@ -150,6 +155,8 @@ struct Content {
|
||||
Condition<std::string> cmake_after;
|
||||
ConditionVector include_before;
|
||||
ConditionVector include_after;
|
||||
bool system;
|
||||
std::string subdir;
|
||||
};
|
||||
|
||||
enum MsvcRuntimeType {
|
||||
@@ -206,4 +213,4 @@ struct Project {
|
||||
bool is_root_path(const std::string &path);
|
||||
|
||||
} // namespace parser
|
||||
} // namespace cmkr
|
||||
} // namespace cmkr
|
||||
|
||||
+1
-3
@@ -2,10 +2,8 @@
|
||||
#include "build.hpp"
|
||||
#include "cmake_generator.hpp"
|
||||
#include "help.hpp"
|
||||
|
||||
#include "fs.hpp"
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
+4
-38
@@ -1,14 +1,10 @@
|
||||
#include "build.hpp"
|
||||
#include "cmake_generator.hpp"
|
||||
#include "error.hpp"
|
||||
#include "project_parser.hpp"
|
||||
|
||||
#include "fs.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
namespace cmkr {
|
||||
namespace build {
|
||||
@@ -17,7 +13,7 @@ int run(int argc, char **argv) {
|
||||
parser::Project project(nullptr, ".", true);
|
||||
if (argc > 2) {
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
project.build_args.push_back(argv[i]);
|
||||
project.build_args.emplace_back(argv[i]);
|
||||
}
|
||||
}
|
||||
std::stringstream ss;
|
||||
@@ -48,13 +44,13 @@ int run(int argc, char **argv) {
|
||||
}
|
||||
|
||||
int clean() {
|
||||
bool ret = false;
|
||||
bool success = false;
|
||||
parser::Project project(nullptr, ".", true);
|
||||
if (fs::exists(project.build_dir)) {
|
||||
ret = fs::remove_all(project.build_dir);
|
||||
success = fs::remove_all(project.build_dir);
|
||||
fs::create_directory(project.build_dir);
|
||||
}
|
||||
return !ret;
|
||||
return success ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int install() {
|
||||
@@ -64,33 +60,3 @@ int install() {
|
||||
}
|
||||
} // namespace build
|
||||
} // namespace cmkr
|
||||
|
||||
int cmkr_build_run(int argc, char **argv) {
|
||||
try {
|
||||
return cmkr::build::run(argc, argv);
|
||||
} catch (const std::system_error &e) {
|
||||
return e.code().value();
|
||||
} catch (...) {
|
||||
return cmkr::error::Status(cmkr::error::Status::Code::BuildError);
|
||||
}
|
||||
}
|
||||
|
||||
int cmkr_build_clean(void) {
|
||||
try {
|
||||
return cmkr::build::clean();
|
||||
} catch (const std::system_error &e) {
|
||||
return e.code().value();
|
||||
} catch (...) {
|
||||
return cmkr::error::Status(cmkr::error::Status::Code::CleanError);
|
||||
}
|
||||
}
|
||||
|
||||
int cmkr_build_install(void) {
|
||||
try {
|
||||
return cmkr::build::install();
|
||||
} catch (const std::system_error &e) {
|
||||
return e.code().value();
|
||||
} catch (...) {
|
||||
return cmkr::error::Status(cmkr::error::Status::Code::InstallError);
|
||||
}
|
||||
}
|
||||
|
||||
+94
-52
@@ -1,15 +1,14 @@
|
||||
#include "cmake_generator.hpp"
|
||||
#include "error.hpp"
|
||||
#include "literals.hpp"
|
||||
#include <resources/cmkr.hpp>
|
||||
|
||||
#include "fs.hpp"
|
||||
#include "project_parser.hpp"
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
namespace cmkr {
|
||||
namespace gen {
|
||||
@@ -43,7 +42,7 @@ static tsl::ordered_map<std::string, std::vector<std::string>> known_languages =
|
||||
{"Swift", {".swift"}},
|
||||
};
|
||||
|
||||
static std::string format(const char *format, tsl::ordered_map<std::string, std::string> variables) {
|
||||
static std::string format(const char *format, const tsl::ordered_map<std::string, std::string> &variables) {
|
||||
std::string s = format;
|
||||
for (const auto &itr : variables) {
|
||||
size_t start_pos = 0;
|
||||
@@ -216,7 +215,7 @@ void generate_project(const std::string &type) {
|
||||
generate_gitfile(".gitattributes", {"/**/CMakeLists.txt linguist-generated", "/**/cmkr.cmake linguist-vendored"});
|
||||
|
||||
// Generate .gitignore with reasonable defaults for CMake
|
||||
generate_gitfile(".gitignore", {"build*/", "cmake-build*/", ".idea/", ".vscode/"});
|
||||
generate_gitfile(".gitignore", {"build*/", "cmake-build*/", "CMakerLists.txt", "CMakeLists.txt.user"});
|
||||
|
||||
tsl::ordered_map<std::string, std::string> variables = {
|
||||
{"@name", name},
|
||||
@@ -249,7 +248,7 @@ void generate_project(const std::string &type) {
|
||||
|
||||
struct CommandEndl {
|
||||
std::stringstream &ss;
|
||||
CommandEndl(std::stringstream &ss) : ss(ss) {
|
||||
explicit CommandEndl(std::stringstream &ss) : ss(ss) {
|
||||
}
|
||||
void endl() {
|
||||
ss << '\n';
|
||||
@@ -258,7 +257,7 @@ struct CommandEndl {
|
||||
|
||||
struct RawArg {
|
||||
RawArg() = default;
|
||||
RawArg(std::string arg) : arg(std::move(arg)) {
|
||||
explicit RawArg(std::string arg) : arg(std::move(arg)) {
|
||||
}
|
||||
|
||||
std::string arg;
|
||||
@@ -293,7 +292,7 @@ struct Command {
|
||||
// https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#unquoted-argument
|
||||
// NOTE: Normally '/' does not require quoting according to the documentation but this has been the case here
|
||||
// previously, so for backwards compatibility its still here.
|
||||
if (str.find_first_of("()#\"\\'> |/;") == str.npos)
|
||||
if (str.find_first_of("()#\"\\'> |/;") == std::string::npos)
|
||||
return str;
|
||||
std::string result;
|
||||
result += "\"";
|
||||
@@ -442,14 +441,15 @@ static std::string tolf(const std::string &str) {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
struct Generator {
|
||||
Generator(const parser::Project &project) : project(project) {
|
||||
Generator(const parser::Project &project, fs::path path) : project(project), path(std::move(path)) {
|
||||
}
|
||||
Generator(const Generator &) = delete;
|
||||
|
||||
const parser::Project &project;
|
||||
fs::path path;
|
||||
std::stringstream ss;
|
||||
int indent = 0;
|
||||
|
||||
@@ -479,8 +479,8 @@ struct Generator {
|
||||
void inject_includes(const std::vector<std::string> &includes) {
|
||||
if (!includes.empty()) {
|
||||
for (const auto &file : includes) {
|
||||
if (!fs::is_regular_file(file)) {
|
||||
throw std::runtime_error("Include '" + file + "' does not exist");
|
||||
if (!fs::exists(path / file)) {
|
||||
throw std::runtime_error("Include not found: " + file);
|
||||
}
|
||||
cmd("include")(file);
|
||||
}
|
||||
@@ -493,7 +493,7 @@ struct Generator {
|
||||
throw std::runtime_error("Detected additional \" at the end of cmake block");
|
||||
}
|
||||
auto cmake_lf = tolf(cmake);
|
||||
while (cmake_lf.back() == '\n')
|
||||
while (!cmake_lf.empty() && cmake_lf.back() == '\n')
|
||||
cmake_lf.pop_back();
|
||||
bool did_indent = false;
|
||||
for (char ch : cmake_lf) {
|
||||
@@ -562,28 +562,26 @@ struct ConditionScope {
|
||||
};
|
||||
|
||||
static bool vcpkg_valid_identifier(const std::string &name) {
|
||||
// prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default
|
||||
auto is_reserved = [](const std::string &s) {
|
||||
if (s == "prn" || s == "aux" || s == "nul" || s == "con" || s == "core" || s == "default") {
|
||||
return true;
|
||||
}
|
||||
if (s.length() == 4 && (s.compare(0, 3, "lpt") == 0 || s.compare(0, 3, "com") == 0) && (s[3] >= '1' && s[3] <= '9')) {
|
||||
return true;
|
||||
// [a-z0-9]+(-[a-z0-9]+)*
|
||||
for (size_t i = 0; i < name.length(); i++) {
|
||||
auto c = name[i];
|
||||
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (i > 0 && c == '-')) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// [a-z0-9]+(-[a-z0-9]+)*
|
||||
auto is_identifier = [](const std::string &s) {
|
||||
for (size_t i = 0; i < s.length(); i++) {
|
||||
auto c = s[i];
|
||||
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (i > 0 && c == '-')) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vcpkg_identifier_reserved(const std::string &name) {
|
||||
// prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default
|
||||
if (name == "prn" || name == "aux" || name == "nul" || name == "con" || name == "core" || name == "default") {
|
||||
return true;
|
||||
};
|
||||
return is_identifier(name) && !is_reserved(name);
|
||||
}
|
||||
if (name.length() == 4 && (name.compare(0, 3, "lpt") == 0 || name.compare(0, 3, "com") == 0) && (name[3] >= '1' && name[3] <= '9')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string vcpkg_escape_identifier(const std::string &name) {
|
||||
@@ -600,10 +598,12 @@ static std::string vcpkg_escape_identifier(const std::string &name) {
|
||||
|
||||
escaped += std::tolower(ch);
|
||||
}
|
||||
|
||||
if (!vcpkg_valid_identifier(escaped)) {
|
||||
throw std::runtime_error("The escaped project name '" + escaped + "' is not usable with [vcpkg]");
|
||||
}
|
||||
if (vcpkg_identifier_reserved(escaped)) {
|
||||
throw std::runtime_error("The escaped project name '" + escaped + "' is a reserved name [vcpkg]");
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
@@ -627,7 +627,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
}
|
||||
|
||||
Generator gen(project);
|
||||
Generator gen(project, path);
|
||||
|
||||
// Helper lambdas for more convenient CMake generation
|
||||
auto &ss = gen.ss;
|
||||
@@ -785,7 +785,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
gen.conditional_includes(project.include_after);
|
||||
gen.conditional_cmake(project.cmake_after);
|
||||
|
||||
if (!project.vcpkg.packages.empty()) {
|
||||
if (project.vcpkg.enabled()) {
|
||||
if (!is_root_project) {
|
||||
throw std::runtime_error("[vcpkg] is only supported in the root project");
|
||||
}
|
||||
|
||||
// Allow the user to specify a url or derive it from the version
|
||||
auto url = project.vcpkg.url;
|
||||
auto version_name = url;
|
||||
@@ -798,7 +802,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
|
||||
// Show a nicer error than vcpkg when specifying an invalid package name
|
||||
for (const auto &package : project.vcpkg.packages) {
|
||||
const auto &packages = project.vcpkg.packages;
|
||||
for (const auto &package : packages) {
|
||||
if (!vcpkg_valid_identifier(package.name)) {
|
||||
throw std::runtime_error("Invalid [vcpkg].packages name '" + package.name + "' (needs to be lowercase alphanumeric)");
|
||||
}
|
||||
@@ -808,14 +813,20 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
// clang-format off
|
||||
cmd("if")("CMKR_ROOT_PROJECT", "AND", "NOT", "CMKR_DISABLE_VCPKG");
|
||||
cmd("include")("FetchContent");
|
||||
cmd("message")("STATUS", "Fetching vcpkg (" + version_name + ")...");
|
||||
cmd("FetchContent_Declare")("vcpkg", "URL", url);
|
||||
// Not using FetchContent_MakeAvailable here in case vcpkg adds CMakeLists.txt
|
||||
cmd("FetchContent_GetProperties")("vcpkg");
|
||||
cmd("if")("NOT", "vcpkg_POPULATED");
|
||||
cmd("FetchContent_Populate")("vcpkg");
|
||||
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
|
||||
comment("Fix warnings about DOWNLOAD_EXTRACT_TIMESTAMP");
|
||||
// clang-format off
|
||||
cmd("if")("POLICY", "CMP0135");
|
||||
cmd("cmake_policy")("SET", "CMP0135", "NEW");
|
||||
cmd("endif")();
|
||||
// clang-format on
|
||||
cmd("message")("STATUS", "Fetching vcpkg (" + version_name + ")...");
|
||||
cmd("FetchContent_Declare")("vcpkg", "URL", url);
|
||||
// Not using FetchContent_MakeAvailable here in case vcpkg adds CMakeLists.txt
|
||||
cmd("FetchContent_GetProperties")("vcpkg");
|
||||
cmd("if")("NOT", "vcpkg_POPULATED");
|
||||
cmd("FetchContent_Populate")("vcpkg");
|
||||
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
|
||||
cmd("endif")();
|
||||
cmd("endif")();
|
||||
endl();
|
||||
// clang-format on
|
||||
@@ -832,16 +843,21 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
"dependencies": [
|
||||
)";
|
||||
|
||||
const auto &packages = project.vcpkg.packages;
|
||||
for (size_t i = 0; i < packages.size(); i++) {
|
||||
const auto &package = packages[i];
|
||||
const auto &features = package.features;
|
||||
if (!vcpkg_valid_identifier(package.name)) {
|
||||
throw std::runtime_error("Invalid vcpkg package name '" + package.name + "'");
|
||||
throw std::runtime_error("Invalid vcpkg package name '" + package.name + "', name is not valid");
|
||||
}
|
||||
if (vcpkg_identifier_reserved(package.name)) {
|
||||
throw std::runtime_error("Invalid vcpkg package name '" + package.name + "', name is reserved");
|
||||
}
|
||||
for (const auto &feature : features) {
|
||||
if (!vcpkg_valid_identifier(feature)) {
|
||||
throw std::runtime_error("Invalid vcpkg package feature '" + feature + "'");
|
||||
throw std::runtime_error("Invalid vcpkg package feature '" + feature + "', name is not valid");
|
||||
}
|
||||
if (vcpkg_identifier_reserved(feature)) {
|
||||
throw std::runtime_error("Invalid vcpkg package feature '" + feature + "', name is reserved");
|
||||
}
|
||||
}
|
||||
if (features.empty()) {
|
||||
@@ -886,20 +902,32 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
|
||||
if (!project.contents.empty()) {
|
||||
cmd("include")("FetchContent").endl();
|
||||
if (!project.root()->vcpkg.enabled()) {
|
||||
comment("Fix warnings about DOWNLOAD_EXTRACT_TIMESTAMP");
|
||||
// clang-format off
|
||||
cmd("if")("POLICY", "CMP0135");
|
||||
cmd("cmake_policy")("SET", "CMP0135", "NEW");
|
||||
cmd("endif")();
|
||||
// clang-format on
|
||||
}
|
||||
for (const auto &content : project.contents) {
|
||||
ConditionScope cs(gen, content.condition);
|
||||
|
||||
gen.conditional_includes(content.include_before);
|
||||
gen.conditional_cmake(content.cmake_before);
|
||||
|
||||
std::string version_info = "";
|
||||
std::string version_info;
|
||||
if (content.arguments.contains("GIT_TAG")) {
|
||||
version_info = " (" + content.arguments.at("GIT_TAG") + ")";
|
||||
} else if (content.arguments.contains("SVN_REVISION")) {
|
||||
version_info = " (" + content.arguments.at("SVN_REVISION") + ")";
|
||||
}
|
||||
cmd("message")("STATUS", "Fetching " + content.name + version_info + "...");
|
||||
cmd("FetchContent_Declare")(content.name, content.arguments);
|
||||
if (content.system) {
|
||||
cmd("FetchContent_Declare")(content.name, "SYSTEM", content.arguments);
|
||||
} else {
|
||||
cmd("FetchContent_Declare")(content.name, content.arguments);
|
||||
}
|
||||
cmd("FetchContent_MakeAvailable")(content.name).endl();
|
||||
|
||||
gen.conditional_includes(content.include_after);
|
||||
@@ -1123,7 +1151,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
continue;
|
||||
const auto &source_path = fs::path(path) / source;
|
||||
if (!fs::exists(source_path)) {
|
||||
throw_target_error("Source file does not exist " + source);
|
||||
throw_target_error("Source file not found: " + source);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1319,7 +1347,12 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
auto working_directory = std::make_pair("WORKING_DIRECTORY", dir);
|
||||
auto command = std::make_pair("COMMAND", test.command);
|
||||
auto arguments = std::make_pair("", test.arguments);
|
||||
|
||||
// Transform the provided arguments into raw arguments to prevent them from being quoted when the generator runs
|
||||
std::vector<RawArg> raw_arguments{};
|
||||
for (const auto &argument : test.arguments)
|
||||
raw_arguments.emplace_back(argument);
|
||||
auto arguments = std::make_pair("", raw_arguments);
|
||||
ConditionScope cs(gen, test.condition);
|
||||
cmd("add_test")(name, configurations, working_directory, command, arguments).endl();
|
||||
}
|
||||
@@ -1350,10 +1383,19 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the generated CMakeLists.txt output from the stringstream buffer
|
||||
auto generated_cmake = ss.str();
|
||||
|
||||
// Make sure the file ends in a single newline
|
||||
while (!generated_cmake.empty() && std::isspace(generated_cmake.back())) {
|
||||
generated_cmake.pop_back();
|
||||
}
|
||||
generated_cmake += '\n';
|
||||
|
||||
// Generate CMakeLists.txt
|
||||
auto list_path = fs::path(path) / "CMakeLists.txt";
|
||||
|
||||
auto should_regenerate = [&list_path, &ss]() {
|
||||
auto should_regenerate = [&list_path, &generated_cmake]() {
|
||||
if (!fs::exists(list_path))
|
||||
return true;
|
||||
|
||||
@@ -1363,11 +1405,11 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
|
||||
}
|
||||
|
||||
std::string data((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
return data != ss.str();
|
||||
return data != generated_cmake;
|
||||
}();
|
||||
|
||||
if (should_regenerate) {
|
||||
create_file(list_path, ss.str());
|
||||
create_file(list_path, generated_cmake);
|
||||
}
|
||||
|
||||
auto generate_subdir = [path, &project](const fs::path &sub) {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "error.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace cmkr {
|
||||
namespace error {
|
||||
|
||||
Status::Status(Code ec) noexcept : ec_(ec) {
|
||||
}
|
||||
|
||||
Status::operator int() const noexcept {
|
||||
return static_cast<int>(ec_);
|
||||
}
|
||||
|
||||
Status::Code Status::code() const noexcept {
|
||||
return ec_;
|
||||
}
|
||||
|
||||
} // namespace error
|
||||
} // namespace cmkr
|
||||
|
||||
// strings for cmkr::error::Status::Code
|
||||
static const char *err_string[] = {
|
||||
"Success", "Runtime error", "Initialization error", "CMake generation error", "Build error", "Clean error", "Install error",
|
||||
};
|
||||
|
||||
const char *cmkr_error_status(int i) {
|
||||
assert(i >= 0 && static_cast<size_t>(i) < (sizeof(err_string) / sizeof(*(err_string))));
|
||||
return err_string[i];
|
||||
}
|
||||
@@ -23,11 +23,3 @@ arguments:
|
||||
}
|
||||
} // namespace help
|
||||
} // namespace cmkr
|
||||
|
||||
const char *cmkr_help_version(void) {
|
||||
return cmkr::help::version();
|
||||
}
|
||||
|
||||
const char *cmkr_help_message(void) {
|
||||
return cmkr::help::message();
|
||||
}
|
||||
+50
-5
@@ -36,7 +36,7 @@ static std::string format_key_message(const std::string &message, const toml::ke
|
||||
auto loc = value.location();
|
||||
auto line_number_str = std::to_string(loc.line());
|
||||
auto line_width = line_number_str.length();
|
||||
auto line_str = loc.line_str();
|
||||
const auto &line_str = loc.line_str();
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << message << "\n";
|
||||
@@ -73,7 +73,7 @@ class TomlChecker {
|
||||
public:
|
||||
TomlChecker(const TomlBasicValue &v, const toml::key &ky) : m_v(toml::find(v, ky)) {
|
||||
}
|
||||
TomlChecker(const TomlBasicValue &v) : m_v(v) {
|
||||
explicit TomlChecker(const TomlBasicValue &v) : m_v(v) {
|
||||
}
|
||||
TomlChecker(const TomlChecker &) = delete;
|
||||
TomlChecker(TomlChecker &&) = delete;
|
||||
@@ -175,7 +175,7 @@ class TomlCheckerRoot {
|
||||
bool m_checked = false;
|
||||
|
||||
public:
|
||||
TomlCheckerRoot(const TomlBasicValue &root) : m_root(root) {
|
||||
explicit TomlCheckerRoot(const TomlBasicValue &root) : m_root(root) {
|
||||
}
|
||||
TomlCheckerRoot(const TomlCheckerRoot &) = delete;
|
||||
TomlCheckerRoot(TomlCheckerRoot &&) = delete;
|
||||
@@ -265,9 +265,12 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
conditions["bsd"] = R"cmake(CMAKE_SYSTEM_NAME MATCHES "BSD")cmake";
|
||||
conditions["linux"] = conditions["lunix"] = R"cmake(CMAKE_SYSTEM_NAME MATCHES "Linux")cmake";
|
||||
conditions["gcc"] = R"cmake(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")cmake";
|
||||
conditions["msvc"] = R"cmake(MSVC)cmake";
|
||||
conditions["clang"] =
|
||||
R"cmake((CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$") OR (CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$"))cmake";
|
||||
conditions["msvc"] = R"cmake(MSVC)cmake";
|
||||
conditions["clang-cl"] =
|
||||
R"cmake((CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$") OR (CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC$"))cmake";
|
||||
conditions["clang-any"] = R"cmake(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "Clang")cmake";
|
||||
conditions["root"] = R"cmake(CMKR_ROOT_PROJECT)cmake";
|
||||
conditions["x64"] = R"cmake(CMAKE_SIZEOF_VOID_P EQUAL 8)cmake";
|
||||
conditions["x32"] = R"cmake(CMAKE_SIZEOF_VOID_P EQUAL 4)cmake";
|
||||
@@ -443,6 +446,15 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
c.optional("cmake-after", content.cmake_after);
|
||||
c.optional("include-before", content.include_before);
|
||||
c.optional("include-after", content.include_after);
|
||||
c.optional("system", content.system);
|
||||
|
||||
// Check if the minimum version requirement is satisfied (CMake 3.25)
|
||||
if (c.contains("system") && !this->cmake_minimum_version(3, 25)) {
|
||||
throw_key_error("The system argument is only supported on CMake version 3.25 and above.\nSet the CMake version in cmake.toml:\n"
|
||||
"[cmake]\n"
|
||||
"version = \"3.25\"\n",
|
||||
"system", "");
|
||||
}
|
||||
|
||||
for (const auto &argItr : itr.second.as_table()) {
|
||||
std::string value;
|
||||
@@ -495,6 +507,8 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
value = algo + "=" + value;
|
||||
} else if (key == "hash") {
|
||||
key = "URL_HASH";
|
||||
} else if (key == "subdir") {
|
||||
key = "SOURCE_SUBDIR";
|
||||
} else if (is_cmake_arg(key)) {
|
||||
// allow passthrough of ExternalProject options
|
||||
} else if (!c.visisted(key)) {
|
||||
@@ -585,6 +599,38 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
|
||||
t.optional("link-libraries", target.link_libraries);
|
||||
t.optional("private-link-libraries", target.private_link_libraries);
|
||||
|
||||
// Add support for relative paths for (private-)link-libraries
|
||||
const auto fix_relative_paths = [&name, &path](ConditionVector &libraries, const char *key) {
|
||||
for (const auto &library_entries : libraries) {
|
||||
for (auto &library_path : libraries[library_entries.first]) {
|
||||
// Skip processing paths with potential CMake macros in them (this check isn't perfect)
|
||||
// https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#variable-references
|
||||
if ((library_path.find("${") != std::string::npos || library_path.find("$ENV{") != std::string::npos ||
|
||||
library_path.find("$CACHE{") != std::string::npos) &&
|
||||
library_path.find('}') != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip paths that don't contain backwards or forwards slashes
|
||||
if (library_path.find_first_of(R"(\/)") == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the new file path exists, otherwise emit an error
|
||||
const auto expected_library_file_path = fs::path{path} / library_path;
|
||||
if (!fs::exists(expected_library_file_path)) {
|
||||
throw std::runtime_error("Attempted to link against a library file that doesn't exist for target \"" + name + "\" in \"" +
|
||||
key + "\": " + library_path);
|
||||
}
|
||||
|
||||
// Prepend ${CMAKE_CURRENT_SOURCE_DIR} to the path
|
||||
library_path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}/");
|
||||
}
|
||||
}
|
||||
};
|
||||
fix_relative_paths(target.link_libraries, "link-libraries");
|
||||
fix_relative_paths(target.private_link_libraries, "private-link-libraries");
|
||||
|
||||
t.optional("link-options", target.link_options);
|
||||
t.optional("private-link-options", target.private_link_options);
|
||||
|
||||
@@ -771,7 +817,6 @@ const Project *Project::root() const {
|
||||
bool Project::cmake_minimum_version(int major, int minor) const {
|
||||
// NOTE: this code is like pulling teeth, sorry
|
||||
auto root_version = root()->cmake_version;
|
||||
puts(root_version.c_str());
|
||||
auto range_index = root_version.find("...");
|
||||
if (range_index != std::string::npos) {
|
||||
root_version.resize(range_index);
|
||||
|
||||
Generated
+22
@@ -100,3 +100,25 @@ if(MSVC) # msvc
|
||||
)
|
||||
|
||||
endif()
|
||||
add_test(
|
||||
NAME
|
||||
compile-options
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_LIST_DIR}/compile-options"
|
||||
COMMAND
|
||||
"$<TARGET_FILE:cmkr>"
|
||||
build
|
||||
)
|
||||
|
||||
if(WIN32) # windows
|
||||
add_test(
|
||||
NAME
|
||||
relative-paths
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_LIST_DIR}/relative-paths"
|
||||
COMMAND
|
||||
"$<TARGET_FILE:cmkr>"
|
||||
build
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -8,4 +8,4 @@ description = "Minimal example"
|
||||
type = "executable"
|
||||
sources = ["src/basic.cpp"]
|
||||
|
||||
# Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`.
|
||||
# Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`.
|
||||
|
||||
+14
-1
@@ -51,4 +51,17 @@ condition = "msvc"
|
||||
name = "msvc-runtime"
|
||||
working-directory = "msvc-runtime"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
arguments = ["build"]
|
||||
|
||||
[[test]]
|
||||
name = "compile-options"
|
||||
working-directory = "compile-options"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
|
||||
[[test]]
|
||||
condition = "windows"
|
||||
name = "relative-paths"
|
||||
working-directory = "relative-paths"
|
||||
command = "$<TARGET_FILE:cmkr>"
|
||||
arguments = ["build"]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Example project that sets compiler/linker flags for various platforms.
|
||||
|
||||
[project]
|
||||
name = "compile-options"
|
||||
description = "Compiler flags"
|
||||
|
||||
[target.hello]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
msvc.compile-options = ["/W2"]
|
||||
gcc.compile-options = ["-Wall"]
|
||||
clang.compile-options = ["-Wall"]
|
||||
|
||||
# The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags depending on the platform. See the [targets](/cmake-toml/#targets) documentation for other things you can set.
|
||||
# _Note_: In general you only want to specify flags _required_ to compile your code without errors.
|
||||
@@ -0,0 +1,5 @@
|
||||
#include <cstdio>
|
||||
|
||||
int main() {
|
||||
puts("Hello from cmkr!");
|
||||
}
|
||||
+23
-23
@@ -1,23 +1,23 @@
|
||||
[project]
|
||||
name = "conditions"
|
||||
cmake-after = "set(CUSTOM ON)"
|
||||
|
||||
[conditions]
|
||||
custom = "CUSTOM"
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
windows.sources = ["src/windows_specific.cpp"]
|
||||
cmake-after = "message(STATUS cmake-after)"
|
||||
windows.cmake-after = "message(STATUS win32-after)"
|
||||
macos.cmake-after = "message(STATUS macos-after)"
|
||||
linux.cmake-after = "message(STATUS linux-after)"
|
||||
unix.cmake-after = "message(STATUS unix-after)"
|
||||
custom.cmake-after = "message(STATUS custom-after)"
|
||||
|
||||
[target.example.properties]
|
||||
AUTOMOC = false
|
||||
custom.OUTPUT_NAME = "example2"
|
||||
custom.AUTORCC = true
|
||||
AUTOGEN = "ON"
|
||||
[project]
|
||||
name = "conditions"
|
||||
cmake-after = "set(CUSTOM ON)"
|
||||
|
||||
[conditions]
|
||||
custom = "CUSTOM"
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
windows.sources = ["src/windows_specific.cpp"]
|
||||
cmake-after = "message(STATUS cmake-after)"
|
||||
windows.cmake-after = "message(STATUS win32-after)"
|
||||
macos.cmake-after = "message(STATUS macos-after)"
|
||||
linux.cmake-after = "message(STATUS linux-after)"
|
||||
unix.cmake-after = "message(STATUS unix-after)"
|
||||
custom.cmake-after = "message(STATUS custom-after)"
|
||||
|
||||
[target.example.properties]
|
||||
AUTOMOC = false
|
||||
custom.OUTPUT_NAME = "example2"
|
||||
custom.AUTORCC = true
|
||||
AUTOGEN = "ON"
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
int main() { }
|
||||
int main() {
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <Windows.h>
|
||||
|
||||
void foo() { }
|
||||
#include <Windows.h>
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Require a C++11 compiler for the target `example`.
|
||||
|
||||
[project]
|
||||
name = "cxx-standard"
|
||||
description = "Changing C++ standard"
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
compile-features = ["cxx_std_11"]
|
||||
|
||||
# This is equivalent to CMake's [target_compile_features](https://cmake.org/cmake/help/latest/command/target_compile_features.html)`(example PRIVATE cxx_std_11)`. For more information on available C/C++ standards and features see [cmake-compile-features(7)](https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html).
|
||||
# Require a C++11 compiler for the target `example`.
|
||||
|
||||
[project]
|
||||
name = "cxx-standard"
|
||||
description = "Changing C++ standard"
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
compile-features = ["cxx_std_11"]
|
||||
|
||||
# This is equivalent to CMake's [target_compile_features](https://cmake.org/cmake/help/latest/command/target_compile_features.html)`(example PRIVATE cxx_std_11)`. For more information on available C/C++ standards and features see [cmake-compile-features(7)](https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html).
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include <cstdio>
|
||||
#include <tuple>
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tpl = std::make_tuple(1, 2);
|
||||
printf("Hello from C++11 %d\n", std::get<0>(tpl));
|
||||
}
|
||||
#include <cstdio>
|
||||
#include <tuple>
|
||||
|
||||
int main() {
|
||||
auto tpl = std::make_tuple(1, 2);
|
||||
printf("Hello from C++11 %d\n", std::get<0>(tpl));
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
link-libraries = ["fmt::fmt"]
|
||||
|
||||
# This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html).
|
||||
# This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html).
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
fmt::print("Hello, world!\n");
|
||||
}
|
||||
}
|
||||
|
||||
+18
-18
@@ -1,18 +1,18 @@
|
||||
[project]
|
||||
name = "globbing"
|
||||
description = "Globbing sources"
|
||||
|
||||
# Recursively glob in the mylib/ folder
|
||||
[target.mylib]
|
||||
type = "static"
|
||||
alias = "mylib::mylib"
|
||||
sources = ["mylib/**.hpp", "mylib/**.cpp"]
|
||||
include-directories = ["mylib/include"]
|
||||
|
||||
# Single-folder glob in example/src/
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["example/src/*.cpp"]
|
||||
link-libraries = ["mylib::mylib"]
|
||||
|
||||
# As you can see in the example above you can use `**.ext` to glob recursively and `*.ext` to glob non-recursively. This **does not** generate `file(GLOB ...)` commands, but instead globs when cmkr is run. Files are sorted to give deterministic results regardless of the platform used.
|
||||
[project]
|
||||
name = "globbing"
|
||||
description = "Globbing sources"
|
||||
|
||||
# Recursively glob in the mylib/ folder
|
||||
[target.mylib]
|
||||
type = "static"
|
||||
alias = "mylib::mylib"
|
||||
sources = ["mylib/**.hpp", "mylib/**.cpp"]
|
||||
include-directories = ["mylib/include"]
|
||||
|
||||
# Single-folder glob in example/src/
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["example/src/*.cpp"]
|
||||
link-libraries = ["mylib::mylib"]
|
||||
|
||||
# As you can see in the example above you can use `**.ext` to glob recursively and `*.ext` to glob non-recursively. This **does not** generate `file(GLOB ...)` commands, but instead globs when cmkr is run. Files are sorted to give deterministic results regardless of the platform used.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <mylib/mylib.hpp>
|
||||
|
||||
int main() {
|
||||
std::cout << mylib::message() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#include <iostream>
|
||||
#include <mylib/mylib.hpp>
|
||||
|
||||
int main() {
|
||||
std::cout << mylib::message() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mylib
|
||||
{
|
||||
std::string message();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mylib {
|
||||
std::string message();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <mylib/mylib.hpp>
|
||||
|
||||
std::string mylib::message()
|
||||
{
|
||||
return "cmkr is awesome!";
|
||||
}
|
||||
#include <mylib/mylib.hpp>
|
||||
|
||||
std::string mylib::message() {
|
||||
return "cmkr is awesome!";
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
[project]
|
||||
name = "interface"
|
||||
description = "Header-only library"
|
||||
|
||||
[target.mylib]
|
||||
type = "interface"
|
||||
include-directories = ["include"]
|
||||
compile-features = ["cxx_std_11"]
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
link-libraries = ["mylib"]
|
||||
[project]
|
||||
name = "interface"
|
||||
description = "Header-only library"
|
||||
|
||||
[target.mylib]
|
||||
type = "interface"
|
||||
include-directories = ["include"]
|
||||
compile-features = ["cxx_std_11"]
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
link-libraries = ["mylib"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
namespace mylib
|
||||
{
|
||||
static const char* version() { return "v1.0"; }
|
||||
} // namespace mylib
|
||||
namespace mylib {
|
||||
static const char *version() {
|
||||
return "v1.0";
|
||||
}
|
||||
} // namespace mylib
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "mylib/mylib.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("mylib version: %s\n", mylib::version());
|
||||
}
|
||||
#include <cstdio>
|
||||
|
||||
#include "mylib/mylib.hpp"
|
||||
|
||||
int main() {
|
||||
printf("mylib version: %s\n", mylib::version());
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ sources = ["src/main.cpp"]
|
||||
[target.dynamic-runtime]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
msvc-runtime = "dynamic"
|
||||
msvc-runtime = "dynamic"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "relative-paths"
|
||||
|
||||
[target.test-library]
|
||||
type = "static"
|
||||
sources = ["src/library-code.cpp"]
|
||||
|
||||
[target.example]
|
||||
type = "executable"
|
||||
sources = ["src/main.cpp"]
|
||||
windows.link-libraries = ["libs/test-library-x64-Release.lib"]
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
// Created by Anthony Printup on 9/18/2023.
|
||||
#include <cstdio>
|
||||
|
||||
extern "C" void library_function() {
|
||||
std::puts("Hello from library_function!");
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Created by Anthony Printup on 9/18/2023.
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef WIN32
|
||||
extern "C" void library_function();
|
||||
#endif
|
||||
int main() {
|
||||
puts("Hello from cmkr(relative-paths)!");
|
||||
#ifdef WIN32
|
||||
library_function();
|
||||
#endif
|
||||
}
|
||||
@@ -22,4 +22,4 @@ compile-definitions = ["APP_A"]
|
||||
type = "app"
|
||||
compile-definitions = ["APP_B"]
|
||||
|
||||
# **Note**: In most cases you probably want to use an [interface](/examples/interface) target instead.
|
||||
# **Note**: In most cases you probably want to use an [interface](/examples/interface) target instead.
|
||||
|
||||
@@ -19,4 +19,4 @@ sources = ["src/main.cpp"]
|
||||
link-libraries = ["fmt::fmt"]
|
||||
|
||||
# The bootstrapping of vcpkg is fully automated and no user interaction is necessary. You can disable vcpkg by setting `CMKR_DISABLE_VCPKG=ON`.
|
||||
# To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`.
|
||||
# To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
fmt::print("Hello, world!\n");
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
# Disable clang-format in this folder
|
||||
DisableFormat: true
|
||||
SortIncludes: Never
|
||||
Reference in New Issue
Block a user