BrightSpots / rcv

Ranked Choice Voting Universal Tabulator
Mozilla Public License 2.0
72 stars 19 forks source link

Figure out how to create distributions for Windows, Linux, and MacOS on any system #282

Closed HEdingfield closed 1 year ago

HEdingfield commented 5 years ago

Versions created using Gradle's distZip or jlink tasks are platform-specific due to the way JavaFX libraries are downloaded. If you try to run a version built on a Mac in Windows or Linux, for example, you get:

Graphics Device initialization failed for : d3d, sw Error initializing QuantumRenderer: no suitable pipeline found java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found

It should be possible to set up a separate zip dist for each OS even without actually being on that OS by doing something synthesized from the following:

See also:

HEdingfield commented 5 years ago

Addressing #57 using jpackage may make this a moot point.

HEdingfield commented 5 years ago

Attempted to use targetPlatform to generate for all three platforms after downloading the JDKs for each of them (see build.gradle excerpt I used below). The MacOS version didn't work when @tarheel tried. The one I generated on Linux gave:

~/Downloads/rcv-macOS/bin $ ./java -bash: ./java: cannot execute binary file

The one I generated on Windows gave:

~/Downloads/rcv-macOS $ bin/rcv bin/rcv: line 3: bin/java: cannot execute binary file

Could switch focus to creating a .jar and figuring out how to include the right OpenJFX libraries, but this seems like a step backwards. Hoping we can just get jpackage working (issue #57) sometime in the near future to handle this (e.g. once we move to JDK 13 or 14). In the meantime, we'll just need to generate each image on its native OS.

build.gradle excerpt:

// ### jlink plugin settings
jlink {
    imageDir = file(JLINK_DIR)
    imageZip = file(JLINK_DIR + ".zip")
    addOptions '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'
    mergedModule {
        requires "java.xml"
    }
    launcher {
        name = "rcv"
    }
    targetPlatform('lin', 'C:\\Program Files\\Java\\openjdk-12.0.1_linux-x64_bin\\jdk-12.0.1')
    targetPlatform('win', 'C:\\Program Files\\Java\\jdk-12.0.1')
    targetPlatform('mac', 'C:\\Program Files\\Java\\openjdk-12.0.1_osx-x64_bin\\jdk-12.0.1.jdk')
}

def docsToCopy = copySpec {
    from("$projectDir/") {
        include "README.md", "LICENSE"
    }
}

def sampleInputToCopy = copySpec {
    includeEmptyDirs = false
    from("$projectDir/src/test/resources/network/brightspots/rcv/test_data") {
        include "2015_portland_mayor/2015_portland_mayor_config.json"
        include "2015_portland_mayor/2015_portland_mayor_cvr.xlsx"
        include "sample_interactive_tiebreak/sample_interactive_tiebreak_config.json"
        include "sample_interactive_tiebreak/sample_interactive_tiebreak_sequential_config.json"
        include "sample_interactive_tiebreak/sample_interactive_tiebreak_cvr.xlsx"
        include "precinct_example/precinct_example_config.json"
        include "precinct_example/precinct_example_cvr.xlsx"
        exclude "output"
        exclude "**/*expected*"
    }
}

tasks.jlink.doLast {
    [JLINK_DIR + "/rcv-lin/docs", JLINK_DIR + "/rcv-win/docs", JLINK_DIR + "/rcv-mac/docs"].each { dest ->
        copy {
            with docsToCopy
            into dest
        }
    }
    [JLINK_DIR + "/rcv-lin/sample_input", JLINK_DIR + "/rcv-win/sample_input", JLINK_DIR + "/rcv-mac/sample_input"].each { dest ->
        copy {
            with sampleInputToCopy
            into dest
        }
    }
}
HEdingfield commented 5 years ago

Strange caveat to note: after creating jlink on Linux, the file size was huge. I had to unzip, then run: $ strip -p --strip-unneeded rcv/lib/server/libjvm.so And then replace that file in the zip to bring file size down from 200 MB to 50 MB

Found out about this here: https://github.com/docker-library/openjdk/issues/217

HEdingfield commented 1 year ago

@artoonie solved this nicely with #658 by creating a GitHub action that does builds for all platforms for us.