# Building Stroika

---

## Common

Stroika is a C++ class library. The only fully supported build environment for Stroika is GNU Make. Once you have that setup, you can build through your favorite IDE. There are other build tools required, but make auto-detects these and warns what is missing.

This build process is cross-platform. It supports cross-compiling, and builds on visual studio.net (windows), and Linux. Stroika also directly supports the IDEs Visual Studio.Net, and Visual Studio code.

---

## <a name="Quick-Start">Quick Start</a>

If you have a POSIX build environment (else see below, docker environments or installing development tools):

```bash
git clone https://github.com/SophistSolutions/Stroika.git Stroika-Dev
```

or

```bash
wget https://github.com/SophistSolutions/Stroika/archive/v3-Release.tar.gz
tar xf v3-Release.tar.gz && mv Stroika-3-Release Stroika-Dev
```

followed by:

```bash
make --directory Stroika-Dev all run-tests
```

Or, for a depending on your system, for a quicker turnaround, perhaps:
```bash
make --directory Stroika-Dev all run-tests CONFIGURATION=Debug -j10
```


If you have a relatively standard POSIX like c++ build environement, you maybe done at this point. If you got errors, or want to know more, read on.

### <a name="build-with-IDE">Build with IDE</a>

Some project files are pre-checked in. For example, look in 
 [Workspaces/VisualStudio.Net-2022/](../Workspaces/VisualStudio.Net-2022/) or [Workspaces/VSCode/](../Workspaces/VSCode/). But some files/configuration/defaults maybe needed by some of these tools so perhaps run:

```bash
make project-files
```
to build some of them (note, if you do a make all, as suggested above, then this will be taken care of automatically).

### <a name="build-with-docker">Build with Docker</a>

If you are missing any components and just want a quick environment to test that has all the right build components installed, you can use the pre-built docker containers:

UNIX:

```bash
docker run -it sophistsolutionsinc/stroika-buildvm-ubuntu2204-small
cat Getting-Started-With-Stroika.md
```

Windows:

```bash
docker run -it sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k22
cat Getting-Started-With-Stroika.md
```

Or - a couple other docker run variants that may help with windows
```bash
docker run --mount type=bind,source=c:/Sandbox,target=c:/Sandbox -it sophistsolutionsinc/stroika-buildvm-windows-msys-vs2k22
docker run -it --storage-opt "size=100GB" sophistsolutionsinc/stroika-buildvm-windows-cygwin-vs2k22
```


### **_Note_**

It takes a while to build all of Stroika (10-20 minutes per configuration), so adding -j10 (or so) helps a lot.

---

## More Details on Getting Started

### Install required tools

This mostly conists of the standard UNIX build tools.

Roughly:
- c++ compiler supporting C++20 or later
- bash (sh)
- make (gnu make), patch, perl, pkg-config, realpath, sed, tar, tr, wget, unzip
- 7za, cmake (optionally - for building some optional components)


You may find it helpful to review the instructions in [Installing-Required-Tools.md](./Installing-Required-Tools.md) which layout details per development platform.

### Things to try (explore)

- `make help`

  Not needed, but gives some idea of make options.

- `make check-prerequisite-tools`

  Not needed, but tells you if you are missing anything critical.

- `make default-configurations`

  Not needed, but it&#39;s a springboard for setting up the configuration you want.

  Review ConfigurationFiles/Debug.xml or any of the other default configuration files

---

## The **configure** script

Like many non-trivial C/C++ libraries, you run configure to establish some build parameters, before invoking make. But unlike most such configuration systems, Stroika creates 'named' configurations, and facilitates building multiple such named configurations at once.

Each configuration is stored in in a file named \${CONFIGNAME}.xml in the top-level `ConfigurationFiles/` directory.

- Examples of generating configurations
  - `./configure Debug-x86 --config-tag Windows --config-tag x86 --arch x86 --apply-default-debug-flags`
  - `./configure Debug --config-tag Unix --apply-default-debug-flags`
  - `./configure clang++-6-release-libstdc++ --config-tag Unix --compiler-driver clang++-6.0 --apply-default-release-flags --stdlib libstdc++ --trace2file enable`
  - `CXX=clang++ ./configure Debug-clang --config-tag Unix --apply-default-debug-flags`
  - `./configure g++-valgrind-debug-SSLPurify --config-tag Unix --config-tag valgrind -valgrind enable --openssl use --openssl-extraargs purify --apply-default-debug-flags --sanitize none;`

### Configuration File Format

Simple XML format (@todo provide XSD).
The command-line used to generate the configuration is the first element of the XML file, so its easy to regenerate the configuration with whatever slight variation you wish.

#### Example Configuration file

```xml
<!--This file autogenerated by the configure command: see Configure-Command-Line, modify it, and re-run-->

<Configuration>
    <Configure-Command-Line>configure Debug-unix --config-tag Unix --build-by-default Linux --only-if-has-compiler --apply-default-debug-flags</Configure-Command-Line>
    <ProjectPlatformSubdir>Unix</ProjectPlatformSubdir>
    <TARGET_PLATFORMS>Linux POSIX</TARGET_PLATFORMS>
    <ARCH>x86_64</ARCH>
    <ConfigTags>Unix</ConfigTags>
    <BuildByDefault>Linux</BuildByDefault>
    <AS>as</AS>
    <CMAKE>cmake</CMAKE>
    <CC>gcc</CC>
    <CXX>g++</CXX>
    <ExtraMakeDefines>
    </ExtraMakeDefines>
    <PkgConfigLinkLineAppendages>
       <PkgConfigLinkLineAppendage>PKG_CONFIG_PATH=$(shell realpath --canonicalize-missing ${StroikaRoot}Builds/$(CONFIGURATION)/ThirdPartyComponents/lib/pkgconfig) pkg-config --static --libs openssl</PkgConfigLinkLineAppendage>
       <PkgConfigLinkLineAppendage>PKG_CONFIG_PATH=$(shell realpath --canonicalize-missing ${StroikaRoot}Builds/$(CONFIGURATION)/ThirdPartyComponents/lib/pkgconfig) pkg-config --static --libs libcurl</PkgConfigLinkLineAppendage>
       <PkgConfigLinkLineAppendage>PKG_CONFIG_PATH=$(shell realpath --canonicalize-missing ${StroikaRoot}Builds/$(CONFIGURATION)/ThirdPartyComponents/lib/pkgconfig) pkg-config --static --libs zlib</PkgConfigLinkLineAppendage>
    </PkgConfigLinkLineAppendages>
    <ENABLE_ASSERTIONS>1</ENABLE_ASSERTIONS>
    <qFeatureFlag_StrawberryPerl>no</qFeatureFlag_StrawberryPerl>
    <qFeatureFlag_boost>use</qFeatureFlag_boost>
    <qFeatureFlag_LibCurl>use</qFeatureFlag_LibCurl>
    <qFeatureFlag_OpenSSL>use</qFeatureFlag_OpenSSL>
    <qFeatureFlag_WinHTTP>no</qFeatureFlag_WinHTTP>
    <qFeatureFlag_Xerces>use</qFeatureFlag_Xerces>
    <qFeatureFlag_ZLib>use</qFeatureFlag_ZLib>
    <qFeatureFlag_sqlite>use</qFeatureFlag_sqlite>
    <qFeatureFlag_LZMA>use</qFeatureFlag_LZMA>
    <qFeatureFlag_WIX>no</qFeatureFlag_WIX>
    <CPPFLAGS>-I/mnt/c/Sandbox/Stroika/DevRoot/Builds/Debug-unix/ThirdPartyComponents/include/ -I/mnt/c/Sandbox/Stroika/DevRoot/Library/Sources/ -I/mnt/c/Sandbox/Stroika/DevRoot/IntermediateFiles/Debug-unix/ -D_GLIBCXX_DEBUG -DqDebug=1 -DqHasFeature_LibCurl=1 -DqHasFeature_OpenSSL=1 -DqHasFeature_WinHTTP=0 -DqHasFeature_Xerces=1 -DqHasFeature_ZLib=1 -DqHasFeature_sqlite=1 -DqHasFeature_LZMA=1 -DqHasFeature_boost=1 -DqStroika_Foundation_Debug_Trace_TraceToFile=1 -DqStroika_Foundation_Debug_Trace_DefaultTracingOn=1</CPPFLAGS>
    <CFLAGS>-fvisibility=hidden -g -fsanitize=address,undefined</CFLAGS>
    <CXXFLAGS>--std=c++20 -Wall -Wno-switch -Wno-sign-compare -Wno-unused-function -Wno-psabi -fvisibility=hidden -g -fsanitize=address,undefined</CXXFLAGS>
    <SanitizerFlags>address undefined </SanitizerFlags>
    <INCLUDES_PATH>/mnt/c/Sandbox/Stroika/DevRoot/Builds/Debug-unix/ThirdPartyComponents/include/:/mnt/c/Sandbox/Stroika/DevRoot/Library/Sources/:/mnt/c/Sandbox/Stroika/DevRoot/IntermediateFiles/Debug-unix/</INCLUDES_PATH>
    <CrossCompiling>false</CrossCompiling>
    <IncludeDebugSymbolsInLibraries>1</IncludeDebugSymbolsInLibraries>
    <IncludeDebugSymbolsInExecutables>1</IncludeDebugSymbolsInExecutables>
    <TOOLS_PATH_ADDITIONS></TOOLS_PATH_ADDITIONS>
    <LIBS_PATH>/mnt/c/Sandbox/Stroika/DevRoot/Builds/Debug-unix/ThirdPartyComponents/lib/</LIBS_PATH>
    <LIB_DEPENDENCIES>/usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.a -lboost_filesystem -lboost_system -lboost_thread -lboost_chrono -lboost_json -lxerces-c -llzma -lsqlite -lpthread -lm -lrt </LIB_DEPENDENCIES>
    <EXTRA_PREFIX_LINKER_ARGS>-Wno-return-local-addr  -rdynamic -fsanitize=address,undefined -static-libasan -static-libubsan -static-libstdc++ -static-libgcc --std=c++20 -g</EXTRA_PREFIX_LINKER_ARGS>
    <EXTRA_SUFFIX_LINKER_ARGS></EXTRA_SUFFIX_LINKER_ARGS>
    <AR>gcc-ar</AR>
    <LIBTOOL></LIBTOOL>
    <RANLIB>gcc-ranlib</RANLIB>
    <Linker>g++</Linker>
    <STRIP>x86_64-linux-gnu-strip</STRIP>
    <RUN_PREFIX></RUN_PREFIX>
    <qCompiler_HasNoMisleadingIndentation_Flag>1</qCompiler_HasNoMisleadingIndentation_Flag>
</Configuration>
```

### Configuration Basic Concepts

- Each configuration has a name (e.g. Debug, Release-clang-7, Debug-raspberry-pi, etc)
- Each configuration can have multiple 'tags' - like Unix, Windows, x86, arm, etc - which can be used to build sets of configurations
- Each configuration defines CFLAGS and CXXFLAGS and (explain others) variables used in a regular makefile. You define (on the command line) variables (like 'assertions') which are used to generate to generate a bunch of other variables which appear in configuration files.

### Configure Command-line reference

```text
Help for making Stroika:
Targets:
    all:                         -    Builds everything
    check:                       -    Checks everything was built properly
    clean:
    clobber:
    reconfigure:                 -    Rebuild configuration files from the command-lines that built them before
    libraries:                   -    Builds Stroika foundation & frameworks, and any things it depends on (like third-party-components)
    project-files:               -    Alias for project-files-visual-studio project-files-qt-creator
    project-files-visual-studio: -    Builds project files for visual studio.net
    project-files-qt-creator(*): -    Builds project project-files-qt-creator (also project-files-qt-creator-load
                                      project-files-qt-creator-save)
    tests:
    format-code:                 -    Run astyle on source code, and update it to conform to Stroika code formatting standards
    samples:
    documentation:
    third-party-components:
    run-tests:                   -    [REMOTE=] - eg. REMOTE=lewis@localhost;
                                      [VALGRIND=memcheck, etc] to run with valgrind
                                      (EXTRA_VALGRIND_OPTIONS= can be used with valgrind)
                                      OR VALGRIND_SUPPRESSIONS="Valgrind-MemCheck-Common.supp Valgrind-MemCheck-BlockAllocation.supp"
                                      EG: VALGRIND_SUPPRESSIONS="Valgrind-MemCheck-Common.supp" make VALGRIND=memcheck run-tests
    apply-configurations:        -    Force re-creation implied files / links for any configurations in the Configurations
                                      folder (not needed, automatic)
    default-configurations:      -    Creates the default configurations in Configurations folder; see ./configure -help for environment variables
                                      e.g. EXTRA_CONFIGURE_ARGS='--openssl-extraargs purify --block-allocation disable' make default-configurations
                                      OR EXTRA_CONFIGURE_ARGS='--platform VisualStudio.Net-2019' make default-configurations
                                      OR PLATFORM='VisualStudio.Net-2022' make default-configurations
    list-configurations:         -    prints all available configurations (each can be used as arg to CONFIGURAITON= make lines)
    list-configuration-tags:     -    prints a list of all configurtion tags (configuration tags impute groups of configurations)
    check-prerequisite-tools:    -    Check the tools needed to build Stroika are installed.
Special Variables:               -    Extra params you can pass to the make line that may help...
    CONFIGURATION=XYZ            -    Causes only the configuration XYZ to have the targetted goal applied (e.g. make all CONFIGURATION=Debug)
    CONFIGURATION_TAGS=TAGS      -    Causes only the configurations with tags TAGS to have the targetted goal applied (e.g. make all CONFIGURATION_TAGS=Windows)
                                      NB: TAGS is a handy shortcut for CONFIGURAITON_TAGS, so you can say make all TAGS="Windows 64"
    ECHO_BUILD_LINES=1           -    Causes make lines to be echoed which can help makefile debugging
    WRITE_PREPROCESSOR_OUTPUT=1  -    Write next to each object file a corresponding .i (preprocessor output) file; useful to reproduce and narrow compiler bugs (for report especially)
    MAKE_INDENT_LEVEL=0          -    Helpful to neaten formatting when multiple levels of makes calling Stroika make
    QUICK_BUILD=1                -    Defaults=0, but if =1, skip some optional build steps (like openssl tests, CURRENT folders; used for some CI testing)
    TEST_FAILURES_CAUSE_FAILED_MAKE=0
                                      only applies to make run-tests, and prevents test failures from stopping make (like make -k on run-tests)
```

### Amending a configuration

Configuration files should **not** be edited by hand. Instead, the current command line is the first element of the configuration file: take that as a starting point and ammend it as needed, and re-run **make apply-configurations** or **make CONFIGURATION=X apply-configuration**.

### Environment variables that affect generation of configuration

- CC, CXX, PLATFORM, ARCH, AS, AR, RANLIB, STRIP

The reason this is so important, is that it allows an external build system like bitbake, or node-gyp, etc to define parameters for a build, and easily generate appropriate configurations.

### Printing configure variables from a script

#### Examples

- `./ScriptsLib/GetConfigurationParameter Debug CFLAGS`

  -I"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.30.30705/ATLMFC/include" -I"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.30.30705/include" -I"C:/Program Files (x86)/Windows Kits/NETFXSDK/4.8/include/um" -I"C:/Program Files (x86)/Windows Kits/10/include/10.0.19041.0/ucrt" -I"C:/Program Files (x86)/Windows Kits/10/include/10.0.19041.0/shared" -I"C:/Program Files (x86)/Windows Kits/10/include/10.0.19041.0/um" -I"C:/Program Files (x86)/Windows Kits/10/include/10.0.19041.0/winrt" -I"C:/Program Files (x86)/Windows Kits/10/include/10.0.19041.0/cppwinrt" -I"C:/Sandbox/Stroika/DevRoot/Builds/Debug/ThirdPartyComponents/include/" -I"C:/Sandbox/Stroika/DevRoot/Library/Sources/" -I"C:/Sandbox/Stroika/DevRoot/IntermediateFiles/Debug/" -EHsc -nologo -GR -Gd -W4 -Zc:inline -FC -bigobj -RTCsu -GS -Oy- -Od -MTd -Z7 -D_UNICODE -DUNICODE -D_WINDOWS -D_DEBUG -DqDebug=1 -DqHasFeature_LibCurl=0 -DqHasFeature_OpenSSL=1 -DqHasFeature_WinHTTP=1 -DqHasFeature_ATLMFC=1 -DqHasFeature_Xerces=1 -DqHasFeature_ZLib=1 -DqHasFeature_sqlite=1 -DqHasFeature_LZMA=1 -DqHasFeature_boost=1 -DqStroika_Foundation_Debug_Trace_TraceToFile=1 -DqStroika_Foundation_Debug_Trace_DefaultTracingOn=1  -fsanitize=address

- `./ScriptsLib/GetConfigurationParameter Debug Linker`

  g++

- `./ScriptsLib/GetConfigurationParameter Release CXXFLAGS`

  -flto --std=c++20 -O3 -I/mnt/c/Sandbox/Stroika/DevRoot/Builds/Release/ThirdPartyComponents/include/ -I/mnt/c/Sandbox/Stroika/DevRoot/Library/Sources/ -I/mnt/c/Sandbox/Stroika/DevRoot/IntermediateFiles/Release/ -Wall -Wno-switch -Wno-sign-compare -Wno-unused-variable -Wno-unused-value -Wno-strict-aliasing -Wno-comment -Wno-unused-function -Wno-unused-but-set-variable -Wno-unused-local-typedefs -g

- defining sample configurations
  ~~~bash
  make default-configuration

  make default-configurations DEFAULT_CONFIGURATION_ARGS='--openssl use --OpenSSL-ExtraArgs purify --block-allocation disable --valgrind enable'

  ./configure DEFAULT_CONFIG

  ./configure gcc-with-malloc-guard --malloc-guard true

  ./configure DefaultConfiguration --apply-default-debug-flag
  ./configure DefaultConfiguration --trace2file enable
  ./configure DefaultConfiguration --assertions enable --trace2file enable

  # Profiler
  ./configure DefaultConfiguration --assertions disable --trace2file disable --cpp-optimize-flag -O3 --pg --lto enable

  # Sanitizer explicit
  ./configure g++-debug-sanitize_address --config-tag Unix --only-if-has-compiler --apply-default-debug-flags --sanitize none,address,undefined --trace2file enable

  ### For Windows to use particular version of Windows SDK
  configure DefaultConfiguration --c-define '\#define WINVER 0x600' --c-define '\#define _WIN32_WINNT 0x600' --c-define '\#define _WIN32_WINDOWS 0x600'
  ~~~

---

## Static Linking vs. Dynamic Libraries

Stroika itself is only provided as a static library. This is because static libraries are much simpler, better for optimizing, and more flexible about configuraiton of the particular build options desired.

I cannot rule out ever providing a dynamic link option/feature, but I see exceedingly little point to it.

Of course, you can still use dynamic (shared library) linking however you wish for any components you build (like you can build shared libraries with Stroika), and obviously for most operatiing systems, the libraries your apps must like to are shared libraries.

But this bias towards static linking is reflected in all the defaults and samples provided with Stroika.

---

## Third Party Components

Stroika builds on, and neatly integrates functionality from several third-party compoenents. These components are automatically downloaded and built and integrated into Stroika (depending on configuration) or Stroika can be configured to use the system installed version of these components.

- StrawberryPerl (special case, just a hack to be able to build openssl)
- boost
- curl
- openssl
- lzma SDK
- sqlite
- WIX
- xerces
- zlib

---

## Build Results

Intermediate files (objs etc) go into

- **IntermediateFiles/{CONFIGURATION-NAME}**.

Final build products (libraries and executables) go into

- **Builds/{CONFIGURATION-NAME}**.

---

## Build Process

On any platform, building Stroika, and all is demo applications and regression tests is as simple as cd&#39;ing to the top-level directory, and typing make

### Special Targets

- `make`

  Make with no arguments runs &#39;make help&#39;

- `make help`

  Prints the names and details of the special targets

- `make all`

  Builds the stroika library, tests, demos, etc.

- `make libraries`

  Builds just the Stroika libraries

- `make samples`

  Builds the Stroika sample applications

- `make run-tests`
- `make CONFIGURATION=zyx run-tests REMOTE='lewis@raspberrypi'`
- `make CONFIGURATION=abc run-tests VALGRIND=memcheck`

  Builds Stroika, and all the regression tests, and runs the regression tests. If REMOTE= is specified, the code is copied to the target machine with ssh, and the test run there (helpful for when cross-compiling). VALGRIND= is used to run memcheck, or leakcheck on the given configuration.

- make `project-files`

  Builds project files which can be used for things like visual studio (not needed)

- `make check-prerequisite-tools`

  Checks if the tools needed to build Stroika are installed and in your path. This is done automatically, and generally not needed explicitly.

- `make apply-configurations`

  To generate all the directories and files dependent on the defined configurations. Note – this is generally not necessary, and called automatically.

### CONFIGURATION arguments to make

All the make targets (e.g. all, libraries etc) take an OPTIONAL parameter CONFIGURATION. If specified, only that configuration is built. If omitted (or empty) – ALL configurations are built.

### TAGS arguments to make

This allows for building (or clobbering or whatever) a related family of configurations. For example

- `make TAGS=Windows`

  runs all the windows builds.

- `make TAGS=Unix` all

  runs all the UNIX compiles

- `make TAGS="Windows x86" all`

  This builds all the configurations with BOTH the Windows and x86 tag (so all the 32-bit x86 builds)

- `make TAGS="Unix arm" list-configurations`

  This doesn't build anything, but just lists all the matching configurations.

- `make list-configurations`
- `make list-configuration-tags`
- `make list-configurations TAGS="Windows"`
- `make list-configurations TAGS="Windows x86_64"`

### Other Make variables that can be helpful

- ECHO_BUILD_LINES=1 makes the output of make noisier, so you can run particular builds by hand, or debug the make process.
- MAKE_INDENT_LEVEL=N, is useful when calling the stroika make process as part of another larger make process, to get its output indended.

### Cross-Compiling

#### Building for Raspberry Pi

To cross-compile for Raspberry pi,

- install some suitable cross compiler (in this example arm-linux-gnueabihf-g++-9)

On unubtu, sudo apt-get install g++-11-arm-linux-gnueabihf

- configure raspberrypi-gcc-11 --apply-default-debug-flags --trace2file enable --compiler-driver arm-linux-gnueabihf-g++-11 --cross-compiling true

Set cross-compiling true so that internal tests aren&#39;t run using the arm built executables.

Set –apply-default-release-flags instead of &#39;debug&#39; for a smaller faster executable.

--trace2file disable to disable tracefile utility, and enabled writes a debug log to /tmp.

- make CONFIGURATION=raspberrypi-gcc-9 all

This builds the samples, libraries etc to Builds/raspberrypi-gcc-9)

- make run-tests REMOTE=pi@myRasberryPi

This uses ssh to run the tests remotely on the argument machine (I setup a hostname in /etc/hosts for the mapping).

Using SSH, it&#39;s also helpful to setup ssh keys to avoid re-entering passwords

[http://sshkeychain.sourceforge.net/mirrors/SSH-with-Keys-HOWTO/SSH-with-Keys-HOWTO-4.html](http://sshkeychain.sourceforge.net/mirrors/SSH-with-Keys-HOWTO/SSH-with-Keys-HOWTO-4.html)

---

## Integration with IDEs

### Using Visual Studio.net

Visual Studio.net project and solution files are available for the Stroika demos, top-level project files, and regression tests. Once you have built your configuration files (see above), you can use the project files to build, test, extend and develop Stroika.

Stroika's build process automatically populates a property file

~~~
Library/Projects/VisualStudio.Net/Microsoft.Cpp.stroika.ConfigurationBased.props
~~~

This contains lots of interesting stuff (used to drive intellisense etc) and is automatically included by the provided Stroika projects.
And it includes two important macros (set reasonably by default, but that you may want to override):

~~~
<StroikaBuildToolsExtraPath>c:\msys64\usr\bin;c:\cygwin64\bin</StroikaBuildToolsExtraPath>
<JOBS_FLAG>-j 8</JOBS_FLAG>
~~~

Note users can provide their own overrides to these values in 

~~~
Library/Projects/VisualStudio.Net/Microsoft.Cpp.stroika.user-default.props
~~~


### Using Visual Studio Code

Visual Studio Code works well with Stroika. Just open the workspace file Workspaces/VSCode/Stroika.code-workspace.
The workspsace contains pre-built 'tasks' to build Stroika (run makefiles).

To use the builtin 'tasks.json' - you may need to install the VSCode extension "command variable".

Also, you will need to have tools like cygwin or MSYS (see [Installing-Required-Tools.md](./Installing-Required-Tools.md)) in your path. One good way todo this is to 
add to your settings.json:
  ~~~json
    "terminal.integrated.profiles.windows": {
      "cygwin-bash": {
        "path": "C:\\tools\\cygwin\\bin\\bash.exe",
        "args": [
          "-l", "-i"
        ],
      },
      "msys-bash": {
        "path": "C:\\tools\\msys64\\usr\\bin\\bash.exe",
        "env": {"MSYSTEM": "MSYS", "CHERE_INVOKING": "1"},
        "args": [
          "-l", "-i"
        ],
      },
    },
    "terminal.integrated.defaultProfile.windows": "cygwin-msys",
  ~~~

  The 'defaultProfile' is the one used by the tasks.json for executing commands like make all, make clean etc from vscode's build menu (SHIFT-Cntrl-B)


### Using QtCreator (on unix)

Run Library/Projects/QtCreator/CreateQtCreatorSymbolicLinks.sh to create project files at the top level of your Stroika directory. Then you can open that .creator file in qtCreator, and build and debug Stroika-based applications.


---

## Building your own application

To some degree, this is simple, and you can just copy/munge one of the sample applications. But the paths in the makefile aren't simple to update. So Stroika provides
a 'Skel' utility, that builds a skeleton application.

  ~~~bash
  ./ScriptsLib/Skel --appRoot ../myApp
  cd ../myApp
  make CONFIGURATION=Debug all -j10
  ~~~

Use './ScriptsLib/Skel --help' to see options

---

## Integrating with CMake

CMake is gaining in popularity, and we will consider possibly moving the Stroika build system to be based on/better integrated with cmake in the future. For now, if you prefer using cmake, and want to use Stroika with cmake, see

- https://stackoverflow.com/questions/3489056/compile-other-external-libraries-without-cmakelists-txt-with-cmake?rq=1
- https://cmake.org/cmake/help/v3.0/module/ExternalProject.html?highlight=external%20project

---

## But Why? Build / Configuration Design

### Alternatives

We seriously considered a number of build systems, including cmake, ant, perl scripts, qmake, etc. They all had substantial weaknesses, with ant possibly being the best alternative, except that it&#39;s heavily java oriented. Maybe for c++ cmake would have been the best?

But just plain GNU make – appears to be a nearly universally available alternative, very standard and simple, so that&#39;s what we&#39;re doing.

But - even with just plain make, you need some sort of configure script to establish what compiler options will be defined. Again, lots of different alternatives here, but in the end I decided to just build custom scripts which build a very simple XML configuration declaration, and which drives the make process by #included 'config' makefile.

---

## Common Errors (FAQ)

- When installing a new version of some compilers like Visual Studio, you must rebuild
  your configuration files with
  ~~~
  make reconfigure
  ~~~
  since the configuration file may contain absolute paths (with version info) to particular compilers or libraries.

- Tar failure

  Errors about invalid parameters, and/or bad blocks can usually be fixed by installing a copy of gnu tar. We&#39;ve tested 1.27.

- cp: illegal option –

  Install a copy of GNU cp

- Cannot find &#39;blah&#39; in Cygwin

  If you are trying to install required components in Cygwin, and cannot find them in the Cygwin setup GUI, try:

  cygcheck -p dos2unix

- rm: cannot remove '.../boost/libs/beast/test/extern/zlib-1.2.11/contrib/dotzlib': Device or resource busy

  This appears to be some weird issue with visual studio code. Quit vs code, and try again.

- VisualStudio.Net project fails to load
  ~~~
  C:\Sandbox\Stroika\appFoo\appFoo\Projects\VisualStudio.Net-2022\appFoo.vcxproj : error  : The imported project file "C:\Sandbox\Stroika\appFoo\Workspaces\VisualStudio.net\Microsoft.Cpp.stroika.ConfigurationBased.props" could not be loaded. Could not find file 'C:\Sandbox\Stroika\appFoo\Workspaces\VisualStudio.net\Microsoft.Cpp.stroika.ConfigurationBased.props'.
  ~~~

  You probably just never built, and so must run 
  ~~~
  make project-files
  ~~~

  See also [STK-943](https://stroika.atlassian.net/browse/STK-943)

- ThirdParty components not automatically rebuilt from Visual Studio project files
    ~~~
    1>C:\Sandbox\Stroika\appTest\ThirdPartyComponents\Stroika\StroikaRoot\Library\Sources\Stroika\Foundation\Cryptography\OpenSSL\CipherAlgorithm.cpp(7): fatal error C1083: Cannot open include file: 'openssl/evp.h': No such file or directory
    ~~~

    Due to performance reasons, and weaknesses with the Stroika makefiles, we don't automatically rebuild third party components from the project files when you say 'build'. This almost never matters. But occasionally it can cause confusion - especially getting started.

    The simplest rule to remember is - build from the command line if building from the project file produces errors that sound like missing files.
  
- On raspberry pi

  > /tmp/Test43: /lib/arm-linux-gnueabihf/libc.so.6: version `GLIBC_2.28' not found (required by /tmp/Test43)

  - fix by

    - sudo vi /etc/apt/sources.list"
    - temporarily add

      ```bash
      #tmphack to load GLIBC_2 2.28
      deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
      ```

    - `sudo apt-get update`
    - `apt-cache policy libc6`
    - `sudo apt-get install libc6=2.28-5+rpi1`
    - undo edit to /etc/apt/sources.list (or comment out addition)
    - sudo apt-get update

    NOTE - if you area dealing later versions some variation on this will likely work. Select the next debian release past your current one for the /etc/apt/sources.list addition and use apt-cache policy to find an available version.

- On MacOS

  - Brew issues

    ```sh
    ld: library not found for -lidn2
    ```

    - brew install libidn2

    - and maybe also add to .zshenv

    ```sh
    export CPATH=/opt/homebrew/include
    export LIBRARY_PATH=/opt/homebrew/lib
    ```

  - realpath issues
    ~~~sh
      realpath: illegal option -- -
      usage: realpath [-q] [path ...]
    ~~~

    missing, or insufficient realpath on macos.
    ~~~sh
    make install-realpath
    ~~~



- Under Docker

  ```text
  ==7192==LeakSanitizer has encountered a fatal error.
  ==7192==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
  ==7192==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
  ```

  OR

  ```text
  warning: Error disabling address space randomization: Operation not permitted
  warning: Could not trace the inferior process.
  warning: ptrace: Operation not permitted
  ```

  run the docker container (docker run or docker exec line) - with:
  `--security-opt seccomp=unconfined`

  - See also
    [../ScriptsLib/RunInDockerEnvironment](../ScriptsLib/RunInDockerEnvironment)
    for more hints on developing flags with docker containers.
