|
libsgfc++ 3.0.0
A C++ library that uses SGFC to read and write SGF (Smart Game Format) data.
|
This document contains instructions on how to build, install and execute all parts of the project: The software library itself, the unit tests, a sample program and the API documentation.
The project requires CMake 3.10 or newer to build, and a reasonably modern version of Git to clone the project repository and fetch some Git submodules. Building the API documentation requires Doxygen.
Use your package manager of choice to install these components on your system. On macOS the recommended package manager is Homebrew, on Windows it's Chocolatey.
After cloning the repository you must first initialize its Git submodules:
cd /path/to/project git submodule update --init --recursive
In the next step you apply some patches to SGFC:
cd sgfc test $(ls ../patch/*.patch 2>/dev/null | wc -l) -gt 0 && \ for PATCH_FILE in ../patch/*.patch; do git apply "$PATCH_FILE"; done cd ..
Now you're ready to build. On platforms that support Makefile-based build systems these commands should do it:
mkdir build cd build # If you want a debug build then replace "Release" with "Debug" cmake -DCMAKE_BUILD_TYPE=Release .. cmake --build .
Building with Xcode or Visual Studio is explained in sections further down.
After building you can run tests from the build folder with this command:
ctest
Why does ctest report only a single test? This is because CMake sees the Catch2 test runner as a single test, when in fact the test runner is only the "facade" of the project's entire test suite. Execute the Catch2 test runner directly, with something like the following command, to see more detailed results. The command may vary on different platforms.
./test/libsgfcplusplus-test
The Catch2 test runner also has more capabilities than ctest to control which tests should be run. Invoke the test runner with the -h option to see all the options that are available. Example: All test scenarios are tagged, you can list those tags like this:
./test/libsgfcplusplus-test --list-tags
To run only tests marked with certain tags specify the tags in brackets. The following examples only runs tests that are related to text encodings and/or that excercise go-specific functionality:
./test/libsgfcplusplus-test "[encoding],[go]" # or ./test/libsgfcplusplus-test "[encoding][go]" # and
The [filesystem] tag marks all tests that interact with the filesystem. To exclude these:
./test/libsgfcplusplus-test "~[filesystem]"
For more details see the Catch2 documentation.
The libsgfc++ build system integrates Catch2 by way of the CMake commands find_package() or add_subdirectory(). It attempts to locate the package in two steps:
If both lookup attempts fail, the build fails.
You can define the source distribution path where the build system should look for the package by defining the variable CATCH2_SOURCEDISTRIBUTION_PREFIX:
cmake -DCMAKE_BUILD_TYPE=Release \
-DCATCH2_SOURCEDISTRIBUTION_PREFIX=/path/to/folder \
..
If you don't define a source distribution path, the build system assumes test/Catch2 as the default source distribution path. This path points to the Catch2 Git submodule which you have initialized at the very beginning.
After the tests have run successfully you install the build products to a destination folder of your choice. CMake 3.15 and newer include a command line option --install which can be used like this:
cmake --install . --prefix /path/to/destfolder
Older CMake versions don't have the --install command line option and you must use the generated build system to perform the installation. You also have to define the prefix folder when you generate the build system. Example for make:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/path/to/destfolder .. [...] make install
The following things will be installed:
A couple of notes:
The library's source code is documented with Doxygen formatted inline comments. To generate the documentation you have to have Doxygen installed.
Generating and installing the API documentation is optional, and therefore is not part of the regular software build. These are the commands that need be invoked separately:
cd build cmake --build . --target libsgfcplusplus-doc cmake --install . --component libsgfcplusplus-doc --prefix /path/to/destfolder
Notes:
The example folder contains sample code that demonstrates how to use the library in a client application. When you build the project a simple command line program is also built that you can invoke in one of four modes to run the sample code.
The four modes quickly explained:
The default build builds everything, but if you wish you can disable certain build products by setting the corresponding variables:
The following example builds everything except the static library framework and the examples:
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_STATIC_FRAMEWORK=NO -DENABLE_EXAMPLES=NO .. cmake --build .
You can also set the variable ENABLE_DEFAULT to NO as a quick way to change the default from "build everything" to "build nothing". After that you can enable only certain build products.
The following example only builds the shared library:
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_DEFAULT=NO -DENABLE_SHARED_LIBRARY=YES .. cmake --build .
In the previous section you have seen how to generate a Makefile-based build system. CMake can also generate an Xcode project, like this:
cd build cmake -G Xcode .. # Launch Xcode with the generated project open libsgfc++.xcodeproj
The ALL_BUILD target in the Xcode project builds all targets, i.e. both the shared and the static libraries, the shared and static library frameworks, and the unit tests.
The RUN_TESTS target builds the unit test target and executes a custom post-build script that is supposed to run the test. The post-build script currently doesn't seem to work. It is therefore recommended building the unit test target (libsgfc++-test) and selecting "Product > Run" to execute the test runner. This always works, and Xcode is even nice enough to pop up an output pane that shows you the output of the command line test runner.
The ZERO_CHECK target checks whether your CMakeLists.txt files have changed and if necessary updates the Xcode project with the changes.
CMake can generate a Visual Studio solution like this:
cd build cmake -G "Visual Studio 16 2019" ..
If you use a different version of Visual Studio replace the -G parameter value. Invoking just cmake -G prints out available values.
When CMake has finished you can launch Visual Studio with the generated solution file libsgfc++.sln.
The above generates a true "out of source" build system that is so typical for CMake. An alternative approach is shown in the article CMake projects in Visual Studio on Microsoft's official documentation site. This is a convenient GUI-only approach, but it generates stuff in two folders .vs and out in the project root.
Some packages need to be installed before building can start:
Once all packages are installed the Cygwin build works just like it does on other UNIX-like systems. Just follow the steps in the first sections at the top of this document.
No instructions available. This has not been tested yet.
Cross-compiling for iOS (or for any of the other Apple device OS's) currently seems to be a bit of a moving target in CMake, due to some changes that have been going on in the Apple developer ecosystem in the last years. Driving factors are the introduction of Silicon Macs (i.e. macOS machines running on ARM processors) and the continued evolution of Xcode (e.g. introduction of a new / removal of the old build system).
The next two sections therefore present two ways how to cross-compile for iOS: An old way, which will eventually stop working in future CMake versions (and probably does not even work today on Silicon Macs), and a new way, which may need refinement in the future but should at least work on all machines given modern versions of CMake and Xcode are used.
Both solutions build on CMake's basic mechanics for cross-compiling for iOS, which are explained in the cmake-toolchains man page and are also available from the CMake website.
Here is a set of commands that should work with CMake 3.28.1, on an Intel macOS machine where Xcode 15 is installed. This solution uses the property IOS_INSTALL_COMBINED, which has been deprecated in CMake version 3.28, so the solution will eventually stop working once CMake removes the property completely. Also note that the solution most likely does not work on Silicon Macs - if you have one of these machines then jump ahead to the "new way" section below.
cd /path/to/libsgfcplusplus mkdir build cd build cmake .. -G Xcode \ -DCMAKE_SYSTEM_NAME=iOS \ "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \ -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \ -DCMAKE_IOS_INSTALL_COMBINED=YES cmake --build . --config Release cmake --install . --prefix `pwd`/install
Notes:
The results of the "old way" solution are universal (aka "fat") binaries: These are binaries that can contain multiple architectures (aka "slices") as long as they are different. On Intel macOS machines this is fine because the simulator build (x86_64 architecture) and the device build (arm64 architecture) have different architectures, so it is no problem to store both slices in the same universal binary. On ARM macOS machines (aka Silicon Macs) this does not work, though, because on these machines the simulator build and the device build both use the arm64 architecture.
Apple's solution for this is a new kind of framework called "XCFramework": This is an enhanced framework bundle (recognizable by the extension .xcframework) that can contain any number of binaries for different platforms. It seems that currently CMake does not have built-in support for creating XCFrameworks, instead one has to stitch together an XCFramework bundle manually from individual framework parts using xcodebuild -create-xcframework.
Here is an example that was tested on an Intel Mac, but should also work on a Silicon Mac. Note that this solution no longer uses the deprecated property IOS_INSTALL_COMBINED
Notes:
If you see an Xcode build error "unable to attach DB" then you are likely affected by an incompatibility between the way how CMake handles IOS_INSTALL_COMBINED and the Xcode build system. Depending on the combination of versions of Xcode and CMake that you have, if you still want to use IOS_INSTALL_COMBINED you may therefore need to select the old or the new Xcode build system.
Some background information:
For iOS builds the project default is to not build the shared library, shared library framework, unit tests or the examples. The reason is that when built for the device these binaries all require codesigning, but since the project does not provide a codesigning identity the build would just fail.
The following example shows how you can force the shared library to be built with a codesigning identity of your own.
cmake .. -G Xcode \ [...] # same options as shown in the cross-compiling section -DENABLE_SHARED_LIBRARY=YES \ -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=<identity>
Note: You can find out your codesigning identy with this command: xcrun security find-identity -v -p codesigning. It's the long hex string at the start of the output.
When you build libsgfc++ for iOS you may encounter errors because some build products require a certain minimum iOS version. Known cases:
If you have these errors you have to set the deployment target to 13.0. The deployment target is set with the CMake option -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0.
Should you try to build unit tests or the examples for iOS you will encounter an obstacle: The unit test runner and the examples are both executables, so they need to be codesigned, but unlike a shared library an executable can only be codesigned if it has a bundle identifier.
The project does not provide any bundle identifiers, so if you insist on building the unit tests and/or the examples for iOS that is something you have to provide. There is currently no example how to build bundles - a starting point would be the CMake documentation for MACOSX_BUNDLE.
libsgfc++ exports its CMake targets (both from the build tree and from the install tree) as a CMake package. This allows downstream projects that also use CMake to generate their build system to easily integrate libsgfc++ into their own build. The CMake command for this is find_package().
If libsgfc++ has been installed to a system-wide installation path (e.g. /usr/local) then it can be found without specifying a path. The search logic employed by find_package() is exceedingly complicated and is not documented here. If you want to know more look it up in the CMake documentation of the find_package() command.
An example:
find_package ( libsgfcplusplus 0.1 EXACT )
If libsgfc++ has been installed to some non-standard path, then the downstream project must provide a hint where to look for the CMake package files. The hint should be the installation prefix used to install libsgfc++, not the subfolder where the CMake package files actually reside. Again, find_package() employs clever search logic to probe for the files.
Another example:
find_package ( libsgfcplusplus 0.1 EXACT HINT /path/to/installation-prefix )
As can be seen in the examples, the package name to use is libsgfcplusplus. The exported targets all have the prefix libsgfcplusplus::. The exported targets are:
To use the exported targets after find_package() has successfully located the package, the downstream project typically specifies the exported target names in their target_link_libraries() commands. Example:
target_link_libraries ( downstream-target-name libsgfcplusplus::libsgfcplusplus_shared )
This not only adds the link instructions (including to the iconv dependency) to the downstream target, it also adds the INTERFACE include directories of the linked libsgfc++ target to the include directories of the downstream target. This way the downstream project can write #include statements like this in their source code:
#include <libsgfcplusplus/SgfcPlusPlusFactory.h>