diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07995ab0..c34b618c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: @@ -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 }} @@ -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: diff --git a/.gitignore b/.gitignore index 340e3d5c..6b1246dd 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/dist/macos/Makefile b/dist/macos/Makefile index 025390a0..fd0fcb2a 100644 --- a/dist/macos/Makefile +++ b/dist/macos/Makefile @@ -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 diff --git a/dist/macos/doc/README.txt b/dist/macos/doc/README.txt index 0ee3f261..388a08e9 100644 --- a/dist/macos/doc/README.txt +++ b/dist/macos/doc/README.txt @@ -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 diff --git a/dist/macos/scripts/command.sh b/dist/macos/scripts/command.sh new file mode 100755 index 00000000..aa247252 --- /dev/null +++ b/dist/macos/scripts/command.sh @@ -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}" "$@" diff --git a/dist/macos/scripts/embed-radare2.sh b/dist/macos/scripts/embed-radare2.sh new file mode 100755 index 00000000..f3f98c54 --- /dev/null +++ b/dist/macos/scripts/embed-radare2.sh @@ -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 +) diff --git a/src/Iaito.pro b/src/Iaito.pro index 92f8e9b9..e13b9ad6 100644 --- a/src/Iaito.pro +++ b/src/Iaito.pro @@ -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) diff --git a/src/IaitoApplication.cpp b/src/IaitoApplication.cpp index 59e74d90..172a5a7f 100644 --- a/src/IaitoApplication.cpp +++ b/src/IaitoApplication.cpp @@ -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(); @@ -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 diff --git a/src/core/Iaito.cpp b/src/core/Iaito.cpp index a6ddb2f4..db587338 100644 --- a/src/core/Iaito.cpp +++ b/src/core/Iaito.cpp @@ -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;