-
Notifications
You must be signed in to change notification settings - Fork 1
Welcome
Hi! Thanks for your interest into the Common Package Specification (CPS). These documents are intended to supplement the specification itself with community-editable tutorials, guides, and other explanations.
CPS is a schema for JSON files. Those files describe libraries as built and installed on a filesystem. Currently CPS is targeting C, C++, and Fortran projects, but the project will be extensible to support other languages. The main purpose of CPS is to provide interoperability mechanisms across various tools, with interoperation across build systems as an initial target.
One of the challenges in modern development for natively compiled libraries is that there is no standard or de facto definition for what a library is, exactly. To CPS, a library has a definition -- an entry in a CPS file. All of the following are describable with CPS JSON files:
- static libraries
- shared libraries
- header-only libraries
- deployed object files
- collections of flags modeled as a library
No tools currently use CPS, though there is active research to add CPS support to the CMake build system. There is also interest and collaboration with maintainers of popular C++ ecosystems. Also, an open source project called cps-config has been launched to assist in interacting with installed CPS files from the command line and potentially build systems. Contributors welcome!
It is premature to standardize CPS right now, but it is a goal of the project to propose an addition to a to-be-created ISO C++ Ecosystem Standard as soon as there is sufficient adoption experience to justify that step.
Generally, it is not expected that end users would interact with CPS files directly. Instead, it will be a way for various tools to communicate with one another about what a library is and how to use it.
End user exposure to CPS files would probably be limited to troubleshooting workflows when tools are not interoperating as expected. For instance, looking for inaccurate fields or sharing contents of CPS files in bug reports.
Specific steps to solve specific problems!
How do I write a CPS file for a given type of project?
In a file called fmt.cps
:
{
"cps_version": "0.11.0",
"name": "fmt",
"description": "An open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams.",
"license": "MIT",
"version": "10.2.1",
"default_components": [ "fmt" ],
"components": {
"fmt": {
"type": "archive",
"definitions": {"*": {"FMT_HEADER_ONLY": "0"}},
"requires": [],
"includes": ["@prefix@/include"],
"location": "@prefix@/lib64/libfmt.a"
}
}
}
Note:
- The library would be of the
archive
type. - The
location
is the location of the library binary file. - The "header-only" preprocessor definition is explicitly disabled.
In a file called fmt.cps
:
{
"cps_version": "0.11.0",
"name": "fmt",
"description": "An open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams.",
"license": "MIT",
"version": "10.2.1",
"default_components": [ "fmt" ],
"components": {
"fmt": {
"type": "dylib",
"definitions": {"*": {"FMT_HEADER_ONLY": "0"}},
"requires": [],
"includes": ["@prefix@/include"],
"location": "@prefix@/lib64/libfmt.so"
}
}
}
Note:
- The library would be of the
dylib
type. - The
location
is the location of the library to be linked in downstream projects. - The "header-only" preprocessor definition is explicitly disabled.
- TODO: What about RUNPATH?
In a file called fmt.cps
:
{
"cps_version": "0.11.0",
"name": "fmt",
"description": "An open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams.",
"license": "MIT",
"version": "10.2.1",
"default_components": [ "fmt" ],
"components": {
"fmt": {
"type": "interface",
"definitions": {"*": {"FMT_HEADER_ONLY": "1"}},
"requires": [],
"includes": ["@prefix@/include"],
}
}
}
Note:
- The library would be of the
interface
type. - For this library, a different preprocessor definition for
FMT_HEADER_ONLY
is needed. - There is no
location
field provided.
In a file called fmt.cps
:
{
"cps_version": "0.11.0",
"name": "fmt",
"description": "An open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams.",
"license": "MIT",
"version": "10.2.1",
"default_components": [ ":shared" ],
"components": {
"shared": {
"type": "dylib",
"definitions": {"*": {"FMT_HEADER_ONLY": "0"}},
"requires": [],
"includes": "@prefix@/include",
"location": "@prefix@/lib64/libfmt.so"
},
"static": {
"type": "archive",
"definitions": {"*": {"FMT_HEADER_ONLY": "0"}},
"requires": [],
"includes": "@prefix@/include",
"location": "@prefix@/lib64/libfmt.a"
}
}
}
Note:
- There are two "components", one for the static version of the library and one for the shared version.
- The shared version of the library is the default version in this arrangement, but it's possible to specify otherwise.
- See the simple static and shared examples for notes on specific fields.
- TODO: What about RUNPATH?
- TODO: Do the static and shared versions conflict?
Concepts, context, and other ways to grow understanding.
Why is CPS being developed?
See the CppCon 2023 talk called Libraries: A First Step Toward Standard C++ Dependency Management by Bill Hoffman and Bret Brown to understand the motivation and goals for CPS.
In short, CPS attempts to be a metadata file format to allow better interoperability across the build systems of different projects. It's important to have specific interfaces and protocols for how projects cooperate because natively compiled languages do have nuanced requirements regarding how they are linked together. Certain decisions, as detailed as specific flags used to compile specific files, need to be communicated and followed consistently for correct and productive software development in natively compiled languages. Implications of these difficulties have been far-reaching and have held back innovation and progress in tooling, dependency management, and even a development of a robust library ecosystem.
Historically, dependency management for natively compiled languages has been painstaking and bug-prone, but CPS hopes to provide a path forward.
What do I need to know about writing CPS files?
Mostly, you won't write CPS files. It is expected that build systems will be able to be much more precise, consistent, and efficient about providing this metadata. It is recommended that projects work with the maintainers of their build systems to provide seamless CPS support.
When CPS is fully adopted, it should mostly be use to allow various tools talk about dependency graphs with one another, especially different build environments and build systems. This will be analogous to how debug information is used to allow compilers and debuggers to share information about compiled binaries. Most users do not need to understand how this debug information is encoded, though it is helpful to know it exists and how to ensure it is provided as appropriate.
That being said, there will be situations where project maintainers may need to author a CPS file, so further documentation is available here to help people learn about constructing CPS files in more detail.
If you're ensuring your packages have good CPS files or implementing CPS support in a build system, you will need to understand CPS files in more detail.
Most CPS files will be simple. The first examples in the CPS Cookbook should be the most common examples, especially as the CPS ecosystem develops.
The primary purpose of a CPS file is to provide a defined schema for describing intention of the original authors and packagers of a library. The files should objectively describe the library as deployed. This will primarily consist of describing built files on disk, how they were built, what headers they provide, and what dependencies that library exposes to consumers.
While there are worse and better ways to build and package libraries, CPS exists partly to describe even mistakes accurately. For instance, it is possible to construct a cyclic dependency graph with CPS. It is wise to avoid cyclic library dependencies, but the CPS project values adaptability of its metadata over perfection. It is expected that tools will develop to help clearly identify problems such as cycles in dependency graphs because CPS data will exist to make that activity possible.
Facts, specifics, and other information
Reference documentation for CPS is maintained in the CPS specification. Since precision and review are important to maintaining a specification, those documents are maintained using a more structured pull request workflow. Please use PRs and issues on the CPS repo itself to contribute to the CPS specification.
It can be challenging to write documentation that serves all purposes for all readers. The documentation for CPS is instead structured into the documentation system described by Divio. It's expected that approach will be more approachable both for readers and for contributors to the documentation. If you have ideas, questions, or concerns, please open an issue on this repo describing what you expected and what happened instead.