First Commit

This commit is contained in:
2024-12-02 15:11:30 +01:00
commit 031f6004de
4688 changed files with 441558 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
---
aliases:
- CMakeLists.txt
---
CMake is a great tool to build c++ projects across different platforms and manages all dependencies as well as how to install the project on different platforms. A great guide to modern CMake can be found [here](https://cliutils.gitlab.io/modern-cmake/). And a good example project [here](https://gitlab.com/CLIUtils/modern-cmake/-/tree/master/examples/extended-project).
It also integrates well with the [[GTest Framework|GoogleTest]] framework, which allows to define the tests in a separate folder. They are built together with the project and executed using `ctest`.
# CMake
## Nomenclature
| Definition | Meaning |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Target | Executables, libraries or custom commands that can be installed. |
| Library | A collection of code that is compiled into `lib<name>.a` or `<name>.lib` and can be used in other projects by linking to it. |
| Executable | Is a binary file that executes a certain program. On Windows usually it is `<name>.exe`. |
## How does it work?
On a high level, we want to understand what CMake does.
## Default Setup for Simple Projects
In most projects so far, we define the project, look for the needed dependencies, define our executable or library, link the dependencies and finally install it to the system.
For such a simple project the file tree looks like this:
```sh
├── CMakeLists.txt
├── include
│ └── some.h
└── src
├── some.cpp
└── things.h
```
For this a typical CMakeLists.txt file would look something like the following:
- [ ] Add all the important commands here for cmake to have a small snippet to use in the future #todo/b
```cmake
project("SomeLibrary" VERSION 0.1.0)
add_library(${PROJECT_NAME} src/some.cpp)
```
# CMake Targets
## Library
A library is a code that can be imported and used in other code and thus usually the header files that define the public classes are shared in a raw format, whereas the implementation might just be compiled into a `.so` file (or similar). Typically these files are installed into `install_path/include/library_name/...` and `install_path/lib/library_name.so`, respectively (`.so` stands for shared object). For system installs (usually invoked with `sudo make install`) the `install_path` is `/usr/local/` (if not changed manually in the cmake configuration).
A good tutorial and overview of what is needed in cmake can be found [here](https://iamsorush.com/posts/cpp-cmake-config/) or in [this very good description](https://cliutils.gitlab.io/modern-cmake/chapters/install/installing.html). As a general overview we need to do the following things:
1. add library target and all dependencies
2. make the target including specifying where it will be installed (`DESTINATION` keyword)
3. export the target to a `library_nameTargets.cmake` file (defines all cmake related stuff that I do not care about)
4. In order to actually install the library to be found by cmake we need to have 3 files:
1. `library_nameConfig.cmake`: we define it ourselves and import the next file
2. `library_nameTargets.cmake`: this is automatically written by step 3
3. `library_nameConfigVersion.cmake`: contains information about the version of the library
To do this with CMake we need to do the following in the main `CMakeLists.txt` file:
```cmake
# 1. Add library target and dependencies
add_library(library_name SHARED) # call to create a library target
target_include_directories(library_name PRIVATE "${PROJECT_SOURCE_DIR}") # tell the target where to find important include files
add_subdirectory("subdirectory_name") # add subdirectories if needed - with their own CMakeLists.txt files
# 2. Make Install target
# Finally we need to install the library
# this defines the library_nameTargets variable (because of EXPORT. Nothing is actually installed)
install(TARGETS library_name
EXPORT library_nameTargets # this file is written here and later included
FILE_SET HEADERS
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include)
# 3. Export the install target
# Now we define where the file will be installed, as well as defining a CMAKE namespace. This is saved to the
install(EXPORT library_nameTargets
FILE library_nameTargets.cmake
NAMESPACE libName::
DESTINATION lib/cmake/library_name)
# if your project has no dependencies you can replace library_nameTargets.cmake with library_nameConfig.cmake and skip the last step (no. 5), because the needed file has already been written here.
# 4. write the actual .cmake files
include(CMakePackageConfigHelpers) # load helper to create config file
# creates file library_nameConfigVersion.cmake which is needed when you try to find a package in another project with find_package()
write_basic_package_version_file(
"library_nameConfigVersion.cmake"
VERSION ${library_name_VERSION}
COMPATIBILITY AnyNewerVersion)
# 5. write the library_nameConfig.cmake file which is needed.
# finally the install file library_nameConfig.cmake is actually copied over to library_nameConfig.cmake which is needed to find the library with find_package() in other projects
install(FILES "library_nameConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/library_nameConfigVersion.cmake"
DESTINATION lib/cmake/geo)
```
The file `library_nameConfig.cmake` contains the following:
```cmake
include(CMAKEFindDependencyMacro)
# find_dependency(xxx 2.0) # if any dependencies are needed
# this includes the Targets.cmake file thatis created in step 3 in the cmake file above.
include(${CMAKE_CURRENT_LIST_DIR}/library_nameTargets.cmake)
```
## Executable
# Uninstall Target
The default sequence to install a cmake project is the following:
```bash
mkdir build && cd build
cmake ..
cmake --build .
sudo make install
```
The last command will execute the installation which basically copies important files (as specified in the CMakeLists.txt) into a system directory (usually `/usr/local/`). When this happens a file called `install_manifest.txt` is created in the build folder which lists all installed files. In order to undo the installation you can run the [following command:](https://stackoverflow.com/a/44649542/7705525)
```bash
xargs rm < install_manifest.txt
```
If you want to get fancier you can also create a [uninstall target](https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake), which basically iterates through the `install_manifest.txt` file and removes any file and folder (if empty) listed in the file.
# How is CMake used in ROS2 and Colcon
ROS2 makes extensive use of `CMake` in its buildsystem. It is all hidden behind the `colcon` command, but the projects all contain `CMakeLists.txt`-files that define how a ROS2 package is compiled. A good example to look at source code is the [[ROS2 - NAV2 Library|NAV2]]-Library.
- [ ] #todo/b add cmake specifics and how ament, and colcon uses it. Also how testing is done.
- [ ] [Ament_cmake user documentation](https://docs.ros.org/en/rolling/How-To-Guides/Ament-CMake-Documentation.html) #todo/b
- [ ]
# Flashcards
#learning/cpp
how to run unit tests (gtest) of a cmake project ;; `ctest` after having built the project
<!--SR:!2023-12-10,14,290-->
how to define a executable in a cmake project ;; `add_executable(name sourcefile1 sourcefile2 ...)`
<!--SR:!2024-03-15,59,310-->
how to define a library in a cmake project ;; `add_library(name sourcefile1 sourcefile2 ...)`
<!--SR:!2023-12-09,13,290-->
# Resources
- https://decovar.dev/blog/2021/03/08/cmake-cpp-library/
- https://raymii.org/s/tutorials/Cpp_project_setup_with_cmake_and_unit_tests.html
- https://iamsorush.com/posts/cpp-cmake-config/

View File

@@ -0,0 +1,23 @@
---
aliases:
- GoogleTest
- GTest
---
Also known as gtest is a unit testing library for C++. It is also used by ROS2.
# Flashcards
#learning/cpp
which GTest to use to compare two `std::string` objects? ;; `EXPECT_EQ(s1, s2)`
<!--SR:!2023-12-12,16,290-->
which GTest to use to compare two `char[]` objects? ;; `EXPECT_STREQ(s1, s2)`
<!--SR:!2023-12-13,17,290-->
difference between `ASSERT_EQ` and `EXPECT_EQ`;; **assert** will stop execution if it fails, **expect** will run all following code as well and only report at the end.
<!--SR:!2024-03-08,52,314-->
`Ctest` is not finding any tests ;; in `CMakeLists.txt`: `enable_testing()` needs to before `include_directories(test)`. Else it does not work
<!--SR:!2024-01-25,9,274-->
# Resources
Get started quickly with [[CMake]]: https://gitlab.cern.ch/google/googletest/-/blob/master/docs/quickstart-cmake.md
A good resource:
[IBM C++ Testing documentation](https://developer.ibm.com/articles/au-googletestingframework/#list2)

View File

@@ -0,0 +1,29 @@
A good article: https://cplusplus.com/doc/tutorial/files/
# Key Takeaways
* There are two modes: binary and text. Text mode formats (e.g. ASCII) the bytes being written (and vice versa when being read), whereas in binary mode this does not happen
* There are three libraries: `fstream`, `ofstream`, `ifstream`. f: file, o: output, i: input
* There are position pointers that keep track of where in the file we're writing to or reading from: they are called **put** and **get** position pointers respectively
* In order to **read the pointers** use: `tellg()` and `tellp()` for get and put, respectively.
* In order to **change the pointers** use: `seekg(position)` and `seekp(position)` for get and put, respectively. The arguments can also be `seekg(offset, direction)`
* There are helper flags for the offset: `ios::beg` for beginning of file, `ios::cur` for current location in the file, `ios::end` for the end of the file
Example:
```c++
// obtaining file size
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streampos begin,end;
ifstream myfile ("example.bin", ios::binary);
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size is: " << (end-begin) << " bytes.\n";
return 0;
}
```

View File

@@ -0,0 +1,57 @@
I have been wanting to code properly with unit tests and continuous integration for a few years now and have never done it properly.
# Development Process
## Unit Testing
### C++
In [[C++]] we use the [[GTest Framework|GoogleTest]] Framework.
## Code Coverage
Code coverage testing basically compiles the code with profiling flags, which count the number of times a specific line has been executed. And since google test runs the source code we can test if we are testing all the code that we have written.
For C++ typically, a tool called `gcovr` is used. In order for it to work you need to compile the code with the following flags: `-fprofile-arcs` and `-ftest-coverage`
If the project uses [[CMake]] you can add the following to your CMakeLists.txt:
```cmake
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
endif()
```
# Online Tools
In order to do continuous integration we need a place that automatically runs our unit tests whenever a commit is pushed.
## GitLab
Gitlab is known for its [[Gitlab - CI CD|CICD]] (Continuous Integration / Continuous Deployment) pipeline. It allows to customize and automate the entire process very effectively. The setup process is also very easy and explained well on [their website](https://docs.gitlab.com/ee/ci/quick_start/).
1. You must have runners[^1] available
2. Create a `.gitlab-ci.yml` file at the root of your repository. The entire pipeline of automated tests is defined in this file.
A good example repo can be found [here](https://github.com/pothitos/gtest-demo-gitlab/tree/master).
My own first gitlab-ci config file (`.gitlab-ci.yml`):
```yaml
image: ubuntu:20.04
job:
script:
- export DEBIAN_FRONTEND=noninteractive
- apt-get update
- apt-get install -y cmake g++ build-essential git gcovr
- cd onesec3d_cpp
- mkdir build && cd build
- cmake -DBUILD_TESTING=ON ..
- cmake --build .
- export DATADIR=../test/sample_3d_files/
- ./test/onesec3d_cpp_test
- gcovr --exclude-directories '_deps' -r ..
```
# Flashcards
#learning/cpp
which command to do code coverage testing;;`gcovr`
<!--SR:!2023-12-21,14,290-->
requirements for `gcovr`;; project must be built with flags: `-fprofile-arcs` and `-ftest-coverage`
<!--SR:!2023-12-08,1,210-->
# Resources
- CI for robotics projects with [[ROS2]]: use [[Gazebo]] that is run on the gitlab server: http://moore-mike.com/bobble-ci.html
# Footnotes
[^1]: GitLab Runner is an application that can execute CI/CD jobs in a GitLab pipeline

View File

@@ -0,0 +1,9 @@
---
aliases:
- CICD
- gitlab
---
# Resources
https://github.com/pothitos/gtest-demo-gitlab/blob/master/CMakeLists.txt

View File

@@ -0,0 +1,10 @@
# Terminator
- A tabular terminal emulator that makes working only with the keyboard much easier
- Make terminator default terminal: `sudo update-alternatives --config x-terminal-emulator`
- Right click terminator terminal, go to preferences and change font to meslo, and change to other color theme.
# Oh-my-Zsh
- [ ] Add installation snippet here (or gist) #todo/b
# Dotfiles
- [ ] Add dotfile management system to configure your machine #todo/b

View File

@@ -0,0 +1,23 @@
# Dotfiles
# Functions
## Arguments
Some more info can be found [here](https://unix.stackexchange.com/a/378023/460036).
- `$X`, where X is any number is the xth argument
- `$@`, is a list of all arguments
- `${@:2}`, is the a list of all arguments, starting from the second one
- :2 basically means an offset
# Cheat Sheet
## Watch
Can be used to repeatedly execute commands like retrieving the CPU temperature:
```bash
sensors
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +77.9°C
Tccd1: +77.5°C
```
So with the watch command this will be updated at a certain interval (e.g. 1s and also update the difference `-d`): `watch -d -n 1 'sensors'`

View File

@@ -0,0 +1,7 @@
#learning/computer_science
# VIM
search in vim ;; in vim: `/SEARCH_TERM`, then `N` for next, `shift` + `N` for previous
<!--SR:!2024-03-11,55,310-->
# Nano
cut and paste a line in nano ;;; in nano: `ctrl`+`K`, then `ctrl`+`U`
<!--SR:!2024-01-30,14,292!2023-12-21,9,270-->

View File

@@ -0,0 +1,11 @@
# Main Commands
# Flashcards
#learning/computer_science
update local branch list with remote branch list (also deleted ones) ;; `git fetch -p` p: prune
<!--SR:!2024-03-04,48,290-->
reorder the last n commits ;; `git rebase -i HEAD~n` then change the pick order.
<!--SR:!2024-03-24,68,310-->
word to merge multiple commits into one ;; `squash`
<!--SR:!2024-03-23,67,310-->