Skip to content

Commit

Permalink
[7.x][ML] Changes to allow native compilation on ARM Macs (elastic#1664)
Browse files Browse the repository at this point in the history
This allows native compilation on a Mac containing the
Apple M1 CPU.

PR builds will currently NOT test this platform, nor even
check compilation for it.  Release manager will not build
it either.  Still, it is a step in the right direction to
be able to compile locally for it.

Cross compilation for this platform is still NOT possible.
This can be investigated in a followup PR.  (Supporting
this actually requires considerable changes to the cross
compilation framework, as it currently contains a quite
deeply embedded assumption that macOS is x86_64 only.)

The last dregs of Linux MUSL port code are also removed.
(Most support for MUSL was removed previously, but a few
bits were missed.)

Backport of elastic#1651
  • Loading branch information
droberts195 authored Jan 13, 2021
1 parent 1b4459d commit 752dd03
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 50 deletions.
7 changes: 6 additions & 1 deletion 3rd_party/3rd_party.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ case `uname` in
Darwin)
BOOST_LOCATION=/usr/local/lib
BOOST_COMPILER=clang
BOOST_EXTENSION=mt-x64-1_71.dylib
if [ `uname -m` = x86_64 ] ; then
BOOST_ARCH=x64
else
BOOST_ARCH=a64
fi
BOOST_EXTENSION=mt-${BOOST_ARCH}-1_71.dylib
BOOST_LIBRARIES='atomic chrono date_time filesystem iostreams log log_setup program_options regex system thread'
XML_LOCATION=
GCC_RT_LOCATION=
Expand Down
38 changes: 35 additions & 3 deletions build-setup/macos.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Machine Learning Build Machine Setup for macOS

These same instructions should work for native compilation on both x86_64 and aarch64 architectures.

To ensure everything is consistent for redistributable builds we build all redistributable components from source.

NOTE: if you upgrade macOS then Xcode may need to be re-installed. Please ensure your Xcode is still valid after upgrades.
Expand Down Expand Up @@ -27,11 +29,12 @@ Note, that bash doesn't read `~/.bashrc` for login shells (which is what you get
Most of the tools are built via a GNU "configure" script. There are some environment variables that affect the behaviour of this. Therefore, when building ANY tool on macOS, set the following environment variables:

```
export SSEFLAGS=`[ $(uname -m) = x86_64 ] && echo -msse4.2`
export CPP='clang -E'
export CC=clang
export CFLAGS='-O3 -msse4.2'
export CFLAGS="-O3 $SSEFLAGS"
export CXX='clang++ -std=c++14 -stdlib=libc++'
export CXXFLAGS='-O3 -msse4.2'
export CXXFLAGS="-O3 $SSEFLAGS"
export CXXCPP='clang++ -std=c++14 -E'
export LDFLAGS=-Wl,-headerpad_max_install_names
unset CPATH
Expand All @@ -50,7 +53,8 @@ The first major piece of development software to install is Apple's development
- If you are using El Capitan, you must install Xcode 8.2.x
- If you are using Sierra, you must install Xcode 9.2.x
- If you are using High Sierra, you must install Xcode 10.1.x
- If you are using Mojave, you must install Xcode 10.3.x
- If you are using Mojave, you must install Xcode 11.3.x
- If you are using Catalina or Big Sur, you must install Xcode 12.3.x or above

Older versions of Xcode are installed by dragging the app from the `.dmg` file to the `/Applications` directory on your Mac (or if you got it from the App Store it will already be in the `/Applications` directory). More modern versions of Xcode are distributed as a `.xip` file; simply double click the `.xip` file to expand it, then drag `Xcode.app` to your `/Applications` directory.

Expand Down Expand Up @@ -92,6 +96,34 @@ to:
(3ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
```

Then edit `tools/build/src/tools/darwin.jam` and change:

```
case arm :
{
if $(instruction-set) {
options = -arch$(_)$(instruction-set) ;
} else {
options = -arch arm ;
}
}
```

to:

```
case arm :
{
if $(instruction-set) {
options = -arch$(_)$(instruction-set) ;
} else if $(address-model) = 64 {
options = -arch arm64 ;
} else {
options = -arch arm ;
}
}
```

To complete the build, type:

```
Expand Down
20 changes: 10 additions & 10 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,28 @@ if (cppCrossCompile != '' && cppCrossCompile != 'macosx' && cppCrossCompile != '
throw new GradleException("CPP_CROSS_COMPILE property must be empty, 'macosx' or 'aarch64'")
}

String osArch = System.properties['os.arch']
// Some versions of Java report hardware architectures that
// don't match other tools - these need to be normalized
if (osArch == 'amd64') {
osArch = 'x86_64'
} else if (osArch == 'arm64') {
osArch = 'aarch64'
}
String artifactClassifier;
if (isWindows) {
artifactClassifier = 'windows-x86_64'
} else if (isMacOsX || cppCrossCompile == 'macosx') {
artifactClassifier = 'darwin-x86_64'
artifactClassifier = 'darwin-' + osArch
} else if (cppCrossCompile != '') {
artifactClassifier = 'linux-' + cppCrossCompile
} else {
String osArch = System.properties['os.arch']
// Some versions of Java report hardware architectures that
// don't match other tools - these need to be normalized
if (osArch == 'amd64') {
osArch = 'x86_64'
} else if (osArch == 'i386') {
osArch = 'x86'
}
artifactClassifier = 'linux-' + osArch
}

// Always do the C++ build using bash (Git bash on Windows)
project.ext.bash = isWindows ? "C:\\Program Files\\Git\\bin\\bash" : "/bin/bash"
project.ext.make = (isMacOsX || isWindows) ? "gnumake" : (isLinux ? "make" : "gmake")
project.ext.make = (isMacOsX || isWindows) ? "gnumake" : "make"
project.ext.numCpus = Runtime.runtime.availableProcessors()
project.ext.makeEnvironment = [ 'CPP_CROSS_COMPILE': cppCrossCompile,
'VERSION_QUALIFIER': versionQualifier,
Expand Down
2 changes: 1 addition & 1 deletion include/api/CInferenceModelMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class API_EXPORT CInferenceModelMetadata {
bool supplied)
: s_HyperparameterName(hyperparameterName), s_Value(value),
s_AbsoluteImportance(absoluteImportance),
s_RelativeImportance(relativeImportance), s_Supplied(supplied){};
s_RelativeImportance(relativeImportance), s_Supplied(supplied) {}
std::string s_HyperparameterName;
double s_Value;
double s_AbsoluteImportance;
Expand Down
20 changes: 7 additions & 13 deletions lib/core/CUname.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,18 @@ std::string CUname::mlPlatform() {
// downloads. For *nix platforms this is more-or-less `uname -s`-`uname -m`
// converted to lower case. However, for consistency between different
// operating systems on the same architecture "amd64"/"i86pc" are replaced
// with "x86_64" and "i386"/"i686" with "x86".
// with "x86_64", "i386"/"i686" with "x86" and "arm64" with "aarch64".
//
// Assuming the current platform is supported this name will be one of:
// - darwin-aarch64
// - darwin-x86_64
// - linux-aarch64
// - linux-x86_64
//
// For an unsupported platform it will be something different, but hopefully
// still recognisable.

std::string os(CStringUtils::toLower(name.sysname));
#ifdef _CS_GNU_LIBC_VERSION
if (os == "linux") {
char buffer[128] = {'\0'};
// This isn't great because it's assuming that any C runtime library
// that doesn't identify itself as glibc is musl, but it's hard to do
// better as musl goes out of its way to be hard to detect
if (::confstr(_CS_GNU_LIBC_VERSION, buffer, sizeof(buffer)) == 0 ||
::strstr(buffer, "glibc") == 0) {
os += "-musl";
}
}
#endif

const std::string& machine = CStringUtils::toLower(name.machine);
if (machine.length() == 4 && machine[0] == 'i' && machine[2] == '8' &&
Expand All @@ -109,6 +99,10 @@ std::string CUname::mlPlatform() {
return os + "-x86_64";
}

if (machine == "arm64") {
return os + "-aarch64";
}

return os + '-' + machine;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/maths/unittest/CBoostedTreeTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ BOOST_AUTO_TEST_CASE(testBinomialLogisticRegression) {
LOG_DEBUG(<< "log relative error = "
<< maths::CBasicStatistics::mean(logRelativeError));

BOOST_TEST_REQUIRE(maths::CBasicStatistics::mean(logRelativeError) < 0.65);
BOOST_TEST_REQUIRE(maths::CBasicStatistics::mean(logRelativeError) < 0.67);
meanLogRelativeError.add(maths::CBasicStatistics::mean(logRelativeError));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/maths/unittest/CLinearAlgebraTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(testVectorNx1) {
maths::CVectorNx1<double, 4> sy = s * y;
LOG_DEBUG(<< "Sy = " << sy);
for (std::size_t i = 0u; i < 4; ++i) {
BOOST_REQUIRE_EQUAL(expected(i), sy(i));
BOOST_REQUIRE_CLOSE_ABSOLUTE(expected(i), sy(i), 1e-14);
}
}
}
Expand Down
36 changes: 25 additions & 11 deletions mk/macosx.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

OS=MacOSX

CPP_PLATFORM_HOME=$(CPP_DISTRIBUTION_HOME)/platform/darwin-x86_64
HARDWARE_ARCH:=$(shell uname -m | sed 's/arm64/aarch64/')
CPP_PLATFORM_HOME=$(CPP_DISTRIBUTION_HOME)/platform/darwin-$(HARDWARE_ARCH)
ML_APP_NAME=controller
APP_CONTENTS=$(ML_APP_NAME).app/Contents

Expand All @@ -24,9 +25,13 @@ COVERAGE=--coverage
endif
endif

ifeq ($(HARDWARE_ARCH),x86_64)
ARCHCFLAGS=-msse4.2
endif

SDK_PATH:=$(shell xcrun --show-sdk-path)
# Start by enabling all warnings and then disable the really pointless/annoying ones
CFLAGS=-g $(OPTCFLAGS) -msse4.2 -fstack-protector -Weverything -Werror-switch -Wno-deprecated -Wno-disabled-macro-expansion -Wno-documentation-deprecated-sync -Wno-documentation-unknown-command -Wno-float-equal -Wno-gnu -Wno-missing-prototypes -Wno-padded -Wno-sign-conversion -Wno-unreachable-code -Wno-used-but-marked-unused $(COVERAGE)
CFLAGS=-g $(OPTCFLAGS) $(ARCHCFLAGS) -fstack-protector -Weverything -Werror-switch -Wno-deprecated -Wno-disabled-macro-expansion -Wno-documentation-deprecated-sync -Wno-documentation-unknown-command -Wno-float-equal -Wno-gnu -Wno-missing-prototypes -Wno-padded -Wno-poison-system-directories -Wno-sign-conversion -Wno-unreachable-code -Wno-used-but-marked-unused $(COVERAGE)
CXXFLAGS=$(CFLAGS) -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-global-constructors -Wno-undefined-reinterpret-cast -Wno-unused-member-function -Wno-weak-vtables
CPPFLAGS=-isystem $(CPP_SRC_HOME)/3rd_party/include -isystem /usr/local/include -D$(OS) $(OPTCPPFLAGS)
ANALYZEFLAGS=--analyze
Expand All @@ -46,21 +51,30 @@ RESOURCES_DIR=$(APP_CONTENTS)/Resources
LOCALLIBS=
NETLIBS=
BOOSTVER=1_71
ifeq ($(HARDWARE_ARCH),x86_64)
BOOSTARCH=x64
else
BOOSTARCH=a64
endif
BOOSTCLANGVER:=$(shell $(CXX) --version | grep ' version ' | sed 's/.* version //' | awk -F. '{ print $$1$$2; }')
# Use -isystem instead of -I for Boost headers to suppress warnings from Boost
BOOSTINCLUDES=-isystem /usr/local/include/boost-$(BOOSTVER)
BOOSTCPPFLAGS=-DBOOST_ALL_DYN_LINK -DBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
BOOSTLOGLIBS=-lboost_log-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTLOGSETUPLIBS=-lboost_log_setup-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTREGEXLIBS=-lboost_regex-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTIOSTREAMSLIBS=-lboost_iostreams-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTPROGRAMOPTIONSLIBS=-lboost_program_options-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTTHREADLIBS=-lboost_thread-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER) -lboost_system-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTFILESYSTEMLIBS=-lboost_filesystem-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER) -lboost_system-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTDATETIMELIBS=-lboost_date_time-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTTESTLIBS=-lboost_unit_test_framework-clang-darwin$(BOOSTCLANGVER)-mt-x64-$(BOOSTVER)
BOOSTLOGLIBS=-lboost_log-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTLOGSETUPLIBS=-lboost_log_setup-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTREGEXLIBS=-lboost_regex-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTIOSTREAMSLIBS=-lboost_iostreams-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTPROGRAMOPTIONSLIBS=-lboost_program_options-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTTHREADLIBS=-lboost_thread-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER) -lboost_system-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTFILESYSTEMLIBS=-lboost_filesystem-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER) -lboost_system-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTDATETIMELIBS=-lboost_date_time-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
BOOSTTESTLIBS=-lboost_unit_test_framework-clang-darwin$(BOOSTCLANGVER)-mt-$(BOOSTARCH)-$(BOOSTVER)
RAPIDJSONINCLUDES=-isystem $(CPP_SRC_HOME)/3rd_party/rapidjson/include
ifeq ($(HARDWARE_ARCH),x86_64)
RAPIDJSONCPPFLAGS=-DRAPIDJSON_HAS_STDSTRING -DRAPIDJSON_SSE42
else
RAPIDJSONCPPFLAGS=-DRAPIDJSON_HAS_STDSTRING -DRAPIDJSON_NEON
endif
EIGENINCLUDES=-isystem $(CPP_SRC_HOME)/3rd_party/eigen
EIGENCPPFLAGS=-DEIGEN_MPL2_ONLY -DEIGEN_MAX_ALIGN_BYTES=32
XMLINCLUDES=-isystem $(SDK_PATH)/usr/include/libxml2
Expand Down
10 changes: 1 addition & 9 deletions set_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ case `uname` in

Darwin)
SIMPLE_PLATFORM=macos
BUNDLE_PLATFORM=darwin-x86_64
BUNDLE_PLATFORM=darwin-`uname -m | sed 's/arm64/aarch64/'`
;;

Linux)
Expand Down Expand Up @@ -91,10 +91,6 @@ case $SIMPLE_PLATFORM in
PATH=/usr/local/gcc75/bin:/usr/bin:/bin:/usr/local/gcc75/sbin:/usr/sbin:/sbin:/usr/local/bin
;;

linux-musl)
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
;;

macos)
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
;;
Expand All @@ -120,10 +116,6 @@ case $SIMPLE_PLATFORM in
export LD_LIBRARY_PATH=/usr/local/gcc75/lib64:/usr/local/gcc75/lib:/usr/lib:/lib
;;

linux-musl)
export LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/usr/lib:/lib
;;

windows)
# On Windows there's no separate library path - $PATH is used
PATH=$CPP_PLATFORM_HOME/bin:$PATH:$ROOT/usr/local/lib
Expand Down

0 comments on commit 752dd03

Please sign in to comment.