# HG changeset patch # User Malcolm # Date 1738996429 -3600 # Sat Feb 08 07:33:49 2025 +0100 # Node ID aa13f664a945a9ab45d8fe706c04d0a8b2a135c1 # Parent 01107993a1e77bbd44f4c8ed0c77ad8931513f3e FIX Install target diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -1,1 +1,871 @@ -[![builds.sr.ht status](https://builds.sr.ht/~mmatalka/pds.svg)](https://builds.sr.ht/~mmatalka/pds?) +-[![builds.sr.ht status](https://builds.sr.ht/~mmatalka/pds.svg)](https://builds.sr.ht/~mmatalka/pds?) + +# Table of Contents + +1. [About](#org4d407a9) + 1. [Why Does This Exist?](#orgf2359bb) +2. [Parallelism](#org8802aa0) +3. [Content Hash Based Builds](#org1910cf1) +4. [Terminology](#org6d61324) +5. [Projects](#orgac41c0a) + 1. [Ocaml](#org764fbf3) + 2. [Third-party](#orgeb67f29) +6. [Dependencies](#orgbfc8789) +7. [Configuration](#org0d142cb) + 1. [Configuration Variables For Projects](#org3e4424f) + 2. [Configuration Variables For Tests](#orgc22df3d) + 3. [Outputting the configuration](#orgd51a282) +8. [Produced Files](#org531c6d6) +9. [Documentation](#orga80a0b5) +10. [Selectors](#org1380185) +11. [Changelog](#org4d29c9b) + 1. [1.0.0](#org9e91524) + 2. [1.1.0](#orgb820221) + 3. [2.0.0](#orgc62cbaa) + 4. [3.0.0](#org84e93aa) + 5. [3.0.1](#org094f8fc) + 6. [3.0.2](#org32f6532) + 7. [3.0.3](#org1840326) + 8. [3.0.4](#org92f6fe6) + 9. [3.1.0](#org59d8cf0) + 10. [3.1.1](#orgf69fc75) + 11. [4.11](#org93a61f8) + 12. [4.12](#org88484a8) + 13. [4.13](#org5e6c3d1) + 14. [5.14](#org015dacc) + 15. [5.15](#orgdd7d38b) + 16. [5.16](#orgf4d3fe6) + 17. [5.17 (bug release)](#orgba9ee52) + 18. [5.18](#org47f8132) + 19. [5.19](#org55822ce) + 20. [6.20](#org00d0582) + 21. [5.21](#org992589e) + 22. [5.22](#org2a7a6fd) + 23. [5.23](#org862685f) + 24. [5.24](#orgb4ddbc1) + 25. [5.25](#orgaf4b17a) + 26. [5.26 (bug release)](#org2faefce) + 27. [5.27](#org7cf7066) + 28. [5.28](#orgb8e749f) + 29. [5.29](#org6b3e578) + 30. [6.43](#org682ad5f) + 31. [6.44](#orgfdbaa88) + + + + +# About + +pds is a build system for Ocaml that is meant to make it easy to build a project +that follows a particular layout by generating a makefile for the project. The +input to pds is a config file, `pds.conf`, and a directory structure, which is +always the current working directory, and the output is the build description. + +The directory layout looks like: + + . + /src + /proj1 + /proj2 + /proj3 + /tests + /test1/test.ml + /test2/test.ml + +The `pds.conf` for this project might look like: + + [src.proj1] + type = "exec" + deps = [ "core", "proj2", "proj3" ] + install = true + install_cmd = "cp -vf proj1.native $(PREFIX)/bin/proj1" + remove_cmd = "rm -v $(PREFIX)/bin/proj1" + + [src.proj2] + deps = [ "proj3" ] + install = false + + [src.proj3] + deps = [ "str" ] + install = false + + [tests.test1] + deps = [ "proj2" ] + + [tests.test2] + deps = [ "proj1" ] + +Finally, by using the standard `Makefile` definition below, `make test` will +compile all the code and run the tests. `make install` will install proj1. And +`make remove` will remove it. + + all: + pds + $(MAKE) -f pds.mk all + + %: + pds + $(MAKE) -f pds.mk $* + +pds supports multiple types of builds, at this time `release`, `debug`, +`profile`, and `docs`. The `release` build must always exist and is what +running `make` with no target will execute. The `debug` and `profile` builds +will inherit all configuration from the release build and options can be +overridden. pds also supports tests, and the existing test targets are: `test`, +`test-debug`, and `test-profile`, which run tests for the respective builds. + +pds builds into the `build` directory and each build type is a sub-directory in +the `build` directory, for example `build/release`, `build/docs`, or +`build/test-release`. + + + + +## Why Does This Exist? + +Ocaml has multiple build systems, so it is probably confusing and frustrating to +learn that another one has been created. In the author's experience, many of +the Ocaml build tools are more complicated than the value they add. pds is +meant to be simple but play nice with other tools. If you've felt frustrated by +the existing tooling, then pds might work well for you. If you are happy with +the existing tooling then you should be able to safely ignore pds because it +meant to be non-intrusive. + + + + +# Parallelism + +pds supports parallel builds. The amount of parallelism is specified with the +`-j` option in `make`. A repository with multiple projects in it will +parallelize the build across those projects. That is, if there is `proj1` and +`proj2` that do not depend on each other, they will be built in parallel. +Inside of an Ocaml project, if every `.ml` file in the project has an associated +`.mli` file, the project will be built in parallel. If there is any `.ml` file +that does not have a `.mli` file, the project will be built in serial. The +reason for this is when compiling a `.ml` file that does not have a `.mli` file, +both `ocamlc` and `ocamlopt` generate a `.cmi` file even if the `.cmi` file +already exists. With a parallel build, the byte code and native code builds +will be executed in parallel. If the project is built in parallel, the +generation of the `.cmi` file can overlap, generating compiler errors. This is +the source of the `units Foo and Bar make inconsistent assumptions about Baz` +error. + + + + +# Content Hash Based Builds + +pds does some trickery to build changes only if the contents have changed and +not based on timestamp. + +To accomplish this, pds stores all input files and a hash in a sqlite database +and consults this on each run. If the hash of a file is the same but its +timestamp has changed, pds sets the timestamp to the value in the database. +This tricks Make into only building things that have actually changed. + +If the hashes do not match, pds sets the timestamp to that of the current time +and stores that value in the database. + +The hash stored for every file is both the hash of the file as well as the hash +of the build configuration, this ensure that if a pds configuration has changed +that causes a rebuild. + + + + +# Terminology + +- Project - The name of a directory in the `src` directory. This corresponds to + an entry in the `src` table in the pds configuration file. +- Build - A kind of build, for example `release`, `debug`, `profile` or `docs`. +- Project type - The type of project it is, either `ocaml` or `third-party`. +- Project target type - The type of output the project has, either `exec` or + `library`, this applies only to ocaml projects.. + + + + +# Projects + +Projects are divided up between Ocaml projects, which pds knows how to generate +a `Makefile` for and a third-party project, which pds does not generate a +`Makefile` for but are expected to have one that corresponds to the pds +interface, which is `release`, `debug`, `profile`, `install`, `remove`, `docs`, +and `clean`. + + + + +## Ocaml + +Ocaml projects can be either executables or libraries. The name of the output +is derived from the project name with a suffix added depending on the type. In +the case of a library, a `META` file compatible with `ocamlfind` will be +generated. + + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Project TypeSuffix
Librarycma
Librarycmxa
Executablebyte
Executablenative
+ + + + +## Third-party + +Third party projects do not have a `Makefile` generated by pds but are expected +to have one which corresponds to the pds interface. + + + + +# Dependencies + +The configuration file input to pds specifies dependencies, if any, for each +project. If a dependency has the same name as a project in the `src` directory +then it is considered an internal dependency and an internal dependency will be +compiled before its dependent project and the emitted output will be specified +as a dependency in the dependents `Makefile`. + + + + +# Configuration + +A configuration file is required for all projects. A configuration file path +can be given explicitly or pds will search for `pds.conf` in the current working +directory. `pds.conf` is a [toml](https://github.com/toml-lang/toml) file. All directories in the `src` directory +must be in the configuration file. pds will error if that is not the case. The +only required attribute for each project is `install`, which specifies if it +will be installed or not. In the case of an `exec` project, the `install_cmd` +and `remove_cmd` are required. + +Projects and tests can have some configuration values overridden by specific +build types, the options and precedence is given in the respective sections +below. + +An example of building the example directory structure. + +- `proj3` requires no special dependencies or settings and projects are assumed + to be `library`. +- The global `release` build specifies a project should be compiled with + `-noassert`. +- The global `debug` build specifies that a project should be compiled with + `-g`. +- The project `proj2` overrides the global compiler options for `release` and + `debug` and compiles with `-safe-string`. +- The debug build options completely override the release build options. +- Libraries have a default `ocamlfind` install directory, however, commands need + to have their installation command specified. + + [global.release] + extra_compiler_opts = "-noassert" + + [global.debug] + extra_compiler_opts = "-g" + + [src.proj1] + deps = ["async", "proj2", "proj3"] + type = "exec" + install = true + install_cmd = "cp proj1.native $(PREFIX)/bin/proj1" + remove_cmd = "rm $(PREFIX)/bin/proj1" + + [src.proj2] + install = false + deps = ["core", "async"] + type = "library" + extra_compiler_opts = "-safe-string -noassert" + debug = { extra_compiler_opts = "-safe-string -g" } + + [src.proj3] + install = false + + + + +## Configuration Variables For Projects + + + + +++ ++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDefaultDescription
depsstring list[]List of dependencies both within the project and external
typestring"library"exec, library - Whether the ocaml project is an executbale or library
installbool Whether the built artifacts should be installed
installcmdstring If the type is exec, specify the command to be used to install it
removecmdstring If the typs is exec, specify the command to be used to remove it
projecttypestring"ocaml"third-party or ocaml - defaults to ocaml
extracompileroptsstring""Extra options to give to the ocaml compiler
extraocamldepoptsstring""Extra options to give ot ocamldep
extramakefilelinesstring list[]Extra lines to add to the generated Makefile
compiledepsstring list[]List of builds that need to be built prior to this build but are not automatically linked against
metalinkoptsstring""Link options to go into the META file.
buildbooltrueWhether or not to build the project or test
+ +The following values can be overridden: + +- `extra_compiler_opts` +- `extra_ocamldep_opts` +- `deps` - Note that this has no entry in `global`. +- `compile_deps` - Note that this one has no entry in `global`. + +The precedence ordering is given below. Selectors are discussed later in the +document. + +For `release` builds: + +1. `src..selector..