123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- # -*- mode: sh; tab-width: 4; coding: utf-8 -*-
- # vim: ts=4 noet ai ft=sh
- # Build a .xpi package.
- # This file is part of JPM.sh.
- # Copyright (C) 2016 the Desktopd developers
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU Affero General Public License as
- # published by the Free Software Foundation, either version 3 of the
- # License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- # Dependencies
- . "$gLibDir/tmpdir.sh"
- . "$gLibDir/git.sh"
- . "$gLibDir/xml.sh"
- . "$gLibDir/crypto.sh"
- . "$gLibDir/json.sh"
- . "$gLibDir/code-minifier.sh"
- # jpmXpiGetId
- jpmXpiGetId () {
- printf %s "@${addon_id}"
- }
- # jpmXpiFormatVersion <version>
- jpmXpiFormatVersion () {
- printf %s "$1" | sed 's/[^-._a-zA-Z0-9]*//g'
- }
- # jpmXpiBuild <isProdBuild> [<printPackageName>]
- # Note: Intentional use of subshell
- jpmXpiBuild () (
- isProdBuild=$1
- printPackageName=$2
-
- [ -d "$addon_src_dir" ] || {
- jpmConsoleError "xpi-build: No such directory: $addon_src_dir"
- exit 1 # Exits this subshell
- }
- srcDir=`cd "$addon_src_dir" ; pwd`
-
- # Normalize build environment
- unset LANGUAGE DISPLAY USER
- LANG=C
- LC_ALL=C
-
- [ "$addon_main_path" ] || addon_main_path=main.js
-
- tmpDir=`jpmTempDirCreate`
- [ -d "$tmpDir" ] || {
- jpmConsoleError "xpi-build: Failed to create a temporary directory"
- exit 1 # Exits this subshell
- }
-
- tmpHomeDir="$tmpDir/home"
- tmpTmpDir="$tmpDir/tmp"
- mkdir -p "$tmpHomeDir" "$tmpTmpDir" >&2
-
- TMP="$tmpTmpDir"
- TMPDIR="$tmpTmpDir"
- TEMP="$tmpTmpDir"
- TEMPDIR="$tmpTmpDir"
- HOME="$tmpHomeDir"
- export TMP TMPDIR TEMP TEMPDIR HOME
-
- # Create build directory
- buildDir="$tmpDir/build"
- mkdir -p "$buildDir" >&2
- cp -r "$srcDir"/* "$buildDir/" >&2
-
- versionGit=''
- gitHash=`jpmGitGetHash`
- [ "$gitHash" ] && {
- versionGit="+git.`printf %s "$gitHash" | head -c8`"
- uncomitted=''
- jpmGitUncomitted && {
- versionGit=${versionGit}+uncommitted
- uncomitted=+uncomitted
- }
- printf '//Build:git-%s%s' "$gitHash" "$uncomitted" \
- >> "$buildDir/${addon_main_path}"
-
- [ "$addon_release_phase" = stable ] && versionGit=''
- }
- version=${addon_version}${versionGit}
-
- [ "$isProdBuild" ] && {
- jpmConsoleLog "xpi-build: Excluding development files..."
- rm -fr "$buildDir/debug.js" "$buildDir/data/debug" >&2
-
- preprocess_sed_html='s,^\s*<!--!_DEBUGONLY_!.*-->\s*,,'
- find "$buildDir" \( -name '*.html' -or -name '*.xhtml' \) -exec \
- sh -c 'sed "$1" < "$2" > "$2.tmp" && mv -f "$2.tmp" "$2"' \
- -- "$preprocess_sed_html" {} \;
-
- preprocess_sed='s,^\s*/\*!_DEBUGONLY_!.*\*/.*,,'
- find "$buildDir" \( -name '*.js' -or -name '*.css' \) -exec \
- sh -c 'sed "$1" < "$2" > "$2.tmp" && mv -f "$2.tmp" "$2"' \
- -- "$preprocess_sed" {} \;
-
- # TODO: implement optional minification here
- [ "$addon_minify_html" ] && jpmMinifyHtml "$buildDir"
- [ "$addon_minify_css" ] && jpmMinifyCss "$buildDir"
- [ "$addon_minify_js" ] && jpmMinifyJs "$buildDir"
- :;} || jpmConsoleLog "xpi-build: Debugging build enabled."
-
- addon_preferences_json=''
- [ -f "${addon_preferences_json_path}" ] && \
- addon_preferences_json=`cat "${addon_preferences_json_path}"`
-
- addon_translators_json=''
- [ -f "${addon_translators_json_path}" ] && \
- addon_translators_json=`cat "${addon_translators_json_path}"`
-
- cd "$buildDir" >&2
- jpmConsoleLog "xpi-build: Generating the necessary files..."
- id=`jpmXpiGetId`
- jpmXpiGenInstallRdf "$id" "$version" > ./install.rdf
- cp "$gDepsDir/jpm-core/data/bootstrap.js" ./bootstrap.js >&2
-
- jpmXpiGenPackageJson "$id" "$version" > ./package.json
-
-
- jpmConsoleLog "xpi-build: Zipping files..."
- # Skipping directory entries
- zip -9rXD ../build.zip ./* >/dev/null
- cd .. >&2
-
-
- [ "$isProdBuild" ] && [ -z "$JPM_SH_RAW_PACKAGING" ] && {
- # Postprocessing
- which advzip >/dev/null && {
- jpmConsoleLog "xpi-build: Recompressing..."
- advzip -z -4 -i 500 ./build.zip >/dev/null
- :;} || jpmConsoleNotice "xpi-build: Skipping: AdvanceCOMP (not found)"
-
- which strip-nondeterminism >/dev/null && {
- jpmConsoleLog "xpi-build: Trying to strip nondeterminism (experimental)..."
- strip-nondeterminism -t zip ./build.zip >&2
- } || {
- jpmConsoleWarn "xpi-build: NOTE: Deterministic build disabled (strip-nondeterminism needed)..."
- }
-
- jpmConsoleNotice "xpi-build: SHA2-256: `jpmCryptoSha256 < ./build.zip`"
- }
-
-
- # Output the built package
- jpmConsoleLog "xpi-build: Streaming the built package..."
- cat ./build.zip
-
-
- # Clean up temporary files
- jpmConsoleLog "xpi-build: Cleaning up temporary files to build .xpi ..."
- cd "$srcDir/.." >&2
- rm -fr "$tmpDir" >&2
-
-
- # Print filename
- [ "$printPackageName" ] && printf %s "${id}-${version}" >&3
- )
- # jpmXpiGenPackageJson <id> <version>
- jpmXpiGenPackageJson () {
- versionF=`jpmXpiFormatVersion "$2"`
-
- printf '{"title":%s,"name":%s,"id":%s,"version":%s' \
- "`jpmJsonArgToStringValue "$addon_name"`" \
- "`jpmJsonArgToStringValue "$addon_id"`" \
- "`jpmJsonArgToStringValue "$1"`" \
- "`jpmJsonArgToStringValue "$versionF"`"
-
- printf ',"description":%s,"main":%s,"author":%s,"license":%s' \
- "`jpmJsonArgToStringValue "$addon_description"`" \
- "`jpmJsonArgToStringValue "$addon_main_path"`" \
- "`jpmJsonArgToStringValue "$addon_author"`" \
- "`jpmJsonArgToStringValue "$addon_license_id"`"
-
- printf ',"engines":{"firefox":%s' \
- "`jpmJsonArgToStringValue "$addon_firefox_version"`"
-
- [ "$addon_fennec_version" ] && printf ',"fennec":%s' \
- "`jpmJsonArgToStringValue "$addon_fennec_version"`"
-
- [ "$addon_thunderbird_version" ] && printf ',"thunderbird":%s' \
- "`jpmJsonArgToStringValue "$addon_thunderbird_version"`"
-
- [ "$addon_seamonkey_version" ] && printf ',"seamonkey":%s' \
- "`jpmJsonArgToStringValue "$addon_seamonkey_version"`"
-
- printf '}'
- printf ',"permissions":{"multiprocess":true'
- [ "$addon_support_private_browsing" ] && printf ',"private-browsing":true'
- printf '}'
-
- [ "$addon_preferences_json" ] && printf ',"preferences":%s' \
- "`jpmJsonNormalizeArg "$addon_preferences_json"`"
-
- [ "$addon_translators_json" ] && printf ',"translators":%s' \
- "`jpmJsonNormalizeArg "$addon_translators_json"`"
-
- [ "$addon_unpack" ] && printf ',"unpack":true'
-
- printf '}'
- }
- # @private
- # jpmXpiGenInstallRdfTarget <uuid> <minVersion> <maxVersion>
- jpmXpiGenInstallRdfTarget () {
- cat <<RDF
- <em:targetApplication><Description>
- <em:id>${1}</em:id>
- <em:minVersion>${2}</em:minVersion>
- <em:maxVersion>${3}</em:maxVersion>
- </Description></em:targetApplication>
- RDF
- }
- # jpmXpiGenInstallRdf <id> <version>
- jpmXpiGenInstallRdf () {
- uuidFirefox='{ec8030f7-c20a-464f-9b0e-13a3a9e97384}'
- uuidFennec='{aa3c5121-dab2-40e2-81ca-7ea25febc110}'
- uuidThunderbird='{3550f703-e582-4d05-9a08-453d09bdfdc6}'
- uuidSeamonkey='{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}'
- uuidPaleMoon='{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}'
- versionF=`jpmXpiFormatVersion "$2"`
-
- # XXX: hardcoded
- targetFirefox=`jpmXpiGenInstallRdfTarget "$uuidFirefox" '38.0a1' '*'`
- targetFennec=''
- targetThunderbird=''
- targetSeamonkey=''
- [ "${addon_fennec_version}" ] && \
- targetFennec=`jpmXpiGenInstallRdfTarget "$uuidFennec" '38.0a1' '*'`
- [ "${addon_thunderbird_version}" ] && \
- targetThunderbird=`jpmXpiGenInstallRdfTarget "$uuidThunderbird" '38.0a1' '48.*'`
- [ "${addon_seamonkey_version}" ] && \
- targetSeamonkey=`jpmXpiGenInstallRdfTarget "$uuidSeamonkey" '2.38' '2.47.*'`
-
- # XXX Experimental: Be careful!
- [ "${addon_palemoon_version}" ] && \
- targetPaleMoon=`jpmXpiGenInstallRdfTarget "$uuidPaleMoon" '25.0' '26.*'`
-
- cat <<RDF
- <?xml version="1.0" encoding="utf-8"?>
- <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
- <Description about="urn:mozilla:install-manifest">
- <em:id>`jpmXmlEscapeArg "$1"`</em:id>
- <em:type>2</em:type>
- <em:bootstrap>true</em:bootstrap>
- <em:unpack>`jpmToBoolValue "${addon_unpack}"`</em:unpack>
- <em:version>`jpmXmlEscapeArg "$versionF"`</em:version>
- <em:name>`jpmXmlEscapeArg "${addon_name}"`</em:name>
- <em:description>`jpmXmlEscapeArg "${addon_description}"`</em:description>
- <em:creator>`jpmXmlEscapeArg "${addon_author}"`</em:creator>
- <em:optionsURL>data:text/xml,<placeholder/></em:optionsURL>
- <em:optionsType>2</em:optionsType>
- <em:multiprocessCompatible>true</em:multiprocessCompatible>
- ${targetFirefox}${targetFennec}${targetThunderbird}${targetSeamonkey}${targetPaleMoon}
- </Description>
- </RDF>
- RDF
- }
|