Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundle radare2 inside the macOS app #209

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 17 additions & 40 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,39 +63,16 @@ jobs:
with:
name: iaito-amd64.deb
path: dist/debian/*/*.deb
acr-macos-x64:
runs-on: macos-13
steps:
- uses: actions/checkout@v4
with:
submodules: false # 'recursive' 'true' or 'false'
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: 3.11.x
- name: uname
run: uname -a
- name: install dependencies
run: |
brew install qt@5
echo $(brew --prefix qt@5)/bin >> $GITHUB_PATH
pip3 install meson ninja
- name: install r2
run: |
wget -q https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2-x64-${{env.R2V}}.pkg
sudo installer -pkg *.pkg -target /
- name: build iaito
run: |
./configure
make -j4
- name: packaging
run: make -C dist/macos
- uses: actions/upload-artifact@v4
with:
name: iaito-x64.dmg
path: dist/macos/iaito.dmg
acr-macos-arm64:
runs-on: macos-latest
acr-macos:
strategy:
fail-fast: false
matrix:
include:
- arch: arm64
macos: latest
- arch: x64
macos: 13
runs-on: macos-${{ matrix.macos }}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -112,18 +89,19 @@ jobs:
echo $(brew --prefix qt@5)/bin >> $GITHUB_PATH
pip3 install meson ninja
- name: install r2
working-directory: dist/macos
run: |
wget -q https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2-m1-${{env.R2V}}.pkg
sudo installer -pkg *.pkg -target /
curl -Lo radare2.pkg "https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2-${{ matrix.arch }}-${{env.R2V}}.pkg"
sudo installer -pkg radare2.pkg -target /
- name: build iaito
run: |
./configure
make -j4
make -j4 -C dist/macos app
- name: packaging
run: make -C dist/macos
run: make -C dist/macos dmg
- uses: actions/upload-artifact@v4
with:
name: iaito-arm64.dmg
name: iaito-${{ matrix.arch }}.dmg
path: dist/macos/iaito.dmg
meson:
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -220,8 +198,7 @@ jobs:
tag_name: ${{ steps.release.outputs.tag }}
needs:
- acr-linux
- acr-macos-arm64
- acr-macos-x64
- acr-macos
- w64-meson
runs-on: ubuntu-latest
steps:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,8 @@ src/out
src/translations

# macOS package
/dist/macos/radare2.pkg
/dist/macos/radare2-unpkg
/dist/macos/disk
/dist/macos/extra
/dist/macos/*.dmg
29 changes: 23 additions & 6 deletions dist/macos/Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
.PHONY: all app clean
.PHONY: all app dmg clean mrproper

all: app iaito.dmg
all: clean app dmg

app: ../../build/iaito.app
app: ../../build/iaito.app radare2-unpkg extra/r2ai
mkdir disk
cp -a ../../build/iaito.app disk/
scripts/embed-radare2.sh radare2-unpkg disk/iaito.app
cp -a extra/r2ai/decai/decai.r2.js disk/iaito.app/Contents/Resources/radare2/lib/radare2/last/
macdeployqt disk/iaito.app -verbose=2

iaito.dmg: app
dmg: app
cp doc/README.txt disk/READ_THIS_FIRST.txt
ln -fs /Applications disk/
hdiutil create -format UDZO -fs APFS -volname iaito -srcfolder disk iaito

radare2-unpkg: radare2.pkg
pkgutil --expand-full $< $@

radare2.pkg:
echo "Download first radare2.pkg from https://github.com/radareorg/radare2/releases"
@false

extra/r2ai:
mkdir -p extra
curl -L "$(shell curl -s https://api.github.com/repos/radareorg/r2ai/releases/latest | jq -r .tarball_url)" | tar -xzC extra/
cd extra && mv radareorg-r2ai-* r2ai

../../build/iaito.app:
echo "Building iaito..."
$(MAKE) -C ../..
$(MAKE) -C ../.. QMAKE_FLAGS=IAITO_BUNDLE_R2_APPBUNDLE=true

clean:
rm -rf disk iaito.dmg
rm -rf radare2-unpkg disk iaito.dmg

mrproper: clean
rm -rf radare2.pkg extra
20 changes: 4 additions & 16 deletions dist/macos/doc/README.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
IMPORTANT!

Steps to install iaito:
To install iaito you can drag and drop the application to /Applications.
But then you are required to run this commands from Terminal before you can execute for the first time.

1. First go to radare2 releases:
https://github.com/radareorg/radare2/releases/latest

2. Download the corresponding pkg file:
Apple Silicon (all models): radare2-m1-*.pkg
Intel CPU: radare2-x64-*.pkg

3. Run the pkg file either by double-click or in Terminal by running:
sudo installer -pkg radare2-*.pkg -target /

4. Drag and drop the iaito icon to /Applications.

5. Run this commands from Terminal:
sudo xattr -c /Applications/iaito.app
sudo codesign --force --deep --sign - /Applications/iaito.app
sudo xattr -c /Applications/iaito.app
sudo codesign --force --deep --sign - /Applications/iaito.app
14 changes: 14 additions & 0 deletions dist/macos/scripts/command.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

CMD=$(basename "$0")
APPDIR=$(cd "$(dirname "$0")/../../../.."; pwd)

R2_BINDIR="${APPDIR}/Contents/Helpers"
R2_LIBDIR="${APPDIR}/Contents/Frameworks"
R2_PREFIX="${APPDIR}/Contents/Resources/radare2"

export R2_BINDIR
export R2_LIBDIR
export R2_PREFIX

exec "${R2_BINDIR}/${CMD}" "$@"
64 changes: 64 additions & 0 deletions dist/macos/scripts/embed-radare2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/sh -e

R2PKGDIR="$1"
APPDIR="$2"

SCRIPTS="$(dirname "$0")"
R2DIR="${R2PKGDIR}/Payload/usr/local"
R2V=$(readlink "${R2DIR}/lib/radare2/last")

fix_binary() {
echo "Change library paths for \"$1\"..."
ARGS=$(otool -L "$1" | awk '/\/usr\/local\/lib\/libr_/{dst=$1; sub(/\/usr\/local\/lib/,"@executable_path/../Frameworks", dst); print "-change "$1" "dst}')
[ -n "$ARGS" ] && install_name_tool $ARGS "$1"
}

mkdir -p \
"${APPDIR}/Contents/Helpers" \
"${APPDIR}/Contents/Frameworks" \
"${APPDIR}/Contents/PlugIns/radare2" \
"${APPDIR}/Contents/Resources/radare2/bin" \
"${APPDIR}/Contents/Resources/radare2/lib/radare2/${R2V}/"

cp -a "${R2DIR}/bin/"* "${APPDIR}/Contents/Helpers/"
cp -a "${R2DIR}/lib/radare2/${R2V}/"*.dylib "${APPDIR}/Contents/PlugIns/radare2/"
cp -a "${R2DIR}/lib/"*.dylib "${APPDIR}/Contents/Frameworks/"
cp -a "${R2DIR}/include" "${APPDIR}/Contents/Resources/radare2/"
cp -a "${R2DIR}/share" "${APPDIR}/Contents/Resources/radare2/"
#cp -a "${R2DIR}/lib/pkgconfig" "${APPDIR}/Contents/Resources/radare2/lib/"
cp -p "${SCRIPTS}/command.sh" "${APPDIR}/Contents/Resources/radare2/bin/radare2"
cp -a "${R2DIR}/lib/radare2/last" "${APPDIR}/Contents/Resources/radare2/lib/radare2/"
#cp -a "${R2DIR}/lib/radare2/${R2V}/"*.js "${APPDIR}/Contents/Resources/radare2/lib/radare2/${R2V}/"

(
cd "${APPDIR}/Contents/MacOS"
fix_binary "iaito"
)

(
cd "${APPDIR}/Contents/Helpers"
for c in *; do
[ -L "$c" ] || fix_binary "$c"
[ "$c" != "radare2" ] && ln -s radare2 "../Resources/radare2/bin/$c"
done
)

(
LIBS=$(cd "${R2DIR}/lib"; ls *.dylib)
cd "${APPDIR}/Contents/Frameworks"
for c in $LIBS; do
[ -L "$c" ] || fix_binary "$c"
c2=$c # Resolve upto 2 link levels
[ -L "$c2" ] && c2=$(readlink "$c2")
[ -L "$c2" ] && c2=$(readlink "$c2")
ln -s "../../../Frameworks/$c2" "../Resources/radare2/lib/$c"
done
)

(
cd "${APPDIR}/Contents/PlugIns/radare2"
for c in *.dylib; do
[ -L "$c" ] || fix_binary "$c"
ln -s "../../../../../PlugIns/radare2/$c" "../../Resources/radare2/lib/radare2/${R2V}/$c"
done
)
8 changes: 5 additions & 3 deletions src/Iaito.pro
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ CONFIG+=app_bundle

CONFIG += sdk_no_version_check

unix:QMAKE_RPATHDIR += /usr/local/lib
unix:QMAKE_LFLAGS_RPATH=
unix:QMAKE_LFLAGS += "-Wl,-rpath,/usr/local/lib"
unix:!macx|macx:!IAITO_BUNDLE_R2_APPBUNDLE {
QMAKE_RPATHDIR += /usr/local/lib
QMAKE_LFLAGS_RPATH=
QMAKE_LFLAGS += "-Wl,-rpath,/usr/local/lib"
}

QMAKE_CXXFLAGS += $$(CXXFLAGS)
QMAKE_CFLAGS += $$(CFLAGS)
Expand Down
37 changes: 21 additions & 16 deletions src/IaitoApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,27 @@ IaitoApplication::IaitoApplication(int &argc, char **argv)
qputenv("R_ALT_SRC_DIR", "1");
#endif

#ifdef MACOS_R2_BUNDLED
{
auto appdir = QDir(QCoreApplication::applicationDirPath()); // Contents/MacOS
appdir.cdUp(); // Contents

auto r2prefix = appdir; // Contents
r2prefix.cd("Resources/radare2"); // Contents/Resources/radare2
qputenv("R2_PREFIX", r2prefix.absolutePath().toLocal8Bit());

auto r2bin = appdir; // Contents
r2bin.cd("Helpers"); // Contents/Helpers
auto paths = QStringList(QString::fromLocal8Bit(qgetenv("PATH")));
paths.prepend(r2bin.absolutePath());
qputenv("PATH", paths.join(QLatin1Char(':')).toLocal8Bit());

// auto sleighHome = appdir; // Contents
// sleighHome.cd("PlugIns/radare2/r2ghidra_sleigh"); // Contents/PlugIns/radare2/r2ghidra_sleigh
// qputenv("SLEIGHHOME", sleighHome.absolutePath().toLocal8Bit());
}
#endif

Core()->initialize(clOptions.enableR2Plugins);
Core()->setSettings();
Config()->loadInitial();
Expand Down Expand Up @@ -219,22 +240,6 @@ IaitoApplication::IaitoApplication(int &argc, char **argv)
}
#endif

#ifdef Q_OS_MACOS
{
auto r2prefix = QDir(QCoreApplication::applicationDirPath()); // Contents/MacOS
r2prefix.cdUp(); // Contents
r2prefix.cd("Resources/r2"); // Contents/Resources/r2

auto sleighHome = r2prefix;
sleighHome.cd("share/radare2/plugins/r2ghidra_sleigh"); // Contents/Resources/r2/share/radare2/plugins/r2ghidra_sleigh
Core()->setConfig("r2ghidra.sleighhome", sleighHome.absolutePath());

auto r2decHome = r2prefix;
r2decHome.cd("share/radare2/plugins/r2dec-js"); // Contents/Resources/r2/share/radare2/plugins/r2dec-js
qputenv("R2DEC_HOME", r2decHome.absolutePath().toLocal8Bit());
}
#endif

#ifdef IAITO_APPVEYOR_R2DEC
qputenv("R2DEC_HOME", "lib\\plugins\\r2dec-js");
#endif
Expand Down
10 changes: 1 addition & 9 deletions src/core/Iaito.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,11 @@ void IaitoCore::initialize(bool loadPlugins)

r_event_hook(core_->anal->ev, R_EVENT_ALL, cutterREventCallback, this);
#if 0
#if defined(APPIMAGE) || defined(MACOS_R2_BUNDLED)
auto prefix = QDir(QCoreApplication::applicationDirPath());
#ifdef APPIMAGE
auto prefix = QDir(QCoreApplication::applicationDirPath());
// Executable is in appdir/bin
prefix.cdUp();
qInfo() << "Setting r2 prefix =" << prefix.absolutePath() << " for AppImage.";
#else // MACOS_R2_BUNDLED \
// Executable is in Contents/MacOS, prefix is Contents/Resources/r2
prefix.cdUp();
prefix.cd("Resources");
prefix.cd("r2");
qInfo() << "Setting r2 prefix =" << prefix.absolutePath() << " for macOS Application Bundle.";
#endif
setConfig("dir.prefix", prefix.absolutePath());

auto pluginsDir = prefix;
Expand Down
Loading