- Overview
- Tutorials
- Getting started
- Get started with Canton and the JSON Ledger API
- Get Started with Canton, the JSON Ledger API, and TypeScript
- Get started with Canton Network App Dev Quickstart
- Get started with smart contract development
- Basic contracts
- Test templates using Daml scripts
- Build the Daml Archive (.dar) file
- Data types
- Transform contracts using choices
- Add constraints to a contract
- Parties and authority
- Compose choices
- Handle exceptions
- Work with dependencies
- Functional programming 101
- The Daml standard library
- Test Daml contracts
- Next steps
- Application development
- Getting started
- Development how-tos
- Component how-tos
- Explanations
- References
- Application development
- Smart contract development
- Daml language cheat sheet
- Daml language reference
- Daml standard library
- DA.Action.State.Class
- DA.Action.State
- DA.Action
- DA.Assert
- DA.Bifunctor
- DA.Crypto.Text
- DA.Date
- DA.Either
- DA.Exception
- DA.Fail
- DA.Foldable
- DA.Functor
- DA.Internal.Interface.AnyView.Types
- DA.Internal.Interface.AnyView
- DA.List.BuiltinOrder
- DA.List.Total
- DA.List
- DA.Logic
- DA.Map
- DA.Math
- DA.Monoid
- DA.NonEmpty.Types
- DA.NonEmpty
- DA.Numeric
- DA.Optional
- DA.Record
- DA.Semigroup
- DA.Set
- DA.Stack
- DA.Text
- DA.TextMap
- DA.Time
- DA.Traversable
- DA.Tuple
- DA.Validation
- GHC.Show.Text
- GHC.Tuple.Check
- Prelude
- Smart contract upgrading reference
- Glossary of concepts
Short Makefile primer¶
Make is the original build tool developed to assist with C development on UNIX in 1976 [36]. As such it relies heavily on transparent integration with the Unix shell. To this day, Make retains the most comprehensive and seamless shell integration of any build tool available — which is why it makes a good choreography tool. The version used in this project is GNU Make [37], which has a number of useful extensions.
The basic format of a Make build target is:
.<SPECIAL-TARGET-DECLARATIONS>*: <target-name>
<target>: <dependency list (space separated)>
shell commands, make macros, and gnu-make function invocations
For instance, to build the frontend, you can run npm install && npm run build from the frontend/ directory, or make build-frontend from the quickstart/ directory via the following target in quickstart/Makefile:
.PHONY: build-frontend
build-frontend: ## Build the frontend application
@cd frontend && npm install && npm run build
.PHONY is a special built-in target used to indicate that build-frontend is strictly a target name and does not correspond to a file [38].
build-frontend: Is a build target that can be invoked directly via make <target> or indirectly as a dependency for another target. If not marked as a phony-target it is treated as a file, and the last-modified timestamp compared to its dependencies in the usual manner.
# is a line comment delimiter, identical to a shell script.
## is not a Make concept, but is used by convention as a doc-string to generate the usage displayed by make help.
<tab>@cd frontend && npm install && npm run build is a shell command to be executed when the target is invoked. Unless this is a phony-target, Make expects this command to regenerate the target file. By default, Make prints each shell command to stdout immediately before it executes it; this is suppressed if the command is prepended with a @.
NOTE: The shell-command MUST be indented by a literal TAB character, the equivalent number of spaces WILL NOT WORK.
You can see dependency list in action with the top-level build target:
.PHONY: build
build: build-frontend build-backend build-daml build-docker-images
When the target is invoked, the dependency targets are run and brought up to date (or invoked in the case of phony targets) before any shell command is executed.
Other Make features used in the existing file include:
define [39] which is used to define multiline variables. In this case, we use it to define a simple macro (open-url-target) to define cross-platform browser interaction targets (try make open-app-ui once the application is started for an example). The file also includes:
# Function to run docker-compose with default files and environment
define docker-compose
docker compose $(DOCKER_COMPOSE_FILES) $(DOCKER_COMPOSE_ENVFILE) \
$(DOCKER_COMPOSE_PROFILES) $(1)
endef
This provides DRY abstraction around calls to docker-compose.
call [40] which is used to invoke a variable as a function.
Note that the format of a call invocation is: $(call <cmd>[, <args>]*). So $(call open-url-target, open-app-ui, http://localhost:3000) calls open-url-target with $(1) set to the string open-app-ui and $(2) set to the URL.
Similarly, the make status target uses $(call docker-compose, ps) to run docker-compose ps with the default arguments. This happens via the docker-compose function discussed above. Removing the @ allows you to see the expanded command.
√ % make status
docker compose -f compose.yaml --env-file .env --profile localnet \
--env-file docker/localnet.env --profile observability ps
eval [41] which is used to treat the result of calling open-url-target as a macro to define dynamic make targets.