qcdx 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. qcdx/__init__.py +5 -0
  2. qcdx/__main__.py +5 -0
  3. qcdx/_commit.py +1 -0
  4. qcdx/cli.py +105 -0
  5. qcdx/data/kit/.github/actions/pk-setup/action.yml +157 -0
  6. qcdx/data/kit/cmake/QCDXConfig.cmake +17 -0
  7. qcdx/data/kit/cmake/QCDXConfigVersion.cmake +46 -0
  8. qcdx/data/kit/cmake/projectkit/ApplicationCreator.cmake +262 -0
  9. qcdx/data/kit/cmake/projectkit/CompilerWarnings.cmake +54 -0
  10. qcdx/data/kit/cmake/projectkit/ConanBuildDir.cmake +84 -0
  11. qcdx/data/kit/cmake/projectkit/Dependencies.cmake +601 -0
  12. qcdx/data/kit/cmake/projectkit/FileCollection.cmake +115 -0
  13. qcdx/data/kit/cmake/projectkit/HostTools.cmake +74 -0
  14. qcdx/data/kit/cmake/projectkit/LibraryCreator.cmake +561 -0
  15. qcdx/data/kit/cmake/projectkit/Packaging.cmake +291 -0
  16. qcdx/data/kit/cmake/projectkit/ProjectKit.cmake +21 -0
  17. qcdx/data/kit/cmake/projectkit/ProjectOptions.cmake +250 -0
  18. qcdx/data/kit/cmake/projectkit/ProjectSetup.cmake +218 -0
  19. qcdx/data/kit/cmake/projectkit/StaticAnalysis.cmake +159 -0
  20. qcdx/data/kit/cmake/projectkit/TestCreator.cmake +146 -0
  21. qcdx/data/kit/cmake/projectkit/ToolCreator.cmake +139 -0
  22. qcdx/data/kit/cmake/projectkit/Tooling.cmake +150 -0
  23. qcdx/data/kit/cmake/projectkit/VERSION +1 -0
  24. qcdx/data/kit/cmake/projectkit/docs/ANALYSER_LAUNCHER.md +154 -0
  25. qcdx/data/kit/cmake/projectkit/docs/PACKAGE.md +257 -0
  26. qcdx/data/kit/cmake/projectkit/docs/PK.md +254 -0
  27. qcdx/data/kit/cmake/projectkit/docs/PK_DEP.md +430 -0
  28. qcdx/data/kit/cmake/projectkit/docs/RELEASE.md +194 -0
  29. qcdx/data/kit/cmake/projectkit/docs/VERIFY.md +312 -0
  30. qcdx/data/kit/cmake/projectkit/scripts/analyser_launcher.py +65 -0
  31. qcdx/data/kit/cmake/projectkit/scripts/helpers/pk/deps.py +1534 -0
  32. qcdx/data/kit/cmake/projectkit/scripts/helpers/pk/presets.cmake +142 -0
  33. qcdx/data/kit/cmake/projectkit/scripts/pklib/__init__.py +0 -0
  34. qcdx/data/kit/cmake/projectkit/scripts/pklib/bootstrap.py +289 -0
  35. qcdx/data/kit/cmake/projectkit/scripts/pklib/common.py +472 -0
  36. qcdx/data/kit/cmake/projectkit/scripts/pklib/package.py +268 -0
  37. qcdx/data/kit/cmake/projectkit/scripts/pklib/pk.py +1750 -0
  38. qcdx/data/kit/cmake/projectkit/scripts/pklib/release.py +928 -0
  39. qcdx/data/kit/cmake/projectkit/scripts/pklib/targets.py +117 -0
  40. qcdx/data/kit/cmake/projectkit/scripts/pklib/verify.py +209 -0
  41. qcdx/data/kit/cmake/projectkit/scripts/pklib/verify_base.py +428 -0
  42. qcdx/data/kit/cmake/projectkit/templates/PackageConfig.cmake.in +7 -0
  43. qcdx/data/kit/cmake/projectkit/templates/pkgconfig.pc.in +11 -0
  44. qcdx/data/kit/cmake/projectkit/test_package/CMakeLists.txt +24 -0
  45. qcdx/data/kit/cmake/projectkit/test_package/conanfile.py +42 -0
  46. qcdx/data/kit/cmake/projectkit/test_package/src/example.cpp +1 -0
  47. qcdx/data/kit/scripts/bootstrap.py +10 -0
  48. qcdx/data/kit/scripts/package.py +10 -0
  49. qcdx/data/kit/scripts/pk.py +10 -0
  50. qcdx/data/kit/scripts/release.py +10 -0
  51. qcdx/data/kit/scripts/verify.py +10 -0
  52. qcdx/data/template/.clang-format +27 -0
  53. qcdx/data/template/.clang-tidy +26 -0
  54. qcdx/data/template/.clangd +6 -0
  55. qcdx/data/template/.gitattributes +1 -0
  56. qcdx/data/template/.github/workflows/release.yml +241 -0
  57. qcdx/data/template/.github/workflows/verify.yml +74 -0
  58. qcdx/data/template/.gitignore +168 -0
  59. qcdx/data/template/CMakeLists.txt +53 -0
  60. qcdx/data/template/CMakePresets.json +593 -0
  61. qcdx/data/template/README.md +56 -0
  62. qcdx/data/template/apps/CMakeLists.txt +4 -0
  63. qcdx/data/template/apps/qcdx/main.cpp +8 -0
  64. qcdx/data/template/cmake/qcdxConfig.cmake.in +38 -0
  65. qcdx/data/template/cmake/toolchains/aarch64-linux-gnu.cmake +40 -0
  66. qcdx/data/template/cmake/toolchains/aarch64-mingw-llvm-w64.cmake +28 -0
  67. qcdx/data/template/cmake/toolchains/x86_64-linux-gnu.cmake +20 -0
  68. qcdx/data/template/cmake/toolchains/x86_64-mingw-w64.cmake +20 -0
  69. qcdx/data/template/conan.lock +11 -0
  70. qcdx/data/template/conanfile.py +142 -0
  71. qcdx/data/template/deps.json +25 -0
  72. qcdx/data/template/include/qcdx/core.hpp +9 -0
  73. qcdx/data/template/profiles/aarch64-linux-gnu +43 -0
  74. qcdx/data/template/profiles/aarch64-mingw-llvm-w64 +42 -0
  75. qcdx/data/template/profiles/ci-linux-armv8 +19 -0
  76. qcdx/data/template/profiles/ci-linux-x86_64 +19 -0
  77. qcdx/data/template/profiles/ci-macos-armv8 +17 -0
  78. qcdx/data/template/profiles/ci-macos-x86_64 +17 -0
  79. qcdx/data/template/profiles/ci-windows-clang64 +12 -0
  80. qcdx/data/template/profiles/ci-windows-clangarm64 +12 -0
  81. qcdx/data/template/profiles/ci-windows-ucrt64 +12 -0
  82. qcdx/data/template/profiles/native +32 -0
  83. qcdx/data/template/profiles/x86_64-linux-gnu +43 -0
  84. qcdx/data/template/profiles/x86_64-mingw-w64 +44 -0
  85. qcdx/data/template/scripts/helpers/package/package.conf +3 -0
  86. qcdx/data/template/scripts/helpers/release/release.conf +99 -0
  87. qcdx/data/template/scripts/helpers/verify/consumer.cpp +7 -0
  88. qcdx/data/template/scripts/helpers/verify/verify.conf +1 -0
  89. qcdx/data/template/src/CMakeLists.txt +5 -0
  90. qcdx/data/template/src/qcdx/core.cpp +13 -0
  91. qcdx/data/template/tests/CMakeLists.txt +4 -0
  92. qcdx/data/template/tests/qcdx/tests_core.cpp +10 -0
  93. qcdx/data/template/tools/CMakeLists.txt +4 -0
  94. qcdx/data/template/tools/codegen.cpp +137 -0
  95. qcdx/new.py +224 -0
  96. qcdx/resources.py +131 -0
  97. qcdx-0.1.0.dist-info/METADATA +298 -0
  98. qcdx-0.1.0.dist-info/RECORD +101 -0
  99. qcdx-0.1.0.dist-info/WHEEL +4 -0
  100. qcdx-0.1.0.dist-info/entry_points.txt +3 -0
  101. qcdx-0.1.0.dist-info/licenses/LICENSE +21 -0
qcdx/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ """QCDX: create, build, test, package and release C and C++ projects."""
2
+
3
+ from .resources import version as _version
4
+
5
+ __version__ = _version()
qcdx/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())
qcdx/_commit.py ADDED
@@ -0,0 +1 @@
1
+ COMMIT = "5b7e37c25528c05ec84e1be4a7c21d4c9a6168e1"
qcdx/cli.py ADDED
@@ -0,0 +1,105 @@
1
+ """The global 'pk' command.
2
+
3
+ Outside a project it creates one ('pk new'). Inside a project every command
4
+ runs that project's own scripts/pk.py, so the kit version the project
5
+ vendored decides what 'pk build' does, never the installed QCDX version.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ import subprocess
12
+ import sys
13
+ from pathlib import Path
14
+ from typing import List, Optional
15
+
16
+ from . import new, resources
17
+
18
+ HELP = """\
19
+ pk - QCDX {version}: create and build C and C++ projects with CMake and Conan
20
+
21
+ usage:
22
+ pk new NAME [DIR] [flag...] create a project ('pk new --help')
23
+ pk cmake-dir print the QCDX CMake package directory, for
24
+ -DQCDX_DIR=... or CMAKE_PREFIX_PATH
25
+ pk --version QCDX version, and the kit version of this project
26
+
27
+ Inside a project every other command (build, run, test, sync, ...) runs the
28
+ project's own scripts/pk.py; 'pk help' there lists them all.{where}"""
29
+
30
+
31
+ def find_project(start: Path) -> Optional[Path]:
32
+ for directory in (start, *start.parents):
33
+ if (directory / "scripts" / "pk.py").is_file() and (directory / "CMakePresets.json").is_file():
34
+ return directory
35
+ return None
36
+
37
+
38
+ def project_kit_version(project: Path) -> str:
39
+ try:
40
+ return (project / "cmake" / "projectkit" / "VERSION").read_text(encoding="utf-8").strip()
41
+ except OSError:
42
+ return "unknown (older than 0.1.0)"
43
+
44
+
45
+ def tool_path(env: dict) -> None:
46
+ """Append this Python's scripts folder to PATH, as a fallback.
47
+
48
+ pipx and uv keep a package's dependencies in a private environment, so
49
+ the conan, cmake and ninja of "qcdx[tools]" are only reachable this way.
50
+ Appended, not prepended: tools the user installed always win.
51
+ """
52
+ folder = os.path.dirname(os.path.abspath(sys.executable))
53
+ found = [name for name in ("conan", "cmake", "ninja")
54
+ if any(os.path.isfile(os.path.join(folder, name + ext)) for ext in ("", ".exe"))]
55
+ paths = env.get("PATH", "").split(os.pathsep)
56
+ if found and folder not in paths:
57
+ env["PATH"] = os.pathsep.join([*paths, folder])
58
+
59
+
60
+ def delegate(project: Path, argv: List[str]) -> int:
61
+ env = dict(os.environ, PK_SELF_NAME="pk")
62
+ tool_path(env)
63
+ script = str(project / "scripts" / "pk.py")
64
+ try:
65
+ return subprocess.call([sys.executable, script, *argv], env=env)
66
+ except KeyboardInterrupt:
67
+ return 130
68
+
69
+
70
+ def main(argv: Optional[List[str]] = None) -> int:
71
+ try:
72
+ return run(list(sys.argv[1:] if argv is None else argv))
73
+ except BrokenPipeError: # 'pk ... | head'
74
+ os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())
75
+ return 141
76
+ except KeyboardInterrupt:
77
+ return 130
78
+
79
+
80
+ def run(argv: List[str]) -> int:
81
+ project = find_project(Path.cwd())
82
+ command = argv[0] if argv else ""
83
+
84
+ if command == "new":
85
+ return new.main(argv[1:])
86
+ if command in ("--version", "-V", "version"):
87
+ print(f"QCDX {resources.version()}")
88
+ if project is not None:
89
+ print(f"kit {project_kit_version(project)} in {project}")
90
+ return 0
91
+ if command == "cmake-dir":
92
+ print(resources.cmake_dir())
93
+ return 0
94
+ if project is not None:
95
+ return delegate(project, argv)
96
+ if command in ("", "help", "-h", "--help"):
97
+ print(HELP.format(version=resources.version(), where="\n\n(no project here)"))
98
+ return 0
99
+ sys.stderr.write(f"pk: '{command}' needs a project, and there is none in {Path.cwd()} or above.\n"
100
+ " 'pk new NAME' creates one.\n")
101
+ return 2
102
+
103
+
104
+ if __name__ == "__main__":
105
+ sys.exit(main())
@@ -0,0 +1,157 @@
1
+ name: pk-setup
2
+ description: >-
3
+ Toolchain, Conan and the Conan cache for a verify/release target. Used by
4
+ verify.yml and release.yml to only have to set up target once in one place.
5
+
6
+ inputs:
7
+ target:
8
+ description: A target name from cmake/projectkit/scripts/pklib/targets.py.
9
+ required: true
10
+ msystem:
11
+ description: MSYS2 environment (UCRT64, CLANG64, CLANGARM64), Windows only.
12
+ default: ''
13
+ cache:
14
+ description: "'save' restores & saves Conan cache, 'restore' doesn't save."
15
+ default: save
16
+ conan-version:
17
+ default: '2.33.0'
18
+ llvm-mingw-tag:
19
+ default: '20260616'
20
+ llvm-mingw-asset:
21
+ # Linux x86_64 UCRT build of the pinned release.
22
+ default: llvm-mingw-20260616-ucrt-ubuntu-22.04-x86_64.tar.xz
23
+ llvm-mingw-sha256:
24
+ default: 534b92e067b22a6b4441f48ae9240a3341b17825d04d577eab0cf85c44b4deda
25
+
26
+ runs:
27
+ using: composite
28
+ steps:
29
+ # -------------------------------------------------------------------------
30
+ # Linux and macOS
31
+ # -------------------------------------------------------------------------
32
+
33
+ - if: runner.os != 'Windows'
34
+ uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
35
+
36
+ - if: runner.os != 'Windows'
37
+ uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
38
+ with:
39
+ python-version: '3.12'
40
+
41
+ - name: Install Conan
42
+ if: runner.os != 'Windows'
43
+ shell: bash
44
+ run: python -m pip install --disable-pip-version-check "conan==${{ inputs.conan-version }}"
45
+
46
+ # Conan only accepts compiler.cstd=23 from GCC 14. apt should only run when
47
+ # something is missing.
48
+ - name: Install Linux packages
49
+ if: runner.os == 'Linux'
50
+ shell: bash
51
+ env:
52
+ TARGET: ${{ inputs.target }}
53
+ run: |
54
+ packages=()
55
+ command -v g++-14 >/dev/null || packages+=(g++-14)
56
+ case "$TARGET" in
57
+ cross-x86_64-mingw-w64) packages+=(g++-mingw-w64-x86-64) ;;
58
+ cross-aarch64-linux-gnu) command -v aarch64-linux-gnu-gcc >/dev/null || packages+=(g++-aarch64-linux-gnu) ;;
59
+ cross-x86_64-linux-gnu) command -v x86_64-linux-gnu-gcc >/dev/null || packages+=(g++-x86-64-linux-gnu) ;;
60
+ esac
61
+ if [ ${#packages[@]} -gt 0 ]; then
62
+ sudo apt-get update -qq
63
+ sudo apt-get install -y -qq --no-install-recommends "${packages[@]}"
64
+ fi
65
+ if [ "$TARGET" = cross-x86_64-mingw-w64 ]; then
66
+ sudo update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix
67
+ sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
68
+ fi
69
+ echo "CC=gcc-14" >> "$GITHUB_ENV"
70
+ echo "CXX=g++-14" >> "$GITHUB_ENV"
71
+
72
+ - name: Install llvm-mingw
73
+ if: inputs.target == 'cross-aarch64-mingw-llvm-w64'
74
+ shell: bash
75
+ env:
76
+ TAG: ${{ inputs.llvm-mingw-tag }}
77
+ ASSET: ${{ inputs.llvm-mingw-asset }}
78
+ SHA256: ${{ inputs.llvm-mingw-sha256 }}
79
+ run: |
80
+ archive="$RUNNER_TEMP/$ASSET"
81
+ curl -fsSL -o "$archive" "https://github.com/mstorsjo/llvm-mingw/releases/download/${TAG}/${ASSET}"
82
+ echo "${SHA256} ${archive}" | sha256sum -c -
83
+ mkdir -p "$RUNNER_TEMP/llvm-mingw"
84
+ tar -xJf "$archive" -C "$RUNNER_TEMP/llvm-mingw" --strip-components=1
85
+ rm -f "$archive"
86
+ echo "$RUNNER_TEMP/llvm-mingw/bin" >> "$GITHUB_PATH"
87
+
88
+ - name: Point Conan at the runner temp directory
89
+ if: runner.os != 'Windows'
90
+ shell: bash
91
+ run: echo "CONAN_HOME=$RUNNER_TEMP/conan2" >> "$GITHUB_ENV"
92
+
93
+ # -------------------------------------------------------------------------
94
+ # Windows (MSYS2)
95
+ # -------------------------------------------------------------------------
96
+
97
+ - if: runner.os == 'Windows'
98
+ uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
99
+ with:
100
+ msystem: ${{ inputs.msystem }}
101
+ update: true
102
+ install: git
103
+ pacboy: >-
104
+ toolchain:p
105
+ cmake:p
106
+ ninja:p
107
+ python-pip:p
108
+ pkgconf:p
109
+
110
+ # Visual Studio is installed on the runner used, Conan prefers
111
+ # MSVC on Windows, CC/CXX override it.
112
+ - name: Select the MSYS2 compiler
113
+ if: runner.os == 'Windows'
114
+ shell: pwsh
115
+ env:
116
+ MSYSTEM_NAME: ${{ inputs.msystem }}
117
+ run: |
118
+ if ($env:MSYSTEM_NAME -like 'CLANG*') { $cc = 'clang'; $cxx = 'clang++' } else { $cc = 'gcc'; $cxx = 'g++' }
119
+ "CC=$cc" >> $env:GITHUB_ENV
120
+ "CXX=$cxx" >> $env:GITHUB_ENV
121
+ "CONAN_HOME=$env:RUNNER_TEMP\conan2" >> $env:GITHUB_ENV
122
+
123
+ - name: Install Conan
124
+ if: runner.os == 'Windows'
125
+ shell: msys2 {0}
126
+ run: python -m pip install --disable-pip-version-check --break-system-packages "conan==${{ inputs.conan-version }}"
127
+
128
+ # -------------------------------------------------------------------------
129
+ # Conan cache
130
+ # -------------------------------------------------------------------------
131
+
132
+ # The key is shared with verify.yml, and caches saved on main can be read
133
+ # from every branch and tag: release runs will reuse verify's packages,
134
+ # NEVER storing a wasteful second copy.
135
+ - if: inputs.cache == 'save'
136
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
137
+ with:
138
+ path: ${{ runner.temp }}/conan2/p
139
+ key: conan-${{ inputs.target }}-${{ hashFiles('conanfile.py', 'deps.json', 'conan.lock', 'profiles/**') }}
140
+ restore-keys: conan-${{ inputs.target }}-
141
+
142
+ - if: inputs.cache == 'restore'
143
+ uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
144
+ with:
145
+ path: ${{ runner.temp }}/conan2/p
146
+ key: conan-${{ inputs.target }}-${{ hashFiles('conanfile.py', 'deps.json', 'conan.lock', 'profiles/**') }}
147
+ restore-keys: conan-${{ inputs.target }}-
148
+
149
+ - name: Detect the default Conan profile
150
+ if: runner.os != 'Windows'
151
+ shell: bash
152
+ run: conan profile detect --force
153
+
154
+ - name: Detect the default Conan profile
155
+ if: runner.os == 'Windows'
156
+ shell: msys2 {0}
157
+ run: conan profile detect --force
@@ -0,0 +1,17 @@
1
+ # find_package(QCDX) puts ProjectKit on the module path:
2
+ #
3
+ # find_package(QCDX 0.1 REQUIRED)
4
+ # include(ProjectKit)
5
+ #
6
+ # The same file works installed (share/qcdx/cmake), inside the Python package
7
+ # ('pk cmake-dir') and in a source tree or FetchContent download (cmake/), since
8
+ # everything is found relative to this file.
9
+
10
+ get_filename_component(QCDX_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}/projectkit" ABSOLUTE)
11
+ file(STRINGS "${QCDX_MODULE_DIR}/VERSION" QCDX_VERSION LIMIT_COUNT 1)
12
+
13
+ if(NOT QCDX_MODULE_DIR IN_LIST CMAKE_MODULE_PATH)
14
+ list(APPEND CMAKE_MODULE_PATH "${QCDX_MODULE_DIR}")
15
+ endif()
16
+
17
+ set(QCDX_FOUND TRUE)
@@ -0,0 +1,46 @@
1
+ # Version check for find_package(QCDX ...). Before 1.0 a minor release may
2
+ # break things, so 0.1 matches 0.1.x only; from 1.0 the major version decides.
3
+ # Version ranges (find_package(QCDX 0.1...<0.3)) are checked against the bounds.
4
+
5
+ file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/projectkit/VERSION" PACKAGE_VERSION LIMIT_COUNT 1)
6
+
7
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
8
+ set(PACKAGE_VERSION_EXACT FALSE)
9
+
10
+ if(PACKAGE_FIND_VERSION_RANGE)
11
+ set(_qcdx_ok TRUE)
12
+ if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN)
13
+ set(_qcdx_ok FALSE)
14
+ endif()
15
+ if(PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE")
16
+ if(PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX)
17
+ set(_qcdx_ok FALSE)
18
+ endif()
19
+ elseif(PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX)
20
+ set(_qcdx_ok FALSE)
21
+ endif()
22
+ set(PACKAGE_VERSION_COMPATIBLE ${_qcdx_ok})
23
+ unset(_qcdx_ok)
24
+ elseif(NOT PACKAGE_FIND_VERSION)
25
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
26
+ elseif(PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION)
27
+ string(REGEX MATCH "^[0-9]+" _qcdx_major "${PACKAGE_VERSION}")
28
+ string(REGEX MATCH "^[0-9]+\\.[0-9]+" _qcdx_minor "${PACKAGE_VERSION}")
29
+ if(_qcdx_major STREQUAL "0")
30
+ set(_qcdx_have "${_qcdx_minor}")
31
+ set(_qcdx_want "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}")
32
+ else()
33
+ set(_qcdx_have "${_qcdx_major}")
34
+ set(_qcdx_want "${PACKAGE_FIND_VERSION_MAJOR}")
35
+ endif()
36
+ if(_qcdx_have STREQUAL _qcdx_want)
37
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
38
+ endif()
39
+ if(PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
40
+ set(PACKAGE_VERSION_EXACT TRUE)
41
+ endif()
42
+ unset(_qcdx_major)
43
+ unset(_qcdx_minor)
44
+ unset(_qcdx_have)
45
+ unset(_qcdx_want)
46
+ endif()
@@ -0,0 +1,262 @@
1
+ include_guard(GLOBAL)
2
+
3
+ function(pk_create_app)
4
+ set(options
5
+ DEFAULT_DIRS
6
+ REQUIRE_SOURCES
7
+ REQUIRE_PUBLIC_HEADERS
8
+ REQUIRE_PRIVATE_HEADERS
9
+ NO_DEFAULT_LINKS
10
+ NO_INSTALL)
11
+
12
+ set(one_value_args
13
+ NAME
14
+ LANGUAGE
15
+ SOURCE_DIR
16
+ INCLUDE_DIR)
17
+
18
+ set(multi_value_args
19
+ TARGET_NAME
20
+ OUTPUT_NAME
21
+ SOURCES
22
+ PUBLIC_HEADERS
23
+ PRIVATE_HEADERS
24
+ LINK_PRIVATE
25
+ LINK_INTERFACE
26
+ DEPS)
27
+
28
+ cmake_parse_arguments(ARG
29
+ "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
30
+
31
+ pk_project_prefix(prefix)
32
+
33
+ if(NOT ARG_NAME)
34
+ message(FATAL_ERROR "pk_create_app requires a 'NAME' argument.")
35
+ endif()
36
+ if(ARG_UNPARSED_ARGUMENTS)
37
+ message(FATAL_ERROR
38
+ "pk_create_app (func): unrecognized arguments for '${ARG_NAME}': "
39
+ "${ARG_UNPARSED_ARGUMENTS}")
40
+ endif()
41
+
42
+ if(NOT ARG_TARGET_NAME)
43
+ set(ARG_TARGET_NAME "${ARG_NAME}_app")
44
+ endif()
45
+ list(LENGTH ARG_TARGET_NAME target_count)
46
+
47
+ if(NOT ARG_OUTPUT_NAME)
48
+ if(target_count EQUAL 1)
49
+ set(ARG_OUTPUT_NAME "${ARG_NAME}")
50
+ else()
51
+ set(ARG_OUTPUT_NAME ${ARG_TARGET_NAME})
52
+ endif()
53
+ endif()
54
+ list(LENGTH ARG_OUTPUT_NAME output_count)
55
+
56
+ if(NOT output_count EQUAL target_count)
57
+ message(FATAL_ERROR
58
+ "pk_create_app (func): '${ARG_NAME}' has ${target_count} "
59
+ "'TARGET_NAME' values but ${output_count} 'OUTPUT_NAME' values, one "
60
+ "'OUTPUT_NAME' is required per target.")
61
+ endif()
62
+
63
+ set(unique_targets ${ARG_TARGET_NAME})
64
+ set(unique_outputs ${ARG_OUTPUT_NAME})
65
+ list(REMOVE_DUPLICATES unique_targets)
66
+ list(REMOVE_DUPLICATES unique_outputs)
67
+ list(LENGTH unique_targets unique_target_count)
68
+ list(LENGTH unique_outputs unique_output_count)
69
+
70
+ if(NOT unique_target_count EQUAL target_count)
71
+ message(FATAL_ERROR
72
+ "pk_create_app (func): '${ARG_NAME}' has duplicate 'TARGET_NAME' "
73
+ "values: ${ARG_TARGET_NAME}")
74
+ endif()
75
+ if(NOT unique_output_count EQUAL output_count)
76
+ message(FATAL_ERROR
77
+ "pk_create_app (func): '${ARG_NAME}' has duplicate 'OUTPUT_NAME' "
78
+ "values: ${ARG_OUTPUT_NAME}")
79
+ endif()
80
+
81
+ pk_resolve_files(ARG_SOURCES "'${ARG_NAME}' SOURCES"
82
+ "\\.(c|cc|cpp|cxx)$" ${ARG_SOURCES})
83
+ pk_resolve_files(ARG_PUBLIC_HEADERS "'${ARG_NAME}' PUBLIC_HEADERS"
84
+ "\\.(h|hh|hpp|hxx)$" ${ARG_PUBLIC_HEADERS})
85
+ pk_resolve_files(ARG_PRIVATE_HEADERS "'${ARG_NAME}' PRIVATE_HEADERS"
86
+ "\\.(h|hh|hpp|hxx)$" ${ARG_PRIVATE_HEADERS})
87
+
88
+ foreach(header IN LISTS ARG_PUBLIC_HEADERS)
89
+ if(header IN_LIST ARG_PRIVATE_HEADERS)
90
+ message(FATAL_ERROR
91
+ "pk_create_app (func): '${ARG_NAME}' header passed as both "
92
+ "'PUBLIC_HEADERS' and 'PRIVATE_HEADERS': '${header}'.")
93
+ endif()
94
+ endforeach()
95
+
96
+ set(source_dir_given FALSE)
97
+ set(include_dir_given FALSE)
98
+
99
+ if(ARG_SOURCE_DIR)
100
+ cmake_path(ABSOLUTE_PATH ARG_SOURCE_DIR
101
+ BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" NORMALIZE)
102
+ string(REGEX REPLACE "(.)/+$" "\\1" ARG_SOURCE_DIR "${ARG_SOURCE_DIR}")
103
+ if(NOT IS_DIRECTORY "${ARG_SOURCE_DIR}")
104
+ message(FATAL_ERROR
105
+ "pk_create_app (func): 'SOURCE_DIR' for '${ARG_NAME}' is not a "
106
+ "directory: '${ARG_SOURCE_DIR}'.")
107
+ endif()
108
+ set(source_dir_given TRUE)
109
+ elseif(ARG_DEFAULT_DIRS)
110
+ set(ARG_SOURCE_DIR "${PROJECT_SOURCE_DIR}/apps/${ARG_NAME}")
111
+ else()
112
+ set(ARG_SOURCE_DIR "")
113
+ endif()
114
+
115
+ if(ARG_INCLUDE_DIR)
116
+ cmake_path(ABSOLUTE_PATH ARG_INCLUDE_DIR
117
+ BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" NORMALIZE)
118
+ string(REGEX REPLACE "(.)/+$" "\\1" ARG_INCLUDE_DIR "${ARG_INCLUDE_DIR}")
119
+ if(NOT IS_DIRECTORY "${ARG_INCLUDE_DIR}")
120
+ message(FATAL_ERROR
121
+ "pk_create_app (func): 'INCLUDE_DIR' for '${ARG_NAME}' is not a "
122
+ "directory: '${ARG_INCLUDE_DIR}'.")
123
+ endif()
124
+ set(include_dir_given TRUE)
125
+ else()
126
+ set(ARG_INCLUDE_DIR "")
127
+ endif()
128
+
129
+ if(ARG_SOURCE_DIR)
130
+ set(source_where "'${ARG_SOURCE_DIR}'")
131
+ else()
132
+ set(source_where "no 'SOURCE_DIR'")
133
+ endif()
134
+ if(ARG_INCLUDE_DIR)
135
+ set(include_where "'${ARG_INCLUDE_DIR}'")
136
+ else()
137
+ set(include_where "no 'INCLUDE_DIR'")
138
+ endif()
139
+
140
+ pk_collect_components(${ARG_NAME}
141
+ SOURCE_DIR "${ARG_SOURCE_DIR}"
142
+ INCLUDE_DIR "${ARG_INCLUDE_DIR}"
143
+ OUT_SOURCES globbed_sources
144
+ OUT_PUBLIC_HEADERS globbed_public_headers
145
+ OUT_PRIVATE_HEADERS globbed_private_headers)
146
+
147
+ if(source_dir_given AND NOT globbed_sources AND NOT globbed_private_headers)
148
+ message(FATAL_ERROR
149
+ "pk_create_app (func): 'SOURCE_DIR' for '${ARG_NAME}' contains no "
150
+ "sources or headers: '${ARG_SOURCE_DIR}'.")
151
+ endif()
152
+ if(include_dir_given AND NOT globbed_public_headers)
153
+ message(FATAL_ERROR
154
+ "pk_create_app (func): 'INCLUDE_DIR' for '${ARG_NAME}' contains no "
155
+ "headers: '${ARG_INCLUDE_DIR}'.")
156
+ endif()
157
+
158
+ set(explicit_files ${ARG_SOURCES} ${ARG_PUBLIC_HEADERS} ${ARG_PRIVATE_HEADERS})
159
+ if(explicit_files)
160
+ foreach(globbed IN ITEMS
161
+ globbed_sources globbed_public_headers globbed_private_headers)
162
+ if(${globbed})
163
+ list(REMOVE_ITEM ${globbed} ${explicit_files})
164
+ endif()
165
+ endforeach()
166
+ endif()
167
+
168
+ list(APPEND ARG_SOURCES ${globbed_sources})
169
+ list(APPEND ARG_PUBLIC_HEADERS ${globbed_public_headers})
170
+ list(APPEND ARG_PRIVATE_HEADERS ${globbed_private_headers})
171
+
172
+ if(NOT ARG_SOURCES)
173
+ message(FATAL_ERROR
174
+ "pk_create_app (func): No sources found for '${ARG_NAME}' in "
175
+ "${source_where} and none were given via 'SOURCES'.")
176
+ endif()
177
+ if(ARG_REQUIRE_PUBLIC_HEADERS AND NOT ARG_PUBLIC_HEADERS)
178
+ message(FATAL_ERROR
179
+ "pk_create_app (func): Public headers are required for "
180
+ "'${ARG_NAME}', yet none were found in ${include_where} and none were "
181
+ "given via 'PUBLIC_HEADERS'.")
182
+ endif()
183
+ if(ARG_REQUIRE_PRIVATE_HEADERS AND NOT ARG_PRIVATE_HEADERS)
184
+ message(FATAL_ERROR
185
+ "pk_create_app (func): Private headers are required for "
186
+ "'${ARG_NAME}', yet none were found in ${source_where} and none were "
187
+ "given via 'PRIVATE_HEADERS'.")
188
+ endif()
189
+
190
+ pk_resolve_language(language source_languages "application '${ARG_NAME}'"
191
+ "${ARG_LANGUAGE}" ${ARG_SOURCES})
192
+
193
+ set(app_languages ${language} ${source_languages})
194
+ list(REMOVE_DUPLICATES app_languages)
195
+
196
+ set(std_C "c_std_${${prefix}_C_STANDARD}")
197
+ set(std_CXX "cxx_std_${${prefix}_CXX_STANDARD}")
198
+
199
+ foreach(target output IN ZIP_LISTS ARG_TARGET_NAME ARG_OUTPUT_NAME)
200
+ add_executable(${target} ${ARG_SOURCES})
201
+
202
+ set_target_properties(${target} PROPERTIES
203
+ OUTPUT_NAME "${output}")
204
+
205
+ if(ARG_PUBLIC_HEADERS)
206
+ target_sources(${target}
207
+ PRIVATE
208
+ FILE_SET ${ARG_NAME}_app_public_headers
209
+ TYPE HEADERS
210
+ BASE_DIRS "${PROJECT_SOURCE_DIR}/include"
211
+ FILES ${ARG_PUBLIC_HEADERS})
212
+ endif()
213
+
214
+ if(ARG_PRIVATE_HEADERS)
215
+ target_sources(${target}
216
+ PRIVATE
217
+ FILE_SET ${ARG_NAME}_app_private_headers
218
+ TYPE HEADERS
219
+ BASE_DIRS "${PROJECT_SOURCE_DIR}/apps"
220
+ FILES ${ARG_PRIVATE_HEADERS})
221
+ endif()
222
+
223
+ foreach(app_language IN LISTS app_languages)
224
+ target_compile_features(${target} PRIVATE ${std_${app_language}})
225
+ endforeach()
226
+
227
+ target_compile_definitions(${target} PRIVATE
228
+ ${prefix}_VERSION_STRING="${PROJECT_VERSION}")
229
+ endforeach()
230
+
231
+ if(ARG_NO_DEFAULT_LINKS)
232
+ set(default_links NO_DEFAULT_LINKS)
233
+ else()
234
+ set(default_links "")
235
+ endif()
236
+
237
+ pk_link_targets(
238
+ ${default_links}
239
+ TARGETS ${ARG_TARGET_NAME}
240
+ LINK_PRIVATE ${ARG_LINK_PRIVATE}
241
+ LINK_INTERFACE ${ARG_LINK_INTERFACE})
242
+
243
+ pk_deps_link(
244
+ ROLE APPLICATION
245
+ TARGETS ${ARG_TARGET_NAME}
246
+ PRIVATE ${ARG_DEPS})
247
+
248
+ foreach(target IN LISTS ARG_TARGET_NAME)
249
+ pk_enable_static_analysis(${target})
250
+ endforeach()
251
+
252
+ if(${prefix}_INSTALL AND NOT ARG_NO_INSTALL)
253
+ install(TARGETS ${ARG_TARGET_NAME}
254
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
255
+ endif()
256
+
257
+ pk_register_targets(APPLICATION TARGETS ${ARG_TARGET_NAME})
258
+
259
+ string(JOIN "', '" target_list ${ARG_TARGET_NAME})
260
+ message(STATUS "${PROJECT_NAME}: Application built for '${ARG_NAME}' "
261
+ "with executable target(s) named '${target_list}'.")
262
+ endfunction()
@@ -0,0 +1,54 @@
1
+ include_guard(GLOBAL)
2
+
3
+ function(pk_add_warnings_target)
4
+ pk_project_prefix(prefix)
5
+ set(target "${PROJECT_NAME}_warnings")
6
+
7
+ add_library(${target} INTERFACE)
8
+ add_library(${PROJECT_NAME}::warnings ALIAS ${target})
9
+ set_target_properties(${target} PROPERTIES EXPORT_NAME warnings)
10
+
11
+ set(gnu_ids "GNU,Clang,AppleClang,IntelLLVM")
12
+
13
+ set(gnu_common
14
+ -Wall
15
+ -Wextra
16
+ -Wpedantic
17
+ -Wshadow
18
+ -Wcast-align
19
+ -Wsign-conversion
20
+ -Wnull-dereference
21
+ -Wdouble-promotion
22
+ -Wformat=2
23
+ -Wimplicit-fallthrough)
24
+
25
+ set(gnu_c ${gnu_common}
26
+ -Wstrict-prototypes
27
+ -Wmissing-prototypes)
28
+
29
+ set(gnu_cxx ${gnu_common}
30
+ -Wnon-virtual-dtor
31
+ -Wold-style-cast)
32
+
33
+ set(msvc_c
34
+ /W4
35
+ /w14826)
36
+
37
+ set(msvc_cxx ${msvc_c}
38
+ /permissive-
39
+ /w14640)
40
+
41
+ target_compile_options(${target} INTERFACE
42
+ "$<$<COMPILE_LANG_AND_ID:C,${gnu_ids}>:${gnu_c}>"
43
+ "$<$<COMPILE_LANG_AND_ID:CXX,${gnu_ids}>:${gnu_cxx}>"
44
+ "$<$<COMPILE_LANG_AND_ID:C,MSVC>:${msvc_c}>"
45
+ "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:${msvc_cxx}>")
46
+
47
+ if(${prefix}_WERROR)
48
+ target_compile_options(${target} INTERFACE
49
+ "$<$<COMPILE_LANG_AND_ID:C,${gnu_ids}>:-Werror>"
50
+ "$<$<COMPILE_LANG_AND_ID:CXX,${gnu_ids}>:-Werror>"
51
+ "$<$<COMPILE_LANG_AND_ID:C,MSVC>:/WX>"
52
+ "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/WX>")
53
+ endif()
54
+ endfunction()