Skip to content

Commit 6d44313

Browse files
authored
Sphinx Architecture documentation (#176)
1 parent 419c37f commit 6d44313

File tree

22 files changed

+693
-13
lines changed

22 files changed

+693
-13
lines changed

.github/workflows/pages.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ jobs:
2828
run: |
2929
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILDCC_DOCUMENTATION=ON
3030
31-
- name: Build
32-
working-directory: ${{github.workspace}}
33-
shell: bash
34-
run: cmake --build build --config $BUILD_TYPE
35-
3631
- name: Doxygen + Sphinx
3732
working-directory: ${{github.workspace}}/build
3833
shell: bash

buildcc/lib/env/include/env/command.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,15 @@ class Command {
6161
&arguments = {}) const;
6262

6363
/**
64-
* @brief Execute a particular command and optionally redirect stdout and
65-
* stderr to user supplied dynamic string lists
64+
* @brief Execute a particular command over a subprocess and optionally
65+
* redirect stdout and stderr to user supplied dynamic string lists
66+
*
67+
* @param command Command is run on the shell
68+
* @param working_directory Current working directory
69+
* @param stdout_data Redirect stdout to user OR default print to console
70+
* @param stderr_data Redirect stderr to user OR default print to console
71+
* @return true when exit code = 0
72+
* @return false when exit code != 0
6673
*/
6774
// TODO, Update this to get an integer exit code number instead of boolean
6875
// value

buildcc/lib/env/mock/include/expect_command.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ constexpr const char *const TEST_VECTOR_STRING_TYPE = "vector_string";
88

99
namespace buildcc::env::m {
1010

11+
/**
12+
* @brief `Command::Execute` expectation API
13+
*
14+
* @param calls Number of times the actual `Command::Execute` API is called
15+
* @param expectation Return value of the actual `Command::Execute` API
16+
* @param stdout_data Data passed into stdout_data is redirected into the
17+
* actual `Command::Execute` API to check for expectations. See
18+
* `VectorStringCopier`
19+
* @param stderr_data Data passed into stderr_data is redirected into the actual
20+
* `Command::Execute` API to check for expectations. See `VectorStringCopier`
21+
*/
1122
void CommandExpect_Execute(unsigned int calls, bool expectation,
1223
std::vector<std::string> *stdout_data = nullptr,
1324
std::vector<std::string> *stderr_data = nullptr);

buildcc/lib/target/mock/expect_generator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
namespace buildcc::base::m {
77

8+
/**
9+
* @brief Runs the generator using Taskflow with 1 thread
10+
* CppUTest cannot mock with multiple threads
11+
*/
812
void GeneratorRunner(Generator &generator);
913

1014
void GeneratorExpect_InputRemoved(unsigned int calls, Generator *generator);

buildcc/lib/target/mock/expect_target.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ namespace buildcc {
77

88
namespace base::m {
99

10+
/**
11+
* @brief Runs the target using Taskflow with 1 thread
12+
* CppUTest cannot mock with multiple threads
13+
*/
1014
void TargetRunner(Target &target);
1115

1216
void TargetExpect_SourceRemoved(unsigned int calls, Target *target);

cmake/tool/doxygen.cmake

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ if (${BUILDCC_DOCUMENTATION})
55
message("Doxygen Found: ${DOXYGEN_FOUND}")
66
message("Doxygen Version: ${DOXYGEN_VERSION}")
77

8-
set(DOXYGEN_EXCLUDE_PATTERNS
9-
*test/*
10-
*mock/*
11-
)
8+
# set(DOXYGEN_EXCLUDE_PATTERNS
9+
# *test/*
10+
# *mock/*
11+
# )
1212
set(DOXYGEN_EXTRACT_ALL YES)
1313
set(DOXYGEN_WARN_IF_UNDOCUMENTED YES)
1414
set(DOXYGEN_GENERATE_XML YES)
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
CMake Boilerplate
2+
=================
3+
4+
.. code-block:: cmake
5+
6+
if (${TESTING})
7+
# setup mocking
8+
# setup testing executables
9+
10+
# TODO, Add example
11+
endif()
12+
13+
if(${BUILDCC_BUILD_AS_SINGLE_LIB})
14+
# buildcc files as an aggregate to one CMake library
15+
# third party libraries still remain seperate so do NOT add it here
16+
# Add third party library dependency to `buildcc` library in `buildcc/CMakeLists.txt`
17+
18+
# TODO, Add example
19+
endif()
20+
21+
if(${BUILDCC_BUILD_AS_INTERFACE})
22+
# one buildcc library broken up into smaller library chunks instead of aggregated to one CMake library like in BUILDCC_BUILD_AS_SINGLE_LIB
23+
# NOTE: Do not forget to add this small library chunk to `buildcc_i` library in `buildcc/CMakeLists.txt`
24+
25+
# TODO, Add example
26+
endif()
27+
28+
if (${BUILDCC_INSTALL})
29+
# Install behaviour when option selected
30+
31+
# TODO, Add example
32+
endif()
33+
34+
35+
When structuring our code we would like to create different folders with ``CMakeLists.txt`` files as individual compile units.
36+
We can then ``add_subdirectory`` that particular folder. This helps us keep our codebase modular.
37+
38+
39+
**Example: Environment**
40+
41+
.. code-block:: cmake
42+
43+
# Env test
44+
if (${TESTING})
45+
add_library(mock_env STATIC
46+
mock/logging.cpp
47+
mock/assert_fatal.cpp
48+
49+
src/env.cpp
50+
src/task_state.cpp
51+
52+
src/command.cpp
53+
mock/execute.cpp
54+
)
55+
target_include_directories(mock_env PUBLIC
56+
${CMAKE_CURRENT_SOURCE_DIR}/include
57+
${CMAKE_CURRENT_SOURCE_DIR}/mock/include
58+
)
59+
target_link_libraries(mock_env PUBLIC
60+
fmt::fmt-header-only
61+
Taskflow
62+
63+
CppUTest
64+
CppUTestExt
65+
gcov
66+
)
67+
target_compile_options(mock_env PUBLIC ${TEST_COMPILE_FLAGS} ${BUILD_COMPILE_FLAGS})
68+
target_link_options(mock_env PUBLIC ${TEST_LINK_FLAGS} ${BUILD_LINK_FLAGS})
69+
70+
# Tests
71+
add_executable(test_env_util test/test_env_util.cpp)
72+
target_link_libraries(test_env_util PRIVATE mock_env)
73+
74+
add_executable(test_task_state test/test_task_state.cpp)
75+
target_link_libraries(test_task_state PRIVATE mock_env)
76+
77+
add_executable(test_command test/test_command.cpp)
78+
target_link_libraries(test_command PRIVATE mock_env)
79+
80+
add_test(NAME test_env_util COMMAND test_env_util)
81+
add_test(NAME test_task_state COMMAND test_task_state)
82+
add_test(NAME test_command COMMAND test_command)
83+
endif()
84+
85+
set(ENV_SRCS
86+
src/env.cpp
87+
src/assert_fatal.cpp
88+
src/logging.cpp
89+
include/env/assert_fatal.h
90+
include/env/assert_throw.h
91+
include/env/env.h
92+
include/env/logging.h
93+
include/env/util.h
94+
95+
include/env/host_os.h
96+
include/env/host_compiler.h
97+
include/env/host_os_util.h
98+
99+
src/task_state.cpp
100+
include/env/task_state.h
101+
102+
src/command.cpp
103+
src/execute.cpp
104+
include/env/command.h
105+
)
106+
107+
if(${BUILDCC_BUILD_AS_SINGLE_LIB})
108+
target_sources(buildcc PRIVATE
109+
${ENV_SRCS}
110+
)
111+
target_include_directories(buildcc PUBLIC
112+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
113+
$<INSTALL_INTERFACE:${BUILDCC_INSTALL_HEADER_PREFIX}>
114+
)
115+
endif()
116+
117+
if(${BUILDCC_BUILD_AS_INTERFACE})
118+
m_clangtidy("env")
119+
add_library(env
120+
${ENV_SRCS}
121+
)
122+
target_include_directories(env PUBLIC
123+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
124+
$<INSTALL_INTERFACE:${BUILDCC_INSTALL_HEADER_PREFIX}>
125+
)
126+
target_link_libraries(env PUBLIC fmt::fmt-header-only)
127+
target_compile_options(env PRIVATE ${BUILD_COMPILE_FLAGS})
128+
target_link_options(env PRIVATE ${BUILD_LINK_FLAGS})
129+
target_link_libraries(env PRIVATE
130+
spdlog::spdlog_header_only
131+
tiny-process-library::tiny-process-library
132+
)
133+
endif()
134+
135+
if (${BUILDCC_INSTALL})
136+
if (${BUILDCC_BUILD_AS_INTERFACE})
137+
install(TARGETS env DESTINATION lib EXPORT envConfig)
138+
install(EXPORT envConfig DESTINATION "${BUILDCC_INSTALL_LIB_PREFIX}/env")
139+
endif()
140+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION "${BUILDCC_INSTALL_HEADER_PREFIX}")
141+
endif()

docs/source/arch/design_patterns.rst

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,45 @@
11
Design Patterns
22
===============
3+
4+
CRTP / Mixins
5+
--------------
6+
7+
`Article by fluentcpp.com on CRTP <https://www.fluentcpp.com/2017/05/16/what-the-crtp-brings-to-code/>`_
8+
9+
* Mixins are a design pattern used to add additional functionality to an existing class
10+
* In this case, the ``TargetInfo`` and the ``Target`` class are meant to have a lot of setter APIs for user inputs.
11+
* Adding more APIs to the class makes its difficult to read and maintain.
12+
* For reference: See :doc:`serialization_schema`
13+
* For example: In Target ``source_files`` have currently have several APIs
14+
* ``AddSource``
15+
* ``AddSourceAbsolute``
16+
* ``GlobSources``
17+
* ``GlobSourcesAbsolute``
18+
* In the future we might have additional APIs such as
19+
* ``AddSources`` that takes an ``std::initializer_list``
20+
* ``AddSources`` that takes a ``std::vector<>`` or ``std::unordered_set<>``
21+
* ``AddSource(s)ByPattern`` that takes a fmt string like ``{dir}/source.cpp``
22+
* From our serialization schema we can see that each of these fields could have many APIs associated with them. Having 50+ APIs for different fields in a single header i.e ``target_info.h`` / ``target.h`` would not be readible and hard to maintain.
23+
* The Mixin / CRTP pattern is used to easily add functionality for a particular field in its own header / source file.
24+
25+
Friend classes
26+
---------------
27+
28+
* Friend classes are used when 2 classes have strong coupling with each other, but still need to maintain flexibility for other purposes. For example: Unit testing.
29+
* In ``target.h`` we have 3 friend classes (non CRTP based)
30+
* ``CompilePch``
31+
* ``CompileObject``
32+
* ``LinkTarget``
33+
* These 3 classes are made friend classes for 2 main purposes
34+
* Unit Testing
35+
* Flexibility / Maintaibility
36+
* Unit Testing
37+
* If these were not friend classes, the functions would've been private in scope within the ``Target`` class
38+
* Unit testing these individual private functions would not be possible would public interfaces
39+
* By making them friend classes, We can now unit test the public functions and embed this class in a private context with the ``Target`` class
40+
* Flexibility / Maintaibility
41+
* Each one of the classes mentioned above have their own information / states / tasks to hold.
42+
* Without this segregation all of the member variables, states and tasks would need to be present inside the ``Target`` class
43+
* Strong Coupling
44+
* The 3 friend classes have strong coupling with the ``Target`` class since it uses its internal member variables for setting / getting information.
45+
* The friend class can interact with the parent class and vice versa.

docs/source/arch/namespaces.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,21 @@
11
Namespaces
22
==========
3+
4+
User
5+
-----
6+
7+
* ``buildcc``
8+
* ``buildcc::env``
9+
* ``buildcc::plugin``
10+
11+
.. admonition:: User/Developer opinion
12+
13+
Do we need to segregate the **Environment** into its own ``buildcc::env`` namespace or merge all those APIs into the ``buildcc`` namespace?
14+
15+
Developer
16+
----------
17+
18+
* ``buildcc::base``
19+
* ``buildcc::internal``
20+
21+
.. note:: Consider removing ``buildcc::base`` since a lot of the APIs are typedef`ed to the ``buildcc`` namespace

docs/source/arch/outputs.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,63 @@
11
Outputs
22
=======
3+
4+
BuildCC Library
5+
-----------------
6+
7+
The ``build_in_cpp`` project aims to remove DSLs by writing build files in C++.
8+
9+
However our C++ "script" first needs to be **built (compiled and linked)** then **executed (build targets)**.
10+
11+
When building (compiling and linking) our C++ "script" we need to link the ``buildcc`` library as well to provide the "script" with ``buildcc`` APIs.
12+
13+
BuildExe Executable
14+
---------------------
15+
16+
``BuildExe`` is a standalone executable similar to ``make.exe``.
17+
18+
As part of the current release ``BuildExe`` requires the following folder structure.
19+
20+
.. note:: Proper details of ``BuildExe`` usage to be added. For now this is in its experimental stage with only support for GCC, MinGW and MSVC compilers.
21+
22+
.. uml::
23+
24+
@startmindmap
25+
* ENV[BUILDCC_HOME]
26+
** buildcc
27+
** extensions
28+
** libs
29+
** host
30+
@endmindmap
31+
32+
ENV[BUILDCC_HOME]
33+
^^^^^^^^^^^^^^^^^^
34+
35+
Create your BUILDCC_HOME directory. For example: ``C:/BUILDCCHOME`` or ``local/mnt/BUILDCCHOME`` and add this path to the **environment variable BUILDCC_HOME**.
36+
37+
buildcc
38+
^^^^^^^^
39+
40+
This directory contains the git cloned ``build_in_cpp`` repository
41+
42+
extensions
43+
^^^^^^^^^^^
44+
45+
This directory contains several git cloned second and third party plugins and extensions
46+
47+
.. note:: BuildExe will have the ability to directly use these extensions after specifying them in the .toml file
48+
49+
libs
50+
^^^^^
51+
52+
This directory contains several git cloned libraries that need to be used in your projects or code base once they are specified in your .toml file.
53+
54+
In this way, the ``build_in_cpp`` project automatically behaves like a package manager.
55+
56+
host
57+
^^^^^
58+
59+
Host toolchain toml files that contain information pertaining to the various host toolchains installed on your operating system.
60+
61+
.. note:: The goal is to have a standalone executable to detect the host toolchains and automatically generate .toml files for each one of them. Users can then use these host toolchain files for building their "script"
62+
63+
.. note:: Consider adding a **cross** folder for cross compiled toolchains are well which cannot be used to build the "script" but instead can be used by the script to build cross compiled targets.

0 commit comments

Comments
 (0)