brew install shark
.It’s time to point out that the article deals with version 2.3.4 of the library. The project itself is already far from 2.3.4, beta version 3.0 is currently available. The code for the new version has been significantly reworked, using boost as a third-party library, so this is a completely different story, especially in the context of iOS.
VERSION=2.3.4 SHARK_ZIP=shark-$VERSION.zip # --- download() { if [ ! -s $SHARK_ZIP ]; then echo Downloading shark source code $SHARK_ZIP... curl -L --progress-bar -o $SHARK_ZIP "http://sourceforge.net/projects/shark-project/files/Shark%20Core/Shark%20${VERSION}/shark-${VERSION}.zip/download" else echo Source code $SHARK_ZIP already downloaded... fi doneSection } SRC_DIR=src # --- unpackSource() { echo Unpacking $SHARK_ZIP to $SRC_DIR... [ -d $SRC_DIR ] || unzip -q $SHARK_ZIP -d $SRC_DIR [ -d $SRC_DIR ] && echo " ...unpacked as $SRC_DIR" doneSection }
ReClaM/EarlyStopping.cpp
. EarlyStopping::EarlyStopping(unsigned sl = 5)
EarlyStopping
has a single argument ( unsigned sl
) and the default value ( 5
) is specified for this argument. Thus, this constructor becomes the default constructor, “so be it,” gcc 4.2 says, but clang has a completely different opinion on this. On StackOverflow, you can find a discussion of this error. EarlyStopping::EarlyStopping(unsigned sl)
sl
.finite(x)
function is not available (not included) for iOS, either for devices or for a simulator. On the network, you can find references to this problem, for example here .isfinite(x)
function. Override finite(x)
as isfinite(x)
using preprocessing macros, to do this, add the following code to SharkDefs.h
#if defined(__APPLE__) && defined(__MACH__) /* Apple OSX and iOS (Darwin). */ #include <TargetConditionals.h> #if TARGET_IPHONE_SIMULATOR == 1 /* iOS in Xcode simulator */ #define finite(x) isfinite(x) #elif TARGET_OS_IPHONE == 1 /* iOS on iPhone, iPad, etc. */ #define finite(x) isfinite(x) // #define drem(x, y) remainder(x, y) #elif TARGET_OS_MAC == 1 /* OSX */ #endif #endif
__APPLE__
and __MACH__
, then we include the header file TargetConditionals.h
, then we check the values TARGET_IPHONE_SIMULATOR
, TARGET_OS_IPHONE
and TARGET_OS_MAC
, and redefine the finite(x)
for the iOS device and simulator.drem(x, y)
function, which needs to be replaced with remainder(x, y)
. However, Shark drem(x, y)
does not use, so this is just a note of information.FileUtil
module, namely the FileUtil.h
file.iotype
type iotype
and SetDefault
, ScanFrom
and PrintTo
. Let's give the compiler a hint using the namespace, i.e. perform a simple replacement where needed iotype -> FileUtil::iotype SetDefault -> FileUtil::SetDefault ScanFrom -> FileUtil::ScanFrom PrintTo -> FileUtil::PrintTo
io_strict
function, which calls the scanFrom_strict
and printTo_strict
functions declared later.io_strict
to the end of the file and there is no problem.Mixture/MixtureOfGaussians.cpp
mark the following code as invalid extern "C" double erf(double) throw();
extern "C"
declaration does not match the original prototype.throw()
. extern "C" double erf(double);
I am aware that for some corrections I do not give a detailed explanation, such as removing throw()
. I would be happy to comment in the comments.
Mixture/RandomVector.h
, line 72. The compiler has no idea how to Mixture/RandomVector.h
with p
. Also alarming is the comment to the code in this line ( // !!!
). for (unsigned k = x.dim(0); k--;) { l += log(Shark::max(p(x[ k ]), 1e-100)); // !!! }
p
. RandomVector
inherits RandomVar
, which declared the "lost" method p
. // RandomVar.h template < class T > class RandomVar { public: // *** virtual double p(const T&) const = 0; // *** } // RandomVector.h template < class T > class RandomVector : public RandomVar< Array< T > > { public: // *** }
this->p
. for (unsigned k = x.dim(0); k--;) { l += log(Shark::max(this->p(x[ k ]), 1e-100)); // !!! }
CMakeLists.txt
file. ADD_LIBRARY( shark SHARED ${SRCS} ) # ADD_LIBRARY( shark STATIC ${SRCS} )
diff
utility. diff -crB shark_orig shark_patched > shark.patch
patch
SRC_DIR=src # --- patchSource() { echo Patching source code... patch -d $SRC_DIR/Shark -p1 --forward -r - -i ../../shark.patch doneSection }
make
, it remains only to configure everything correctly for each platform, this will be helped by the utility cmake
(configure make), which will create a Makefile
and other files needed by make
. We will have to configure and build the library 3 times, for the following platforms and architecturesarmv7
, armv7s
, arm64
architecturesi386
and x86_64
x86_64
Yes, an important point, we will use Xcode 5. Support for the architecture of armv6
officially removed from Xcode 5, so we don’t consider it at all.
cmake
. For each platform, we need to properly configure the environment using the following settingsCMAKE_CXX_COMPILER
)/usr/bin/c++
, we also need to use clang++
from the Xcode toolchain.CMAKE_CXX_FLAGS
)CMAKE_C_COMPILER
)CMAKE_OSX_SYSROOT
)CMAKE_INSTALL_PREFIX
)make install
command, but we will not do this.-G
flag)cmake
generate the familiar Makefile
. It would be logical to use the Xcode project, but I was not able to collect everything in this way.xcode-select --install
.xcode-select
to find all the necessary tools and directories. # XCODE_ROOT=$(xcode-select -print-path) # iPhone OS SDK XCODE_ARM_ROOT=$XCODE_ROOT/Platforms/iPhoneOS.platform/Developer # iPhone Simulator SDK XCODE_SIM_ROOT=$XCODE_ROOT/Platforms/iPhoneSimulator.platform/Developer # , ... XCODE_TOOLCHAIN_BIN=$XCODE_ROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin # C++ CXX_COMPILER=${XCODE_TOOLCHAIN_BIN}/clang++ # C C_COMPILER=${XCODE_TOOLCHAIN_BIN}/clang
cmake
is smart enough to find the root system directory on its own, without further instructions.build/ios
.armv7
, armv7s
and arm64
architectures, we will use the special -arch
flag for clang++
.SDKs/iPhoneOS7.0.sdk
subdirectory of XCODE_ARM_ROOT
CXX_FLAGS="-arch armv7 -arch armv7s -arch arm64" SYSTEM_ROOT=${XCODE_ARM_ROOT}/SDKs/iPhoneOS7.0.sdk
cmake
call will look like this. mkdir -p build/ios cd build/ios cmake \ -DCMAKE_CXX_COMPILER=$CXX_COMPILER \ -DCMAKE_OSX_SYSROOT="$SYSTEM_ROOT" \ -DCMAKE_C_COMPILER=$C_COMPILER \ -DCMAKE_CXX_FLAGS="$CXX_FLAGS" \ -G "Unix Makefiles" \ ../../src/Shark
By the way,cmake
will do a lot of extra work for us. We only need to specify C and C ++ compilers,cmake
will find all other utilities from the same toolkit, for example,ranlib
,lipo
,ld
, etc.
i386
and x86_64
, the latter is needed for testing on a simulator of devices with 64-bit architecture, for example, “iPhone Retina (4-inch 64-bit)”.${XCODE_SIM_ROOT}/SDKs/iPhoneSimulator7.0.sdk
.-mios-simulator-version-min=7.0
flag mkdir -p build/sim cd build/sim CXX_FLAGS="-arch i386 -arch x86_64 -mios-simulator-version-min=7.0" SYSTEM_ROOT=${XCODE_SIM_ROOT}/SDKs/iPhoneSimulator7.0.sdk cmake \ -DCMAKE_CXX_COMPILER=$CXX_COMPILER \ -DCMAKE_OSX_SYSROOT="$SYSTEM_ROOT" \ -DCMAKE_C_COMPILER=$C_COMPILER \ -DCMAKE_CXX_FLAGS="$CXX_FLAGS" \ -G "Unix Makefiles" \ ../../src/Shark
cmake
will find everything else itself. mkdir -p build/osx cd build/osx cmake \ -DCMAKE_CXX_COMPILER=$CXX_COMPILER \ -DCMAKE_C_COMPILER=$C_COMPILER \ -G "Unix Makefiles" \ ../../src/Shark
cmake
make
!, - you think, but no.cmake
has a couple of features to consider.cmake
runs a test for C and C ++ compilers. Oddly enough, clang and clang ++ successfully fail this test for iOS platforms. On the Internet, there are several recommendations on how to bypass this test, for example, in the CMakeLists.txt
file, add NONE
to the project description, but this did not help me. PROJECT( shark NONE )
cmake
without specifying clang and clang ++ compilers and other options. cmake
generate a CMakeCache.txt
file and a CMakeFiles
directory. If you now run cmake
with different settings, the compilers test will not be executed this time.cmake
at least 2 times - you will think again.cmake
will issue a warning and advise you to run it again. In fact, cmake
will not say anything like that, but the ccmake
utility ccmake
provide more information. ccmake
is a console graphic interface for cmake
.cmake
, without parameters to pass the testcmake
, with the necessary parameterscmake
to make changes take effect.make
. To make things go faster, you can parallelize the assembly using the -j
flag. make -j16
libshark.a
in our hands. For every fireman, with the help of the file
utility, make sure that the resulting libraries support all the necessary architectures. $ file build/ios/libshark.a build/ios/libshark.a: Mach-O universal binary with 3 architectures build/ios/libshark.a (for architecture armv7): current ar archive random library build/ios/libshark.a (for architecture armv7s): current ar archive random library build/ios/libshark.a (for architecture cputype (16777228) cpusubtype (0)): current ar archive random library $ file build/sim/libshark.a build/sim/libshark.a: Mach-O universal binary with 2 architectures build/sim/libshark.a (for architecture i386): current ar archive random library build/sim/libshark.a (for architecture x86_64): current ar archive random library $ file build/osx/libshark.a build/osx/libshark.a: current ar archive random library
lipo
utility will cope with this task lipo
mkdir -p lib/ios $XCODE_TOOLCHAIN_BIN/lipo -create build/ios/libshark.a build/sim/libshark.a -o lib/ios/libshark.a
file lib/ios/libshark.a
) to make sure that all 5 architectures are in place.Shark.framework
directory and the necessary folder structure inside, with all the necessary symbolic links, using mkdir
and ln
for this. Shark.framework/ ├── Documentation -> Versions/Current/Documentation ├── Headers -> Versions/Current/Headers ├── Resources -> Versions/Current/Resources └── Versions ├── A │ ├── Documentation │ ├── Headers │ └── Resources └── Current -> A
Shark
. cp build/ios/libshark.a Shark.framework/Versions/A/Shark
.h
files from the src/Shark/include
to the Headers
folder inside the bundle. Then remove the unnecessary statistics.h
. This file is not needed at least because there is no corresponding INSTALL
command in the CMakeLists.txt
file. cp -r src/Shark/include/* Shark.framework/Headers/ rm Shark.framework/Headers/statistics.h
#include
directives, we will have to do this work for them.#include
directives for boost components start with boost/
, for example #include "boost/config.hpp" #include <boost/type_traits/remove_reference.hpp>
sed
editor and patch files using the following rules for all #include
directivesSharkDefs.h
with Shark/SharkDefs.h
Shark/
in the path for all components of the libraryHeaders
folder, i.e. Array, Rng, LinAlg, FileUtil, EALib, MOO-EALib, ReClaM, Mixture, TimeSeries, Fuzzy
. # "invalid character sequence" export LC_TYPE=C export LANG=C # #include # SharkDefs.h # # -E , "gnu vs non-gnu sed" components="Array|Rng|LinAlg|FileUtil|EALib|MOO-EALib|ReClaM|Mixture|TimeSeries|Fuzzy" find Shark.framework/Headers -type f -exec \ sed -E -i '' \ -e "s,#include([<\"]),#include \1,g" \ -e "s,#include([ \t])([<\"])(SharkDefs.h),#include\1\2Shark/\3,g" \ -e "s,#include([ \t])([<\"])(${components}/),#include\1\2Shark/\3,g" \ {} +
FRAMEWORK_NAME=Shark FRAMEWORK_CURRENT_VERSION=2.3.4 cat > Shark.framework/Resources/Info.plist <<EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>${FRAMEWORK_NAME}</string> <key>CFBundleIdentifier</key> <string>dk.diku.image</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>${FRAMEWORK_CURRENT_VERSION}</string> </dict> </plist> EOF
Before the release of iOS 7, namely, devices with thearm64
architecture, it was possible to create universal static libraries, and therefore frameworks, simultaneously for iOS and OSX, including a simulator. Nothing prevented packingarmv6, armv7, armv7s, i386
andx86_64
into one bold library. Devices with 64-bit architecture confused all the cards. In a “thick” library, there cannot be two layers with the same architecture, which means you cannot getx86_64
for iOS simulator of 64-bit devices andx86_64
for OS X.
Pod::Spec.new do |s| s.name = 'Shark-SDK' s.version = '2.3.4' s.license = { :type => 'GPLv2', :text => 'See https://sourceforge.net/directory/license:gpl/' } s.summary = 'iOS & OS X framework for Shark: C++ Machine Learning Library' s.description = <<-DESC SHARK provides libraries for the design of adaptive systems, including methods for linear and nonlinear optimization (eg, evolutionary and gradient-based algorithms), kernel-based algorithms and neural networks, and other machine learning techniques. DESC s.homepage = 'https://sourceforge.net/projects/shark-project/' s.author = { 'shark-admin' => 'https://sourceforge.net/u/shark-admin/profile/' } s.source = { :http => 'https://github.com/mgrebenets/shark2-iosx/releases/download/v2.3.4/Shark-SDK.tgz', :type => :tgz } s.ios.vendored_frameworks = "Shark-iOS-SDK/Shark.framework" s.osx.vendored_frameworks = "Shark-OSX-SDK/Shark.framework" s.ios.deployment_target = '6.0' s.osx.deployment_target = '10.7' end
# Podfile platform :ios, :deployment_target => '6.0' pod 'Shark-SDK' target :'shark2-osx-demo', :exclusive => true do platform :osx, :deployment_target => '10.7' pod 'Shark-SDK' end
Source: https://habr.com/ru/post/208052/
All Articles