Android の apk 出力で Unsupported major.minor version 52.0 エラー
出力する apk ファイルの量が多いので、コマンドラインから gradle 使ってビルドをすることが多いけど、今回急に次のエラーが出て戸惑った。
A problem occurred evaluating project ':app'. > java.lang.UnsupportedClassVersionError: me/tatarka/RetrolambdaPlugin : Unsupported major.minor version 52.0
結論だけ言えば、java8 を使えば解消される。 以下が詳しくて助かった。
Androidアプリのビルドで「Unsupported major.minor version 52.0」のビルドエラーが発生する
webpack をサクッと使う手順
- 0. ディレクトリとテストファイルの準備
- 1. package.json を作る
- 2. devDependencies に追加する
- 3. dependencies に追加する
- 4. package.json を修正
- 5. webpack.config.js を置く
- 6. ビルドして確かめる
webpack の基本操作 にて述べた方法で、効率良く開発環境を整える手順を改めてまとめておく。
要件は、
- js モジュールの統合と単一書き出し
- sass の 統合と css 単一書き出し
- compass の読み込み
- js, css のミニマイズ
- js, css の map ファイルの生成
- ES6 -> ES5 トランスパイル(コンパイル)
- jquery の読み込み
- watch で変更を監視
完成後のディレクトリ構成(ビルド前)は次のようになる。
project/ ├── _css │ ├── entry.sass │ └── sub.sass ├── _js │ ├── entry.js │ └── sub.js ├── css ├── js ├── node_modules ├── package.json ├── webpack_index.html └── webpack.config.js
- ビルド前の各モジュールは
_
(アンダースコア)から始まるディレクトリに入れる - ビルド後のファイルは、それぞれ js, css ディレクトリに格納される
- webpack_index.html は確認用の html
0. ディレクトリとテストファイルの準備
# 各ディレクトリ mkdir {_css,_js,css,js} # テスト用 html echo '<html><link rel="stylesheet" media="all" href="./css/style.css"><body><h1></h1></body><script src="./js/bundle.js"></script></html>' > webpack_index.html # entry.scss echo '@import "compass"; @import "sub"; h1 { @include inline-block; color: #f00; }' > _css/entry.scss # sub.scss echo '@import "compass"; h1 { background-color: #000; }' > _css/sub.scss # entry.js echo 'var $ = require("jquery"); $(function(){$("h1").text(require("./sub.js"));});' > _js/entry.js # sub.js echo 'module.exports = "OK";' > _js/sub.js
- webpack_index.html ではビルド後の js と css の読み込みの他、h1 タグを用意しておく
- entry.scss では sub.scss を読み込む他、h1 を赤字に、また compass で inline-block にする
- sub.scss では h1 の背景を黒にする
- entry.js では jquery の読み込みの他、sub.js の出力を h1 にセットする
- sub.js は “OK” を返す
- ビルド後のイメージは次の感じ
1. package.json を作る
-y
オプションを付けて対話をせずに、初期化する。
npm init -y
2. devDependencies に追加する
npm install --save-dev webpack babel-loader babel-core babel-preset-es2015 node-sass style-loader css-loader sass-loader extract-text-webpack-plugin compass-mixins
それぞれ、
webpack 本体
- webpack
ES6 対応
- babel-loader
- babel-core
- babel-preset-es2015
- sass 対応
- node-sass
- style-loader
- css-loader sass-loader
- sass -> css 書き出し対応
- extract-text-webpack-plugin
- compass 対応
- compass-mixins
3. dependencies に追加する
npm install jquery --save
4. package.json を修正
... "private": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --optimize-minimize" }, ...
- プライベート用にして警告排除
"private": true
- ビルドファイルのミニマイズ設定
"build": "webpack --optimize-minimize"
5. webpack.config.js を置く
var path = require('path'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = [ /** * js */ { entry: "./_js/entry.js", watch: true, output: { path: path.join(__dirname, './js'), filename: "bundle.js" }, module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] }, devtool: 'source-map' }, /** * Sass */ { entry: './_css/entry.scss', watch: true, output: { path: path.join(__dirname, './css'), filename: 'style.css' }, module: { loaders: [{ test: /\.scss$/, loader: ExtractTextPlugin.extract({ use: [{ loader: 'css-loader' }, { loader: 'sass-loader', options: { includePaths: ['node_modules/compass-mixins/lib'] }, } ], fallback: 'style-loader' }) }] }, plugins: [ new ExtractTextPlugin('style.css') ], devtool: 'source-map' } ];
6. ビルドして確かめる
npm run build
実行後、webpack_index.html をブラウザで開き、
と表示されれば、js, sass ともにビルドができている。
また、js/bundle.js, css/style.css はそれぞれミニマイズされていて、かつ同階層に map ファイルも出力されていれば問題ない。
webpack の基本設定
webpack を初めて触ったので、調べたことなどを備忘録として残しておく。webpack のインストールから、ES6, jQuery, Sass, compass の対応まで。
- 1. npm の準備
- 2. ローカルに webpack をインストール
- 3. ローカルにパスを通す
- 4. webpack でビルドをテストする
- 5. webpack.config.js からビルドする
- 6. watch モードにする
- 7. jquery を使う
- 8. ES6 に対応させる
- 9. js を minimize する
- 10. Sass の設定をする
- 11. compass を使う場合
1. npm の準備
package.jsonを作る。
npm init
2. ローカルに webpack をインストール
package.json に書き込みたいので、--save-dev
オプションをつける。
npm install webpack --save-dev
No repository field.
と怒られた場合、一先ず、package.json に "private": true
を追加すれば警告は消える。
ドキュメントに依ると、
If you set “private”: true in your package.json, then npm will refuse to publish it.
This is a way to prevent accidental publication of private repositories. If you would like to ensure that a given package is only ever published to a specific registry (for example, an internal registry), then use the publishConfig dictionary described below to override the registry config param at publish-time.
要は公開用のリポジトリじゃなく、プライベートなリポジトリのみで使うっていう設定。これを指定すれば、repository field
の指定がなくても許される。
3. ローカルにパスを通す
このままだと、webpack
コマンドは動かないので、パスを通す。
export PATH=$PATH:./node_modules/.bin
以下でバージョンが確認出来る。
webpack -v
もちろん、パスを通す必要がないなら、直接、
node_modules/.bin/webpack -v
でも良い。
4. webpack でビルドをテストする
適当に、sub.js を作る。
module.exports = ["a", "b", "c"];
module.export
は return 的なやつ。これを app.js で読み込み、出力する。
console.log(require("./sub.js"));
これを bundle.js としてビルドする。
webpack app.js bundle.js
実行すると、
Version: webpack 2.6.1 Time: 81ms Asset Size Chunks Chunk Names bundle.js 2.78 kB 0 [emitted] main [0] ./sub.js 34 bytes {0} [built] [1] ./app.js 34 bytes {0} [built]
こんな感じの実行結果と bundle.js が書き出されている。
この bundle.js を実行すると、次のような結果になる。
[ 'a', 'b', 'c' ]
なお、npm の実行時にこれも一緒にビルドして欲しいので、build:
の項目を設け、そこに追加する。
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack app.js bundle.js" },
そうすれば、
npm run build
でビルドしてくれる。
5. webpack.config.js からビルドする
そもそも webpack 実行時に js のビルドも自動的にしてほしいので、webpack.config.js にその設定を書く。
まずは、package.json の build:
項目を webpack
だけにして、
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" },
以下のように webpack.config.js を作成。entry
と output
の filename
指定する。
module.exports = { entry: "./app.js", output: { filename: "bundle.js" } }
そうすれば、先ほどと同様に、
npm run build
でビルド出来る。ディレクトリパスを別途指定するなら、path モジュールを読み込んで、
var path = require('path'); module.exports = { entry: "./js/modules/app.js", watch: true, output: { path: path.join(__dirname, './js'), filename: "bundle.js" } }
のようにする。
6. watch モードにする
ファイルを監視させて、変更時に自動ビルド。コマンドラインから設定するなら、
webpack --watch
一方、webpack.config.js で指定するなら、watch:
を設けて、true
にする。
module.exports = { watch: true, entry: "./app.js", ...省略...
7. jquery を使う
まずは、npm で jquery をダウンロード。プロダクトでもつかうので、 オプションは --save
。
npm install jquery --save
var $ = require("jquery"); $(function(){ });
件の通り、$ に jquery をつっこむだけ。
8. ES6 に対応させる
ES6 を ES5 にコンパイルというかトランスパイルというか、とにかく変換する場合は、babel-loader
を使う。
開発用なので、オプションは --save-dev
でインストールする。
npm install babel-loader babel-core babel-preset-es2015 --save-dev
webpack.config.js に以下を追加する。
...省略... module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] } ...省略...
正規表現で node_modules を除く js 系の拡張子を対象にしている。
試しに app.js を次のように書き換え、
/*jshint esversion: 6 */ var $ = require("jquery"); $(function(){ "use strict"; const hoge = "!!!!"; $("body").text(hoge); });
ビルドすると、bundle.js では、
...省略... /*jshint esversion: 6 */ var $ = __webpack_require__(0); $(function () { "use strict"; var hoge = "!!!!"; $("body").text(hoge); }); ...省略...
const
-> var
の変換がされている。
9. js を minimize する
圧縮したいなら、packege.json の build:
で --optimize-minimize
のオプションをつける。
ただ、このままだとデバッグし難いので、更に --devtool source-map
のオプションもつけて、デベロッパーツールから圧縮前を見れるようにする。
...省略... "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --optimize-minimize --devtool source-map" }, ...省略...
これで、Chrome デベロッパーツールの Sources タブに webpack:// のディレクトリが表示される。
source-map は webmap.config.js でも指定できる。
末尾に devtool:
の項目を追加し、source-map
を指定する。
...省略... module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] }, devtool: 'source-map' ...省略...
10. Sass の設定をする
まずは、必要なモジュールをインストール。
npm install --save-dev node-sass style-loader css-loader sass-loader extract-text-webpack-plugin
css の出力も可能にするため、extract-text-webpack-plugin
も入れている。
webpack.config.js の exports
の対象をオブジェクト({}
)からオブジェクトの配列([{},{}]
)形式にして、次のように変更する。
var path = require('path'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = [ /** * js の設定 */ { entry: "./js/modules/app.js", watch: true, output: { path: path.join(__dirname, './js'), filename: "bundle.js" }, module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] }, devtool: 'source-map' }, /** * Sass の設定 */ { entry: './css/modules/style.scss', watch: true, output: { path: path.join(__dirname, './css'), filename: 'app.css' }, module: { loaders: [{ test: /\.scss$/, loader: ExtractTextPlugin.extract('css-loader!sass-loader') }] }, plugins: [ new ExtractTextPlugin('app.css') ], devtool: 'source-map' } ];
これで、複数指定ができる。なお、出力先のディレクトリなども整理してある。
11. compass を使う場合
npm install --save-dev compass-mixins
sass-loader の includePaths に compass-mixins/lib を指定して読み込ませる。
/** * Sass の設定 */ { entry: './css/modules/style.scss', watch: true, output: { path: path.join(__dirname, './css'), filename: 'app.css' }, module: { loaders: [{ test: /\.scss$/, loader: ExtractTextPlugin.extract({ use: [{ loader: 'css-loader' }, { loader: 'sass-loader', options: { includePaths: ['node_modules/compass-mixins/lib'] }, } ], fallback: 'style-loader' }) }] }, plugins: [ new ExtractTextPlugin('app.css') ], devtool: 'source-map' }
下の config ファイルを参考にさせてもらった。
wkhtmltopdf で HTML を PDFにする
wkhtmltopdf のインストール
コマンド確認
wkhtmltopdf -h
上手くインストールされていれば、なんか色々表示される。
PDF に変換
試しに google.com を PDF 出力する。
wkhtmltopdf http://google.com google.pdf
これで簡単に出力できてハッピーなはずが……
ちっさ。サイズがひどいことになってる……。
サイズが小さい問題の対処
--disable-smart-shrinking
というオプションを付ければ良さそうという記事を読んで、さっそくトライするも、変わらず。このオプションは最適化してくれるものだけど、この出力は最悪化されているので、まぁ、違うだろう。
で、もう少し調べ、ようやく同じ事例を発見。
https://stackoverflow.com/questions/40814680/wkhtmltopdf-generates-tiny-output-on-mac
ここで問題が報告されている Mac OS のバージョンが自分のものと一致していて、少し、面倒臭い雰囲気がする……。なお、この時点の環境は、
- OS バージョン: 10.11.6(15G31)
- wkhtmltopdf バージョン: 0.12.4
手動で wkhtmltopdf を消し去って、別バージョンを入れてみる。インストール先に wkhtmltoimage もあって、一緒にインストールされたものなのでこれも消す。
以下から新しく 0.12.3 のインストーラーを落としてインストール。
https://downloads.wkhtmltopdf.org/0.12/0.12.3/
改めて、出力する。
はい、ハッピーになれた。
PHP Composer の導入
installer のダウンロード
curl -sS https://getcomposer.org/installer | php
コマンドの確認するなら、
php composer.phar
local/bin/compoer に移動しておく。
mv composer.phar /usr/local/bin/composer
~/composer/composer.phar とかにしている人もいるので、ここじゃなきゃいけない、みたいなのはないのかな。分からなくなったら、
which composer
とかすればいい。
プロジェクトを作る
新しくプロジェクトを作るなら、
composer init
で、対話形式に composer.json が作れる。最初に、
Package name (<vendor>/<name>)
と ベンダー名/パッケージ名
が聞かれるので、このスラッシュ形式で指定。
Description
プロジェクトの説明を記入。
Author
name <mail address>
の形式で指定。
Minimum Stability
最小限の「安定度合い」的なものを聞かれるので、dev
, alpha
, beta
, RC
, and stable
から適時選択。デフォルトは、stable
。
Package Type
プロジェクトなら project
としてれば良さそう。デフォルトは library
。
License
オプショナルだけど、ドキュメントは、
Optional, but it is highly recommended to supply this.
と言っている。まぁ、そうだな。
Search for a package:
いよいよパッケージ。例えば、phpunit
など。
[0] phpunit/phpunit [1] eher/phpunit [2] jbzoo/phpunit [3] sugared-rim/phpunit [4] hiqdev/php-units [5] task/phpunit [6] phpunit/phpunit-mock-objects [7] phpunit/phpunit-selenium [8] phpunit/phpunit-story [9] phpunit/phpunit-skeleton-generator [10] phpunit/dbunit [11] phpunit/phpunit-dom-assertions [12] phpunit/phpcov [13] phpunit/phpunit-mink-trait [14] phpunit/php-timer
ばーっと候補がでるので、0
を入力。
Enter the version constraint to require (or leave blank to use the latest version)
最新版を使うなら、そのまま return で進む。
Using version ^6.1 for phpunit/phpunit Search for a package:
うっす。もういらないので、return で進む。
{ "name": "hoge/composer-test", "description": "this is a test.", "type": "project", "require-dev": { "phpunit/phpunit": "^6.1" }, "authors": [ { "name": "hoge", "email": "hoge@huga.com" } ], "require": {} } Do you confirm generation [yes]?
こんな json ができれば、OK。yes
で終了。ls
で確認すれば、composer.json がディレクトリに作成されている。
パッケージのインストール
composer install
と、手元の環境の PHP が 5.5.36
だったので、
Problem 1 - phpunit/phpunit 6.1.4 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement. - phpunit/phpunit 6.1.3 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement. - phpunit/phpunit 6.1.2 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement. - phpunit/phpunit 6.1.1 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement. - phpunit/phpunit 6.1.0 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement. - Installation request for phpunit/phpunit ^6.1 -> satisfiable by phpunit/phpunit[6.1.0, 6.1.1, 6.1.2, 6.1.3, 6.1.4].
composer.json を編集して、phpunit のバージョンを phpunit-4.8.35.phar
とする。
"require-dev": { "phpunit/phpunit": "4.8.35" },
Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 21 installs, 0 updates, 0 removals - Installing symfony/yaml (v3.2.8): Downloading (100%) - Installing sebastian/version (1.0.6): Downloading (100%) - Installing sebastian/global-state (1.1.1): Downloading (100%) - Installing sebastian/recursion-context (1.0.5): Downloading (100%) - Installing sebastian/exporter (1.2.2): Downloading (100%) - Installing sebastian/environment (1.3.8): Downloading (100%) - Installing sebastian/diff (1.4.3): Downloading (100%) - Installing sebastian/comparator (1.2.4): Downloading (100%) - Installing doctrine/instantiator (1.0.5): Downloading (100%) - Installing phpunit/php-text-template (1.2.1): Downloading (100%) - Installing phpunit/phpunit-mock-objects (2.3.8):Downloading (100%) ) - Installing phpunit/php-timer (1.0.9): Downloading (100%) - Installing phpunit/php-file-iterator (1.4.2): Downloading (100%) - Installing phpunit/php-token-stream (1.4.11): Downloading (100%) - Installing phpunit/php-code-coverage (2.2.4): Downloading (100%) - Installing webmozart/assert (1.2.0): Downloading (100%) - Installing phpdocumentor/reflection-common (1.0): Downloading (100%) - Installing phpdocumentor/type-resolver (0.2.1): Downloading (100%) - Installing phpdocumentor/reflection-docblock (3.1.1): Downloading (100%) - Installing phpspec/prophecy (v1.7.0): Downloading (100%) - Installing phpunit/phpunit (4.8.35): Downloading (100%) symfony/yaml suggests installing symfony/console (For validating YAML files using the lint command) sebastian/global-state suggests installing ext-uopz (*) phpunit/php-code-coverage suggests installing ext-xdebug (>=2.2.1) phpunit/phpunit suggests installing phpunit/php-invoker (~1.1) Writing lock file Generating autoload files
依存モジュールもまとめて、いっぱい。 ls
すると、
composer.json composer.lock vendor
lock ファイル と vendor ディレクトリができている。vendor という名前のディレクトリに外部の依存モジュールが格納されるので、.gitignore にこのディレクトリを指定しておけば OK。
を参考。
パッケージの追加
composer require cebe/markdown
require
で追加できる。composer.json と lock ファイルも更新される。バージョン指定する場合は、
composer require hoge/huge:1.1.11
みたいにする。
参考
Markdown を PDF にする
前提
node.js が動くこと。
npm で markdown-pdf をインストール
npm install -g markdown-pdf
pdf に変換
markdown-pdf hoge.md
このままだとスタイルがないので、まず、github のスタイルを拝借。
https://gist.github.com/andyferra/2554919
css のオプションをつけて、
markdown-pdf hoge -s github.css
なお、6系の node.js だとエラーがでるけど、出力はちゃんとできる。
(node:63631) Warning: Possible EventEmitter memory leak detected. 2 end listeners added. Use emitter.setMaxListeners() to increase limit
PHPでOS差を吸収する定数を使う
PHP_EOL
改行コードを直接指定すると、
$hoge = "hoge"; echo $hoge, "\n";
みたいにしがち、これだとCRLFに対応できないので、PHP_EOLを使って、
echo $hoge, PHP_EOL ;
にしたほうがよい。環境の違いで、出力をかえてくれるみたい。ちなみに、EOLはEnd of Lineの略。
改行 | 改行コード |
---|---|
LF | \n |
CELF | \r\n |
DIRECTORY_SEPARATOR
ディレクトリパスもつい、
$hoge = "hoge"; $fuga = "fuga"; echo $hoge, "/", $fuga, PHP_EOL;
みたいにしちゃうけど、
echo $hoge, DIRECTORY_SEPARATOR, $fuga, PHP_EOL;
で環境差を吸収できる。
他、PATH_SEPARATORなんかもあるみたい。なお、PHP_OSでOS種を返してくれる。