Skip to content
Merged
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
105 changes: 99 additions & 6 deletions content/learning-paths/cross-platform/matrix/1-foundations.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ Emacs](https://www.gnu.org/software/emacs/), or [Sublime
Text](https://www.sublimetext.com/), which are also popular and they all
support extensions that make C++ development easy.

## Source code

In case you want to, you can [download the source code](https://gitlab.arm.com/learning-code-examples/code-examples/-/archive/main/code-examples-main.tar.gz?path=learning-paths/cross-platform/matrix) for this learning path. This will download a `.tar.gz` archive that you will need to expand:

```BASH
tar xfz code-examples-main-learning-paths-cross-platform-matrix.tar.gz
mv code-examples-main-learning-paths-cross-platform-matrix code-examples
```

The source code for this learning path will be available in `code-examples/learning-paths/cross-platform/matrix/`.

## What are the differences between configuring the project and building the code?

Expand Down Expand Up @@ -64,7 +74,7 @@ projects like [LLVM](https://www.llvm.org) or [Qt](https://www.qt.io/).

Organizing the files in a project is important because it allows you to:

- Easily navigate the structure and find information.
- Easily navigate the structure and find information.
- Organize information for the tools, such as compilers and linkers.
- Make a distinction between information that is exported or installed, and what is
only relevant for building the project.
Expand Down Expand Up @@ -117,7 +127,18 @@ There is nothing like creating the canonical `Hello, World!` application!
Use your favorite text editor or IDE to
create the file `src/howdy.cpp` and add the following content:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-1/src/howdy.cpp" >}}
```CPP
#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char *argv[]) {
cout << "Hello, World !\n";

return EXIT_SUCCESS;
}
```

## Setup CMake

Expand Down Expand Up @@ -226,21 +247,89 @@ library version.
Add the `Matrix.h` header file, declaring the `Version` object
and the `getVersion` function and save the file as `include/Matrix/Matrix.h`:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-1/include/Matrix/Matrix.h" >}}
```CPP
#pragma once

namespace MatComp {

/// The Version struct is used to carry around the major, minor and patch level.
struct Version {
unsigned major; //< The major version level.
unsigned minor; //< The minor version level.
unsigned patch; //< The patch level.
};

/// Get the Matrix library version information.
const Version &getVersion();

} // namespace MatComp
```

With those declarations in place, create and add the following lines to
`lib/Matrix/Matrix.cpp` to provide an implementation to `getVersion`:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-1/lib/Matrix/Matrix.cpp" >}}
```CPP
#include "Matrix/Matrix.h"

namespace {
const MatComp::Version version = {.major = 0, .minor = 1, .patch = 0};
}

namespace MatComp {

const Version &getVersion() { return version; }

} // namespace MatComp
```

Now, you can create a program that will make use of the
``getVersion`` function. Use your editor to save the code below as `src/getVersion.cpp`:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-1/src/getVersion.cpp" >}}
```CPP
#include "Matrix/Matrix.h"

#include <cstdlib>
#include <iostream>

using namespace std;
using namespace MatComp;

int main(int argc, char *argv[]) {
const Version &version = getVersion();
cout << "Using Matrix version: " << version.major << '.' << version.minor
<< '.' << version.patch << '\n';

return EXIT_SUCCESS;
}
```

Finally, add the instructions below in the top-level `CMakeLists.txt`:

{{< include-code TXT "content/learning-paths/cross-platform/matrix/projects/chapter-1/CMakeLists.txt" >}}
```TXT
# Set the minimum CMake version we require. In our case, it is intentionnally
# very old as we are not making use of recent CMake features.
cmake_minimum_required(VERSION 3.5)

# Give a name to our project ('Matrix') and inform CMake about the language used.
project(Matrix LANGUAGES CXX)

# Add 'howdy', a standalone executable with no dependency to any library that
# has to be built from the sources in 'src/howdy.cpp'.
add_executable(howdy src/howdy.cpp)

# Add our 'Matrix' library, that is built as a static library, from source file
# 'lib/Matrix/Matrix.cpp'. CMake is instruction that C++17 is used, and that
# the library headers can be found in ${CMAKE_SOURCE_DIR}/include.
add_library(Matrix STATIC lib/Matrix/Matrix.cpp)
target_compile_features(Matrix PUBLIC cxx_std_17)
target_include_directories(Matrix
PUBLIC ${CMAKE_SOURCE_DIR}/include)

# Add 'matrix-getVersion', an executable that depends on the Matrix library,
# that has to be built from source file 'src/getVersion.cpp'.
add_executable(matrix-getVersion src/getVersion.cpp)
target_link_libraries(matrix-getVersion Matrix)
```

The `add_library` instructs CMake how to build the Matrix library. The
`target_include_directories` specifies where the Matrix library header is located, and the `target_compile_features` specifies that C++17 is the version
Expand Down Expand Up @@ -301,3 +390,7 @@ For example, Visual Studio Code can work seamlessly with CMake with plugins, and
generate project files for several popular IDEs, such as Xcode, Sublime Text, Eclipse,
CodeBlocks, and CodeLite. You can run `cmake --help` to get a
list of supported *generators* (in CMake terminology) for your platform.

You can refer to this chapter source code in
`code-examples/learning-paths/cross-platform/matrix/chapter-1` in the archive that
you have downloaded earlier.
65 changes: 61 additions & 4 deletions content/learning-paths/cross-platform/matrix/2-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ benefits:
- They offer an opportunity to catch regressions.
- They demonstrate how to use the library in practice.
- They create opportunities for those new to the project to easily check their patches, and verify that the introduction of the new code has not created unintended negative changes.

You will notice that setting up testing precedes library code development.

There are many unit testing frameworks available, and C++ is not short of them. See this [wikipedia
Expand All @@ -38,7 +38,38 @@ all external dependencies. It will be used by the main `CMakeLists.txt`.

Create the file `external/CMakeLists.txt` with the following content:

{{< include-code TXT "content/learning-paths/cross-platform/matrix/projects/chapter-2/external/CMakeLists.txt" >}}
```TXT
cmake_minimum_required(VERSION 3.6)

project(external LANGUAGES CXX)

# Get the functionality to configure, build and install external project
# from CMake module 'ExternalProject'.
include(ExternalProject)

# Use the same compiler, build type and instalation directory than those
# from our caller.
set(EXTERNAL_PROJECT_CMAKE_ARGS
-DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER}
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX})

# Add 'googletext' as an external project, that will be cloned with git,
# from the official googletest repository, at version v1.14.
# We ask for a shallow clone, which is a clone with only the revision
# we are interested in rather than googletest's full history ---
# this makes the clone much faster (less data traffic), and uses much
# less disk space ; furthermore, as we are not developping googletest
# but just merely using it, we don't need thre full history. It will be
# built and installed with our build configuration passed with CMAKE_ARGS.
ExternalProject_Add(googletest
PREFIX "external"
GIT_REPOSITORY "https://github.com/google/googletest"
GIT_TAG "v1.14.0"
GIT_SHALLOW TRUE
CMAKE_ARGS ${EXTERNAL_PROJECT_CMAKE_ARGS}
)
```

You might notice a new CMake feature: variables. Variables start with the `$` character and have a name inserted between curly braces. A CMake variable can be set by the CMake itself, or by the user, and they can be modified or used as they are.

Expand Down Expand Up @@ -235,11 +266,33 @@ several files inside the `tests/` directory.

Create the top-level test in `tests/main.cpp` and paste the following code into the file:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-2/tests/main.cpp" >}}
```CPP
#include "gtest/gtest.h"

using namespace testing;

int main(int argc, char **argv) {
InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
```

Create `tests/Version.cpp` and add the `getVersion` unit test into the file:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-2/tests/Version.cpp" >}}
```CPP
#include "Matrix/Matrix.h"

#include "gtest/gtest.h"

using namespace MatComp;

TEST(Matrix, getVersion) {
const Version &version = getVersion();
EXPECT_EQ(version.major, 0);
EXPECT_EQ(version.minor, 1);
EXPECT_EQ(version.patch, 0);
}
```

This test invokes `getVersion` and checks that the `major`, `minor` and `patch` levels match the expected values.

Expand Down Expand Up @@ -325,3 +378,7 @@ Matrix/
CMake makes it easy to use GoogleTest as an external project. Adding unit tests as you go is now easy.

You have created the unit testing environment for your Matrix library and added a test. The infrastructure is now in place to implement the core of the Matrix processing library.

You can refer to this chapter source code in
`code-examples/learning-paths/cross-platform/matrix/chapter-2` in the archive that
you have downloaded earlier.
27 changes: 26 additions & 1 deletion content/learning-paths/cross-platform/matrix/3-code-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,28 @@ Open `lib/Matrix/Matrix.cpp` and include at the top of the file:

Add `die`'s body as shown below:

{{< include-code CPP "content/learning-paths/cross-platform/matrix/projects/chapter-3/lib/Matrix/Matrix.cpp" >}}
```CPP
#include "Matrix/Matrix.h"

#include <cstdlib>
#include <iostream>

namespace {
const MatComp::Version version = {.major = 0, .minor = 1, .patch = 0};
}

namespace MatComp {

const Version &getVersion() { return version; }

void die(const char *fileName, size_t lineNumber, const char *reason) {
std::cerr << "Fatal: " << reason << " from " << fileName << ':'
<< lineNumber << '\n';
exit(EXIT_FAILURE);
}

} // namespace MatComp
```

At this stage, the project should still build and compile, try it to confirm:

Expand Down Expand Up @@ -1045,3 +1066,7 @@ After this rather long exercise, you have a minimalistic, yet fully-functional c
Modern C++ enables you to express move and copy semantics, and to use smart pointers to make memory management easy.

The compiler also catch a large number of type or misuse errors. With this core functionality in place, you have all you need to implement matrix operations in the next section.

You can refer to this chapter source code in
`code-examples/learning-paths/cross-platform/matrix/chapter-3` in the archive that
you have downloaded earlier.
4 changes: 4 additions & 0 deletions content/learning-paths/cross-platform/matrix/4-code-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -1150,3 +1150,7 @@ built and used.
The testing could - and *should* - go much deeper, as a number of corner cases have not been covered.

You can continue to add more functions, and more tests.

You can refer to this chapter source code in
`code-examples/learning-paths/cross-platform/matrix/chapter-4` in the archive that
you have downloaded earlier.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading