Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
command: |
cd build-cmake
ctest --output-junit results.xml --verbose -j4
cd ../hello_world_graph && ././hello_world_graph_test.sh
- store_test_results:
path: build-cmake

Expand Down
7 changes: 7 additions & 0 deletions hello_world_graph/hello.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// a simple test program to print "Hello World"
#include <iostream>

int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
1 change: 1 addition & 0 deletions hello_world_graph/hello_world_graph_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
../build-cmake/ninja hello && test "$(./hello)" = "Hello, World!"
74 changes: 74 additions & 0 deletions shadowdash_docs/hello_world_graph_docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Hello World Graph Documentation

This document provides an overview of the updates to the **Hello World Graph** task in the Shadowdash project, including its structure, new content, and instructions on how to run it.

---

## **Overview**

The `Hello World Graph` demonstrates a basic usage of Ninja's build system by introducing a simple graph structure that compiles and links a "Hello, World!" program. The primary updates in this task include:

1. **Build Graph Definition**:
- A minimal build graph is defined using two custom rules: `compile` and `link`.
- Each rule is implemented as part of the Ninja state with inputs and outputs linked together.

2. **Rules and Edges**:
- **Compile Rule**: Uses `g++` to compile `hello.cc` into `hello.o`.
- **Link Rule**: Links `hello.o` to produce the executable `hello`.

3. **Integration**:
- The graph integrates seamlessly into the Ninja-based build system, leveraging Ninja's structure and performance.

---

## **Key Components**

### 1. **Rules**

- **Compile Rule**: Defines how the source file (`hello.cc`) is compiled:
```plaintext
g++ -c hello.cc -o hello.o

- **Link Rule**: Defines how the object file (hello.o) is linked to produce the executable:
```plaintext
g++ hello.o -o hello

### 2. **Edges**

The edges connect the rules, defining the dependencies:
- `hello.cc` → [Compile Rule] → `hello.o`
- `hello.o` → [Link Rule] → `hello`

---

## **How to Run**

1. **Prerequisites**:
- Ensure you have `g++` installed on your system.
- Ninja is required to run the build graph.

2. **Steps to Build and Run**:
- Navigate to the project root directory:
```bash
cd shadowdash
```
- Run the `hello` target using the Ninja build system:
```bash
./build-cmake/ninja hello
```
- Upon successful execution, you will see the compiled `hello` executable. Run it to verify the output:
```bash
./hello
```
- Expected Output:
```plaintext
Hello, World!
```

---

## **File Structure**

- `hello_world_graph/hello.cc`: The "Hello, World!" source file.
- `build-cmake/ninja`: The Ninja executable for building the project.
- Custom rules and graph logic are embedded in the build system to demonstrate the flow.
66 changes: 66 additions & 0 deletions src/ninja.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1616,9 +1616,75 @@ NORETURN void real_main(int argc, char** argv) {
exit(1);
}

// routine to compile the example hello.cc by manually
// constructing the graph
void compile_hello(int argc, char** argv) {
// ninja initialization
const char* ninja_command = argv[0];
BuildConfig config;
Options options = {};

int exit_code = ReadFlags(&argc, &argv, &options, &config);
if (exit_code >= 0)
exit(exit_code);

Status* status = Status::factory(config);

NinjaMain ninja(ninja_command, config);

string* err;

// start building hello world graph

// create a compile rule
Rule* rule_compile = new Rule("compile");
EvalString value1;
value1.AddText("g++ -c ");
value1.AddSpecial("in");
value1.AddText(" -o ");
value1.AddSpecial("out");
rule_compile->AddBinding("command", value1);

// create a link rule
Rule* rule_link = new Rule("link");
EvalString value2;
value2.AddText("g++ ");
value2.AddSpecial("in");
value2.AddText(" -o ");
value2.AddSpecial("out");
rule_link->AddBinding("command", value2);

// add build from hello.cc to hello.o
Edge* edge_compile = ninja.state_.AddEdge(rule_compile);

ninja.state_.AddOut(edge_compile, "hello.o", 0, err);
ninja.state_.AddIn(edge_compile, "hello.cc", 0);

// add build from hello.o to hello
Edge* edge_link = ninja.state_.AddEdge(rule_link);

ninja.state_.AddOut(edge_link, "hello", 0, err);
ninja.state_.AddIn(edge_link, "hello.o", 0);

// feed to ninja and run the build
int result = ninja.RunBuild(argc, argv, status);
exit(result);
}

} // anonymous namespace

int main(int argc, char** argv) {
// add a branch to run our hello world program
// compilation routine. We can cleanly seperate
// this in another file and generate a dedicated
// executable to compile hello.cc, but we believe
// this does not worth the effort since this task
// is more like an experiment
if(argc == 2 && !strcmp(argv[1], "hello"))
{
compile_hello(argc, argv);
return 0;
}
#if defined(_MSC_VER)
// Set a handler to catch crashes not caught by the __try..__except
// block (e.g. an exception in a stack-unwind-block).
Expand Down