summaryrefslogtreecommitdiff
path: root/doc/tutorial/hello-world.org
diff options
context:
space:
mode:
Diffstat (limited to 'doc/tutorial/hello-world.org')
-rw-r--r--doc/tutorial/hello-world.org370
1 files changed, 0 insertions, 370 deletions
diff --git a/doc/tutorial/hello-world.org b/doc/tutorial/hello-world.org
deleted file mode 100644
index 342eaf82..00000000
--- a/doc/tutorial/hello-world.org
+++ /dev/null
@@ -1,370 +0,0 @@
-* Building C++ Hello World
-
-/justbuild/ is a true language-agnostic (there are no more-equal languages) and
-multi-repository build system. As a consequence, high-level concepts (e.g., C++
-binaries, C++ libraries, etc.) are not hardcoded built-ins of the tool, but
-rather provided via a set of rules. These rules can be specified as a true
-dependency to your project like any other external repository your project might
-depend on.
-
-** Setting up the Multi-Repository Configuration
-
-To build a project with multi-repository dependencies, we first need to provide
-a configuration that declares the required repositories. Before we begin, we
-need to declare where the root of our workspace is located by creating an empty
-file ~ROOT~:
-
-#+BEGIN_SRC sh
-$ touch ROOT
-#+END_SRC
-
-Second, we also need to create the multi-repository configuration ~repos.json~
-in the workspace root:
-
-#+SRCNAME: repos.json
-#+BEGIN_SRC js
-{ "main": "tutorial"
-, "repositories":
- { "rules-cc":
- { "repository":
- { "type": "git"
- , "branch": "master"
- , "commit": "123d8b03bf2440052626151c14c54abce2726e6f"
- , "repository": "https://github.com/just-buildsystem/rules-cc.git"
- , "subdir": "rules"
- }
- }
- , "tutorial":
- { "repository": {"type": "file", "path": "."}
- , "bindings": {"rules": "rules-cc"}
- }
- }
-}
-#+END_SRC
-
-In that configuration, two repositories are defined:
-
- 1. The ~"rules-cc"~ repository located in the subdirectory ~rules~ of
- [[https://github.com/just-buildsystem/rules-cc/tree/123d8b03bf2440052626151c14c54abce2726e6f][just-buildsystem/rules-cc:123d8b03bf2440052626151c14c54abce2726e6f]],
- which contains the high-level concepts for building C/C++ binaries and
- libraries.
-
- 2. The ~"tutorial"~ repository located at ~.~, which contains the targets that
- we want to build. It has a single dependency, which is the /rules/ that are
- needed to build the target. These rules are bound via the open name
- ~"rules"~ to the just created repository ~"rules-cc"~. In this way, the
- entities provided by ~"rules-cc"~ can be accessed from within the
- ~"tutorial"~ repository via the fully-qualified name
- ~["@", "rules", "<module>", "<name>"]~; fully-qualified
- names (for rules, targets to build (like libraries, binaries),
- etc) are given by a repository name, a path specifying a
- directory within that repository (the "module") where the
- specification file is located, and a symbolic name (i.e., an
- arbitrary string that is used as key in the specification).
-
-The final repository configuration contains a single ~JSON~ object with the key
-~"repositories"~ referring to an object of repository names as keys and
-repository descriptions as values. For convenience, the main repository to pick
-is set to ~"tutorial"~.
-
-** Description of the helloworld target
-
-For this tutorial, we want to create a target ~helloworld~ that produces a
-binary from the C++ source ~main.cpp~. To define such a target, create a
-~TARGETS~ file with the following content:
-
-#+SRCNAME: TARGETS
-#+BEGIN_SRC js
-{ "helloworld":
- { "type": ["@", "rules", "CC", "binary"]
- , "name": ["helloworld"]
- , "srcs": ["main.cpp"]
- }
-}
-#+END_SRC
-
-The ~"type"~ field refers to the rule ~"binary"~ from the module ~"CC"~ of the
-~"rules"~ repository. This rule additionally requires the string field ~"name"~,
-which specifies the name of the binary to produce; as the generic interface of
-rules is to have fields either take a list of strings or a list of targets,
-we have to specify the name as a list (this rule will simply concatenate all
-strings given in this field). Furthermore, at least one
-input to the binary is required, which can be specified via the target fields
-~"srcs"~ or ~"deps"~. In our case, the former is used, which contains our single
-source file (files are considered targets).
-
-Now, the last file that is missing is the actual source file ~main.cpp~:
-
-#+SRCNAME: main.cpp
-#+BEGIN_SRC cpp
-#include <iostream>
-
-int main() {
- std::cout << "Hello world!\n";
- return 0;
-}
-#+END_SRC
-
-** Building the helloworld target
-
-To build the ~helloworld~ target, we need specify it on the ~just-mr~ command
-line:
-
-#+BEGIN_SRC sh
-$ just-mr build helloworld
-INFO: Requested target is [["@","tutorial","","helloworld"],{}]
-INFO: Analysed target [["@","tutorial","",helloworld"],{}]
-INFO: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
-INFO: Discovered 2 actions, 1 trees, 0 blobs
-INFO: Building [["@","helloworld","","helloworld"],{}].
-INFO: Processed 2 actions, 0 cache hits.
-INFO: Artifacts built, logical paths are:
- helloworld [b5cfca8b810adc4686f5cac00258a137c5d4a3ba:17088:x]
-$
-#+END_SRC
-
-Note that the target is taken from the ~tutorial~ repository, as it specified as
-the main repository in ~repos.json~. If targets from other repositories should
-be build, the repository to use must be specified via the ~--main~ option.
-
-~just-mr~ reads the repository configuration, fetches externals (if any),
-generates the actual build configuration, and stores it in its cache directory
-(by default under ~$HOME/.cache/just~). Afterwards, the generated configuration
-is used to call the ~just~ binary, which performs the actual build.
-
-Note that these two programs, ~just-mr~ and ~just~, can also be run
-individually. To do so, first run ~just-mr~ with ~setup~ and capture the path to
-the generated build configuration from stdout by assigning it to a shell
-variable (e.g., ~CONF~). Afterwards, ~just~ can be called to perform the actual
-build by explicitly specifying the configuration file via ~-C~:
-
-#+BEGIN_SRC sh
-$ CONF=$(just-mr setup tutorial)
-$ just build -C $CONF helloworld
-#+END_SRC
-
-Note that ~just-mr~ only needs to be run the very first time and only once again
-whenever the ~repos.json~ file is modified.
-
-By default, the BSD-default compiler front-ends (which are also defined for most
-Linux distributions) ~cc~ and ~c++~ are used for C and C++ (variables ~"CC"~ and
-~"CXX"~). If you want to temporarily use different defaults, you can use ~-D~ to
-provide a JSON object that sets different default variables. For instance, to
-use Clang as C++ compiler for a single build invocation, you can use the
-following command to provide an object that sets ~"CXX"~ to ~"clang++"~:
-
-#+BEGIN_SRC sh
-$ just-mr build helloworld -D'{"CXX":"clang++"}'
-INFO: Requested target is [["@","tutorial","","helloworld"],{"CXX":"clang++"}]
-INFO: Analysed target [["@","tutorial","","helloworld"],{"CXX":"clang++"}]
-INFO: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
-INFO: Discovered 2 actions, 1 trees, 0 blobs
-INFO: Building [["@","tutorial","","helloworld"],{"CXX":"clang++"}].
-INFO: Processed 2 actions, 0 cache hits.
-INFO: Artifacts built, logical paths are:
- helloworld [b8cf7b8579d9dc7172b61660139e2c14521cedae:16944:x]
-$
-#+END_SRC
-
-** Defining project defaults
-
-To define a custom set of defaults (toolchain and compile flags) for your
-project, you need to create a separate file root for providing required
-~TARGETS~ file, which contains the ~"defaults"~ target that should be used by
-the rules. This file root is then used as the /target root/ for the rules, i.e.,
-the search path for ~TARGETS~ files. In this way, the description of the
-~"defaults"~ target is provided in a separate file root, to keep the rules
-repository independent of these definitions.
-
-We will call the new file root ~tutorial-defaults~ and need to create a module
-directory ~CC~ in it:
-
-#+BEGIN_SRC sh
-$ mkdir -p ./tutorial-defaults/CC
-#+END_SRC
-
-In that module, we need to create the file ~tutorial-defaults/CC/TARGETS~ that
-contains the target ~"defaults"~ and specifies which toolchain and compile flags
-to use; it has to specify the complete toolchain, but can specify a ~"base"~
-toolchain to inherit from. In our case, we don't use any base, but specify all
-the required fields directly.
-
-#+SRCNAME: tutorial-defaults/CC/TARGETS
-#+BEGIN_SRC js
-{ "defaults":
- { "type": ["CC", "defaults"]
- , "CC": ["cc"]
- , "CXX": ["c++"]
- , "CFLAGS": ["-O2", "-Wall"]
- , "CXXFLAGS": ["-O2", "-Wall"]
- , "AR": ["ar"]
- , "PATH": ["/bin", "/usr/bin"]
- }
-}
-#+END_SRC
-
-To use the project defaults, modify the existing ~repos.json~ to reflect the
-following content:
-
-#+SRCNAME: repos.json
-#+BEGIN_SRC js
-{ "main": "tutorial"
-, "repositories":
- { "rules-cc":
- { "repository":
- { "type": "git"
- , "branch": "master"
- , "commit": "123d8b03bf2440052626151c14c54abce2726e6f"
- , "repository": "https://github.com/just-buildsystem/rules-cc.git"
- , "subdir": "rules"
- }
- , "target_root": "tutorial-defaults"
- , "rule_root": "rules-cc"
- }
- , "tutorial":
- { "repository": {"type": "file", "path": "."}
- , "bindings": {"rules": "rules-cc"}
- }
- , "tutorial-defaults":
- { "repository": {"type": "file", "path": "./tutorial-defaults"}
- }
- }
-}
-#+END_SRC
-
-Note that the ~"defaults"~ target uses the rule ~["CC", "defaults"]~ without
-specifying any external repository (e.g., ~["@", "rules", ...]~). This is
-because ~"tutorial-defaults"~ is not a full-fledged repository but merely a file
-root that is considered local to the ~"rules-cc"~ repository. In fact, the
-~"rules-cc"~ repository cannot refer to any external repository as it does not
-have any defined bindings.
-
-To rebuild the project, we need to rerun ~just-mr~ (note that due to
-configuration changes, rerunning only ~just~ would not suffice):
-
-#+BEGIN_SRC sh
-$ just-mr build helloworld
-INFO: Requested target is [["@","tutorial","","helloworld"],{}]
-INFO: Analysed target [["@","tutorial","","helloworld"],{}]
-INFO: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
-INFO: Discovered 2 actions, 1 trees, 0 blobs
-INFO: Building [["@","tutorial","","helloworld"],{}].
-INFO: Processed 2 actions, 0 cache hits.
-INFO: Artifacts built, logical paths are:
- helloworld [487dc9e47b978877ed2f7d80b3395ce84b23be92:16992:x]
-$
-#+END_SRC
-
-Note that the output binary may have changed due to different defaults.
-
-** Modeling target dependencies
-
-For demonstration purposes, we will separate the print statements into a static
-library ~greet~, which will become a dependency to our binary. Therefore, we
-create a new subdirectory ~greet~ with the files ~greet/greet.hpp~:
-
-#+SRCNAME: greet/greet.hpp
-#+BEGIN_SRC cpp
-#include <string>
-
-void greet(std::string const& s);
-#+END_SRC
-
-and ~greet/greet.cpp~:
-
-#+SRCNAME: greet/greet.cpp
-#+BEGIN_SRC cpp
-#include "greet.hpp"
-#include <iostream>
-
-void greet(std::string const& s) {
- std::cout << "Hello " << s << "!\n";
-}
-#+END_SRC
-
-These files can now be used to create a static library ~libgreet.a~. To do so,
-we need to create the following target description in ~greet/TARGETS~:
-
-#+SRCNAME: greet/TARGETS
-#+BEGIN_SRC js
-{ "greet":
- { "type": ["@", "rules", "CC", "library"]
- , "name": ["greet"]
- , "hdrs": ["greet.hpp"]
- , "srcs": ["greet.cpp"]
- , "stage": ["greet"]
- }
-}
-#+END_SRC
-
-Similar to ~"binary"~, we have to provide a name and source file. Additionally,
-a library has public headers defined via ~"hdrs"~ and an optional staging
-directory ~"stage"~ (default value ~"."~). The staging directory specifies where
-the consumer of this library can expect to find the library's artifacts. Note
-that this does not need to reflect the location on the file system (i.e., a
-full-qualified path like ~["com", "example", "utils", "greet"]~ could be used to
-distinguish it from greeting libraries of other projects). The staging directory
-does not only affect the main artifact ~libgreet.a~ but also it's /runfiles/,
-a second set of artifacts, usually those a consumer needs to make proper use the
-actual artifact; in the case of a library, the runfiles are its public headers.
-Hence, the public header will be staged to ~"greet/greet.hpp"~. With that
-knowledge, we can now perform the necessary modifications to ~main.cpp~:
-
-#+SRCNAME: main.cpp
-#+BEGIN_SRC cpp
-#include "greet/greet.hpp"
-
-int main() {
- greet("Universe");
- return 0;
-}
-#+END_SRC
-
-The target ~"helloworld"~ will have a direct dependency to the target ~"greet"~
-of the module ~"greet"~ in the top-level ~TARGETS~ file:
-
-#+SRCNAME: TARGETS
-#+BEGIN_SRC js
-{ "helloworld":
- { "type": ["@", "rules", "CC", "binary"]
- , "name": ["helloworld"]
- , "srcs": ["main.cpp"]
- , "private-deps": [["greet", "greet"]]
- }
-}
-#+END_SRC
-
-Note that there is no need to explicitly specify ~"greet"~'s public headers here
-as the appropriate artifacts of dependencies are automatically added to the
-inputs of compile and link actions. The new binary can be built with the same
-command as before (no need to rerun ~just-mr~):
-
-#+BEGIN_SRC sh
-$ just-mr build helloworld
-INFO: Requested target is [["@","tutorial","","helloworld"],{}]
-INFO: Analysed target [["@","tutorial","","helloworld"],{}]
-INFO: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
-INFO: Discovered 4 actions, 2 trees, 0 blobs
-INFO: Building [["@","tutorial","","helloworld"],{}].
-INFO: Processed 4 actions, 0 cache hits.
-INFO: Artifacts built, logical paths are:
- helloworld [2b81e3177afc382452a2df9f294d3df90a9ccaf0:17664:x]
-$
-#+END_SRC
-
-To only build the static library target ~"greet"~ from module ~"greet"~, run the
-following command:
-
-#+BEGIN_SRC sh
-$ just-mr build greet greet
-INFO: Requested target is [["@","tutorial","greet","greet"],{}]
-INFO: Analysed target [["@","tutorial","greet","greet"],{}]
-INFO: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
-INFO: Discovered 2 actions, 1 trees, 0 blobs
-INFO: Building [["@","tutorial","greet","greet"],{}].
-INFO: Processed 2 actions, 2 cache hits.
-INFO: Artifacts built, logical paths are:
- greet/libgreet.a [83ed406e21f285337b0c9bd5011f56f656bba683:2992:f]
- (1 runfiles omitted.)
-$
-#+END_SRC