J2objc Packager for Gradle

Gradle plugin and libraries for J2objc development


Basic Quickstart / Tutorials


Config J2objc Runtime

View GitHub

Doppl Project

Stack Overflow j2objc  / j2objc-gradle

Made by


See other tutorials in menu under “Basic Quickstart / Tutorials”

The code here can be found in the ‘testing’ branch of the sample app repo.

Along with translating your shared code, you can translate tests to Objective-C and run them in Xcode. The test translation works in a very similar way to the main shared code translation. The files matched with j2objcConfig’s translatePattern are put through j2objc.

A separate podspec is created for test support: testj2objclib.podspec.

Xcode Config

Inside Xcode, we actually create a separate application target, ‘iosTestOnly’, rather than putting tests in a unit test target. Cocoapods doesn’t allow local podspecs to depend on other local podspecs, so to avoid dependency issues, create a separate application target.

platform :ios, '9.0'

install! 'cocoapods',
           :deterministic_uuids => false

target 'ios' do
  pod 'j2objclib', :path => '../app'

target 'iosTestOnly' do
  pod 'testj2objclib', :path => '../app'

Doppl Testing Support

There is a testing support package that is part of the Doppl suite which we’ll be using to assist in running tests. You can either pass in a list of tests to run directly, or give the method a filename which contains a list of tests to run.

In the Xcode sample project, see iosTestOnly/ViewController.swift.

import UIKit
import testj2objclib

class ViewController: UIViewController {
    override func viewDidLoad() {
        CoTouchlabDopplTestingDopplJunitTestHelper.runResource(with: "j2objcTests.txt")

The file ‘j2objcTests.txt’ is generated by the Gradle plugin. It lists tests that are matched with ‘translatePattern’ and also match the filename pattern “**/*Test.java”. If you change this value in j2objcConfig by setting testIdentifier, although most projects Seem to follow the *Test.java convention.

j2objcConfig {
    translatePattern {
        include '**/shared/**'
    testIdentifier {

The file ‘j2objcTests.txt’ will be in the build directory, and needs to be manually added to Xcode for it to be visible.


When building and running tests its generally easier to run them from AppDelegate or ViewController, because the log output will go into the log panel, but to automate builds easier, you can call tests from an XCTestCase.

import XCTest
import testj2objclib

class iosTestOnlyTests: XCTestCase {  
    func testJ2objcCode() {
        XCTAssertEqual(CoTouchlabDopplTestingDopplJunitTestHelper.runResource(with: "j2objcTests.txt"), 0)

You can also automate the test running process once it’s set up in Xcode with something like the following:

task runIOSTests(type:Exec, dependsOn: 'j2objcBuild') {
    workingDir '../ios'
    commandLine 'xcodebuild', 'test', '-workspace', 'ios.xcworkspace', '-scheme', 'iosTestOnly', '-destination', 'platform=iOS Simulator,name=iPhone 7,OS=latest'

Continuous Integration Options

We learned about Microsoft App Center at Droidcon Boston 2018 and thought we’d give it a try.

Because the Gradle J2objc Plugin now automatically downloads the J2objc runtime, setting up CI servers should be easier, assuming the CI has access to both Gradle and iOS/Xcode build tools.

Fortunately for us, it appears MS App Center does have those available.

Add a file in the ios folder for a post-clone build step, called ‘appcenter-post-clone.sh’, and put the following in to create the Objective-C

cd ..
./gradlew j2objcBuild

This will download J2objc and run the translation step. It is not fast, however. Just this build takes about 10 minutes. If you need fast, you’ll need to set up something on a dedicated server.

To run CI, set up the project as an Objective-C/Swift project. Make sure to select this branch (testing). Select the Xcode workspace and target. Make sure ‘Run XCTest tests’ is enabled. It should look like this.

App Center Setup