備忘録:正規表現

これは、たまに正規表現を使うけどすぐ忘れてしまう人のメモです。
正規表現の基本については下記の記事を参照。

忘れがちなメタ文字6つ

他言語からの類推が働かず、どれがどれか忘れがちなメタ文字は以下の6つ。
無理やり語呂合わせでおぼえることにする。

メタ文字 機能 語呂合わせ
. 任意の1文字 全てに終止符
^ 行の先頭 頭にハット
$ 行の末尾 最後はカネ
* 繰り返し(0文字以上) ゼロからの米作り
+ 繰り返し(1文字以上) プラスは0を含まない
? 繰り返し(0文字か1文字) 有りや無しや?

3種類のカッコ

これはまあそんなに混乱しない。

カッコ 機能
[ ] 集合のどれか1文字
( ) 2文字以上をグループ化
{ } 直前の文字の繰り返し回数

メタ文字の基本

任意の1文字 .

ワイルドカードでは ? だが、正規表現では . であることに注意。

行の先頭 ^ と行の末尾 $

この2つはセットでおぼえる。
正規表現の 先頭 / 末尾 以外では通常の文字扱いとなることに注意。

直前の文字の繰り返し * + ?

この3つはセットでおぼえる。
* と ? はワイルドカードとは意味が異なることに注意。

エスケープ \

これは他言語でもおなじみ。

集合のどれか1文字 [ ] と 補集合のどれか1文字 [^ ]

^ は正規表現の先頭の場合(行の先頭)とは意味が異なるので注意。
こちらのほうが、C言語等のビットNOT演算子から類推できる。

2文字以上をグループ化 ( )

これは分かりやすい。

いずれかの文字列 |

これも分かりやすい。

直前の文字の繰り返し回数 { }

{n} は n文字、{n,} は n文字以上、{n,m} は n文字以上m文字以下。

エスケープシーケンス

メタ文字のエスケープと、おなじみの \n (改行) や \t (タブ) など以外に下記のようなものが使える。

  • \s : 空白文字 (半角スペース、タブ、改行)など ⇔ \S : それ以外の文字
  • \d ⇔ \D : 数字とそれ以外、\l ⇔ \L : 小文字とそれ以外、\u ⇔ \U : 大文字とそれ以外
  • \w ⇔ \W : 英数字+アンダースコア とそれ以外
  • \Q~\E : 囲まれた範囲はメタ文字を解釈しない

置換

( )でくくった部分を前から順に $1 $2 $3 ... で置換できる。
ただし、これには方言差があり、秀丸では \1 \2 \3 ... である。
秀丸は日本だからドルじゃなくて円とおぼえておく。(ただしサクラエディタは$ )

Haskellのモナドいろいろ (まとめ)

分類

  • 上記の記事で述べた8つのモナドは、2種類に分類できる。
  • 失敗系:List, Maybe, Either
  • 状態系:IO, ST, State, Reader, Writer
  • モナドには他にも種類があるが、まずはこの2種類を押さえておく。

失敗系 (List, Maybe, Either)

  • 失敗系モナドは、本来期待されるデータ型以外に、値が無い(失敗)という値がありうる。
  • そのため、エラー処理に利用できる。
  • 失敗系モナドは、計算が失敗する可能性がある関数を連鎖させることができる。
  • どこかで失敗した場合、その後の計算は行われず、最終結果は失敗になる。
  • List を失敗系と呼ぶのは違和感があるが、空リスト [] を値にとりうるのでここに含める。
  • Maybe は値が無い (Nothing) という値をとりうる。
  • Either は値が無いときにエラー情報の値を持たせることができる。

状態系 (IO, ST, State, Reader, Writer)

  • 状態系は、純粋関数型言語である Haskell で状態を扱うために使われる。
  • IO は入出力を扱う。また IORef は変更可能な変数のようなものとして利用できる。
  • IO の外に値を持ち出すことはできない。(IOがつきまとう。)
  • ST は外に値を持ち出すことができる。STRef は変更可能なローカル変数のようなものとして利用できる。
  • State は値だけでなく状態も持ち出せる。
  • State は連鎖した関数の間で状態を共有してグローバル変数のようなものとして利用できる。
  • Reader は読み取り専用の値を共有できる。グローバル定数のようなものとして利用できる。
  • Writer は追記専用の値を共有できる。ログを取るために使われることが多い。

ポエム

  • モナドジェネリック型のコンテナのようなもの」というのは本質的な理解ではないが、実践的な理解の足掛かりにはなる。
  • 「クラスは構造体の拡張のようなもの」というのは本質的な理解ではないが、実践的な理解の足掛かりにはなったのと同じ。
  • モナドブリトーのようなもの」みたいなよく分からない比喩は役に立たない。
  • 「クラスはたい焼きの型のようなもの」みたいなよく分からない比喩は役に立たなかったのと同じ。
  • そもそもブリトーなんて料理食べたことないから比喩として成立しない。
  • モナドは自己関手の圏におけるモノイド」という説明は、ブリトーと五十歩百歩。
  • あれは圏論の教科書の一節であって、群論の基礎知識があると想定される読者への説明。
  • モノイドなにそれおいしいのな人には何の説明にもならない。

Haskellのモナドいろいろ (4)

Readerモナド

Readerモナドは、読み取り専用のStateモナドのようなものである。
Stateモナドグローバル変数のようなものとして利用できたが、
Readerモナドはグローバル定数のようなものとして利用できる。
Stateモナドでは状態の取得にgetを用いたが、Readerモナドでは ask を用いる。
Stateモナドの runState に相当するのは runReader だが、状態は変化しないので値のみ返す。

import Control.Monad.Reader

calcTax :: Int -> Reader Int Int
calcTax x = do
    tax <- ask
    let y = (x * (100 + tax)) `div` 100
    return y

main :: IO ()
main = do
    print $ (`runReader` 8) $ do
        a <- calcTax 100
        b <- calcTax 500
        c <- calcTax 1000
        return (a, b, c) -- (108,540,1080)
    print $ (`runReader` 10) $ do
        a <- calcTax 100
        b <- calcTax 500
        c <- calcTax 1000
        return (a, b, c) -- (110,550,1100)

モナドだから return で値を中に入れることができる。

import Control.Monad.Reader

hoge :: Int -> Reader String Int -- 状態: String, 値: Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5
    let a = runReader ma "hoge"
    print a -- 5    ※ Stateとは異なり、状態は返さない

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad
import Control.Monad.Reader

hoge :: Int -> Reader s Int
hoge x = return x

main :: IO ()
main = do
    let ma  = hoge 5 :: Reader String Int
    let mma = return ma :: Reader String (Reader String Int)
    let ma' = join mma -- Reader String Int
--  let a'  = join ma'  -- エラー
    let a'  = runReader ma' "hoge"
    print a' -- 5

モナドだから fmap で中の値を関数に渡すことができる。

import Control.Monad.Reader

hoge :: Int -> Reader String Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5 :: Reader String Int
    let mb = fmap (*2) ma
    let b = runReader mb "hoge"
    print b -- 10

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

import Control.Monad.Reader

hoge :: Int -> Reader String Int
hoge x = return (x * 2)

main :: IO ()
main = do
    let ma = hoge 5
    let mb = ma >>= hoge
    let a = runReader ma "hoge"
    let b = runReader mb "piyo"
    print a -- 10
    print b -- 20

またすでに見た通り、モナドだから do構文が使える。

Writerモナド

Writerモナドは、追記専用のStateモナドのようなものである。
値の更新ではなく追記であることに注意。主にリストに追加して使う。
ログを取るために使われることが多い。
Stateモナドでは状態の更新に put / modify を用いたが、Writerモナドでは tell を用いる。
Stateモナドの runState, execState に相当するのは runWriter, execWriter である。

import Control.Monad.Writer

main :: IO ()
main = do
    let s = execWriter $ do
            tell "hoge\n"
            tell "piyo\n"
            tell "huga\n"
            return ()
    putStrLn s

モナドだから return で値を中に入れることができる。

import Control.Monad.Writer

hoge :: Int -> Writer String Int -- 状態: String, 値: Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5
    let a = runWriter ma -- 初期値が無いことに注意
    print a -- (5,"")

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad
import Control.Monad.Writer

hoge :: Int -> Writer String Int
hoge x = return x

main :: IO ()
main = do
    let ma  = hoge 5 :: Writer String Int
    let mma = return ma :: Writer String (Writer String Int)
    let ma' = join mma -- Writer String Int
--  let a'  = join ma'  -- エラー
    let a'  = runWriter ma'
    print a' -- (5,"")

モナドだから fmap で中の値を関数に渡すことができる。

import Control.Monad.Writer

hoge :: Int -> Writer String Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5 :: Writer String Int
    let mb = fmap (*2) ma
    let b = runWriter mb
    print b -- (10,"")

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

import Control.Monad.Writer

hoge :: Int -> Writer String Int
hoge x = return (x * 2)

main :: IO ()
main = do
    let ma = hoge 5
    let mb = ma >>= hoge
    let a = runWriter ma
    let b = runWriter mb
    print a -- (10,"")
    print b -- (20,"")

またすでに見た通り、モナドだから do構文が使える。

Haskellのモナドいろいろ (3)

Stateモナド

STモナドは runST で値のみを取り出せたが、Stateモナドは状態も取り出せる。値と状態を取り出すには runState を、値のみを取り出すには evalState を、状態のみを取り出すには execState を用いる。

前の記事STモナドで実装した sum' 関数を Stateモナドを使って書き直すと下記のようになる。
Stateモナドの持つ状態を、破壊的代入可能な変数のようなものとして使っている。

import Control.Monad
import Control.Monad.State

sum' :: [Int] -> Int -- 戻り値が裸
sum' xs = (`execState` 0) $ do  -- execStateで初期状態 0 を与え、結果の状態を取り出す
    forM_ xs $ \i ->
        modify (+ i)            -- 状態を更新

main :: IO ()
main = do
    print $ sum' [1..10] -- 55

簡潔だがいささか分かりにくい。少し書き換えると下記のようになる。
Stateモナドの状態は get で取得し、put で更新するが、関数で更新する場合は modify を用いる。

import Control.Monad
import Control.Monad.State

sum' :: [Int] -> State Int () -- Sateでくるんだ状態Intと値()を返す
sum' xs = do
    forM_ xs $ \i ->
        modify (+ i)          -- 状態を更新

main :: IO ()
main = do
    let a = execState (sum' [1..10]) 0 -- execStateで初期状態 0 を与え、結果の状態を取り出す
    print a -- 55

モナドだから return で値を中に入れることができる。

import Control.Monad.State

hoge :: Int -> State String Int -- 状態: String, 値: Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5
    let a = runState ma "hoge"
    print a -- (5,"hoge")

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad
import Control.Monad.State

hoge :: Int -> State s Int
hoge x = return x

main :: IO ()
main = do
    let ma  = hoge 5 :: State String Int
    let mma = return ma :: State String (State String Int)
    let ma' = join mma -- State String Int
--  let a'  = join ma'  -- エラー
    let a'  = runState ma' "hoge"
    print a' -- (5,"hoge")

モナドだから fmap で中の値を関数に渡すことができる。

import Control.Monad.State

hoge :: Int -> State String Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5 :: State String Int
    let mb = fmap (*2) ma
    let b = runState mb "hoge"
    print b -- (10,"hoge")

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

import Control.Monad.State

hoge :: Int -> State String Int
hoge x = return (x * 2)

main :: IO ()
main = do
    let ma = hoge 5
    let mb = ma >>= hoge
    let a = runState ma "hoge"
    let b = runState mb "piyo"
    print a -- (10,"hoge")
    print b -- (20,"piyo")

またすでに見た通り、モナドだから do構文が使える。

do構文を使って状態付き計算をつなげることができる。
モナドを使わずに状態をいちいち引数として関数に渡すと、下記のように繁雑なコードになる。

fb :: Int -> Int -> Int
fb x0 x1 = x0 + x1

main :: IO ()
main = do
    let x2 = fb  0  1
    let x3 = fb  1 x2
    let x4 = fb x2 x3
    let x5 = fb x3 x4
    let x6 = fb x4 x5
    print x6 -- 8

Stateモナドを使うと下記のように書ける。(字下げに注意すること)
このようにStateモナドの状態はグローバル変数のようなものとして利用できる。

import Control.Monad.State

fb :: State (Int, Int) Int
fb = do
    (x0, x1) <- get
    let x2 = x0 + x1
    put (x1, x2)
    return x2

main :: IO ()
main = do
    let x6 = (`evalState` (0, 1)) $ do
            x2 <- fb
            x3 <- fb
            x4 <- fb
            x5 <- fb
            fb
    print x6 -- 8

Haskellのモナドいろいろ (2)

IOモナド

IOはもちろんモナドである。
入出力という副作用を扱うために用いられる。
main も IO () という型の変数である。 (関数ではない)

モナドだから return で値を中に入れることができる。

hoge::Int -> IO Int
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5
    a <- ma
    print a -- 5

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad

main = do
    let ma  = return 5 :: IO Int
    let mma = return ma
    let ma' = join mma
--  let a'  = join ma' -- エラー
    a' <- ma'
    print a' -- 5

モナドだから fmap で中の値を関数に渡すことができる。

main = do
    let ma = return 5 :: IO Int
    let mb = fmap (*2) ma
    b <- mb
    print b -- 10

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

hoge :: Int -> IO Int
hoge x = return (x * 2)

main = do
    let ma = return 5
    let mb = ma >>= hoge
    b <- mb
    print b -- 10

モナドだから do構文が使える。main じたいが IO() 型だから、これは今まで見て来たとおりである。

do構文を使うと、関数の本筋と無関係な出力もあたかも手続き型言語のように記述できる。

hoge :: Int -> IO Int
hoge x = do
    putStrLn "Hello, world!" -- 関数の本筋と無関係な出力
    return (x * 2)

main = do
    let mb = hoge 5
    print =<< mb -- 10

入力も扱える。

hoge :: IO Int
hoge = do
    putStrLn "Enter an integer:" -- 出力
    s <- getLine -- 入力
    let x = read s :: Int
    return x

main = do
    x <- hoge
    print x

またIOモナドの中では IORef が使える。IORef は変更可能な(破壊的代入ができる)変数のようなものである。
IORef は newIORef で生成し、readIORef で値を取得し、writeIORef で値を更新する。

import Data.IORef

main = do
    ma <- newIORef 1   -- ma :: IORef Integer
    a <- readIORef ma  -- a :: Integer
    print a  -- 1
    writeIORef ma 2
    a' <- readIORef ma
    print a' -- 2

関数で IORef の値を更新するときは、writeIORef ではなく modifyIORef を用いる。

import Control.Monad
import Data.IORef

sum' :: [Int] -> IO Int -- 戻り値にIOがつきまとう
sum' xs = do
    v <- newIORef 0          -- 初期値
    forM_ xs $ \i ->
        modifyIORef v (+ i)  -- 更新
    readIORef v

main = do
    print =<< sum' [1..10] -- 55

しかしIOモナドの外に値を持ち出すことができない。(IOがつきまとう。)

STモナド

IOモナド / IORef と異なり、STモナド / STRef は runST で値を外に持ち出すことができる。
STモナドは破壊的代入を内部に閉じ込めて、計算結果のみを取り出すのに用いる。
STRef では、newIORef / readIORef / writeIORef / modifyIORef に代えて
newSTRef / readSTRef / writeSTRef / modifySTRef を用いる。

import Control.Monad
import Control.Monad.ST
import Data.STRef

sum' :: [Int] -> Int -- 戻り値が裸
sum' xs = runST $ do -- runSTでSTモナドから値を取り出す
    v <- newSTRef 0          -- 初期値
    forM_ xs $ \i ->
        modifySTRef v (+ i)  -- 更新
    readSTRef v

main :: IO ()
main = do
    print $ sum' [1..10] -- 55

上記の例では sum' 関数の do構文の部分が STモナドだが、そのことがやや分かりにくい。
少し書き換えると下記のようになる。

import Control.Monad
import Control.Monad.ST
import Data.STRef

sum' :: [Int] -> ST s Int -- STでくるんだ値を返す
sum' xs = do
    v <- newSTRef 0          -- 初期値
    forM_ xs $ \i ->
        modifySTRef v (+ i)  -- 更新
    readSTRef v

main :: IO ()
main = do
    let a = runST $ sum' [1..10] -- runSTでSTモナドから値を取り出す
    print a -- 55

モナドだから return で値を中に入れることができる。

import Control.Monad.ST

hoge :: a -> ST s a -- 内部で使用する状態型 s があることに注意
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5
    let a = runST ma
    print a -- 5

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad
import Control.Monad.ST

hoge :: a -> ST s a
hoge x = return x


main :: IO ()
main = do
    let ma  = hoge 5 :: ST s Int
    let mma = return ma :: ST s (ST s Int)
    let ma' = join mma -- ST s Int
--  let a'  = join ma'  -- エラー
    let a'  = runST ma' 
    print a' -- 5

モナドだから fmap で中の値を関数に渡すことができる。

import Control.Monad.ST

hoge :: a -> ST s a
hoge x = return x

main :: IO ()
main = do
    let ma = hoge 5 :: ST s Int
    let mb = fmap (*2) ma
    let b = runST mb
    print b -- 10

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

import Control.Monad.ST

hoge :: Int -> ST s Int
hoge x = return (x * 2)

main :: IO ()
main = do
    let ma = hoge 5
    let mb = ma >>= hoge
    let a = runST ma
    let b = runST mb
    print a -- 10
    print b -- 20

またすでに見た通り、モナドだから do構文が使える。

Haskellのモナドいろいろ (1)

Listモナド

リストもモナドである。意外なことにリストもモナドである。
リストには要素数が0個の空リストがありうる。
これは後述するMaybe や Either における失敗の表現のようなものとも言える。

モナドだから return で値を中に入れることができる。

hoge::Int -> [Int]
hoge x = return x

main = do
    print $ hoge 5 -- [5]

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad

main = do
    let a = [[1,2],[3,5],[5,6]]
    let b = [[[1],[2]],[[3],[4]]]
    let c = [1]
    print $ join a -- [1,2,3,5,5,6]
    print $ join b -- [[1],[2],[3],[4]]
--  print $ join c -- エラー

モナドだから fmap で中の値を関数に渡すことができる。
リストには特に map というのも用意されているが、結果は fmap と同じ。

main = do
    let a = [1,2,3,4,5]
    print $ fmap (*2) a -- [2,4,6,8,10]
    print $ map  (*2) a -- [2,4,6,8,10]

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

main = do
    print $ [7] >>= replicate 3 -- [7,7,7]

モナドだから do構文が使える。

hoge :: [Int] -> [Int]
hoge xs = do
    x <- xs
    return $ x * 2

main = do
    print $ hoge [1,2,3,4,5] -- [2,4,6,8,10]

Maybeモナド

Maybeは成否を表現できる。成功なら Just 値、失敗なら Nothing。
1個か0個しか要素を持てないリストのようなものとも言える。

モナドだから return で値を中に入れることができる。

hoge::Int -> Maybe Int
hoge x = return x

main = do
    print $ hoge 5 -- Just 5

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad

main = do
    let a = Just(Just 5) :: Maybe (Maybe Int)
    let b = Just Nothing :: Maybe (Maybe Int)
    let c = Just 2 
    print $ join a -- Just 1
    print $ join b -- Nothing
--  print $ join c -- エラー

モナドだから fmap で中の値を関数に渡すことができる。

main = do
    let a = Just 5
    print $ fmap (*2) a -- Just 10

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

hoge :: Int -> Maybe Int
hoge x
    | x >= 10   = Just (x `div` 10)
    | otherwise = Nothing

main = do
    print $ Just 50 >>= hoge -- Just 5
    print $ Just 5  >>= hoge -- Nothing

モナドだから do構文が使える。

hoge :: Maybe Int -> Maybe Int
hoge mx = do
    x <- mx
    if x >= 10
        then return (x `div` 10)
        else Nothing

main = do
    print $ hoge (Just 50) -- Just 5
    print $ hoge (Just 5)  -- Nothing
    print $ hoge Nothing   -- Nothing

失敗するかもしれない関数を連鎖できる。
途中で失敗した場合、その後の計算は行われず最終結果は失敗になる。

hoge :: Int -> Maybe Int
hoge x
    | x >= 10   = Just (x `div` 10)
    | otherwise = Nothing

main = do
    print $ Just 500 >>= hoge >>= hoge -- Just 5
    print $ Just 50  >>= hoge >>= hoge -- Nothing
    print $ Just 5   >>= hoge >>= hoge -- Nothing

Eitherモナド

Eitherは成否を表現でき、失敗にも値(エラー情報)を持てる。成功なら Right 値、失敗なら Left 値。
Maybeの拡張してエラー情報を持てるようにしたようなものと言える。

モナドだから return で値を中に入れることができる。

hoge::Int -> Either String Int 
hoge x = return x

main = do
    print $ hoge 5 -- Right 5

モナドだから join で一皮むくことができるが、 join で裸にはできない。

import Control.Monad

main = do
    let a = Right(Right 5)     :: Either String (Either String Int) 
    let b = Right(Left "hoge") :: Either String (Either String Int) 
    let c = Right 2            :: Either String Int
    print $ join a -- Right 5
    print $ join b -- Left "hoge"
--  print $ join c -- エラー

モナドだから fmap で中の値を関数に渡すことができる。

main = do
    let a = Right 5 :: Either String Int
    print $ fmap (*2) a -- Right 10

モナドだから bind ( >>= ) で中の値を、モナドを返す関数に渡すことができる。

hoge :: Int -> Either String Int
hoge x
    | x >= 10   = Right (x `div` 10)
    | otherwise = Left "error"

main = do
    print $ Right 50 >>= hoge -- Right 5
    print $ Right 5  >>= hoge -- Left "error"

モナドだから do構文が使える。

hoge :: Either String Int -> Either String Int
hoge mx = do
    x <- mx
    if x >= 10
        then return (x `div` 10)
        else Left "error"

main = do
    print $ hoge (Right 50)    -- Right 5
    print $ hoge (Right 5)     -- Left "error"
    print $ hoge (Left "hoge") -- Left "hoge"

失敗するかもしれない関数を連鎖できる。
途中で失敗した場合、その後の計算は行われず最終結果は失敗になる。

hoge :: Int -> Either String Int
hoge x
    | x >= 10   = Right (x `div` 10)
    | otherwise = Left "error"

main = do
    print $ Right 500 >>= hoge >>= hoge -- Right 5
    print $ Right 50  >>= hoge >>= hoge -- Left "error"
    print $ Right 5   >>= hoge >>= hoge -- Left "error"

InnoSetupでQtアプリのインストーラ作成

やりたいこと

Qtで作成したWindowsアプリのインストーラをInnoSetupで作成する。

InnoSetupのインストール

下記コマンドを実行してInnoSetupをインストールする。 (本稿執筆時点でバージョン6.2.2)

winget install JRSoftware.InnoSetup

WindowsのノートPCでは文字表示が小さすぎて見にくい場合がある。その場合は、アプリのショートカットを右クリックして、[プロパティ]→[互換性] タブ→[高DPI設定の変更] で、[高いDPIスケールの動作を上書きします。] にチェックし、[拡大縮小の実行元] には [システム] を選択。

Qtアプリの配布用ファイルを集める

Qtのリリースビルドのディレクトリで下記のようなコマンドを実行する。

windeployqt --dir deploy 実行ファイル名.exe

すると必要なDLLなどが deploy フォルダに集まる。その他に必要なリソースファイルなどがあれば手動で deploy フォルダに集める。

InnoSetupでインストーラを作成

ウィザードを利用してインストーラを作成する手順を以下に記す。

  • InnoSetupを起動する。
  • Welcome : 「Create a new script file using the Script Wizard」を選択して「OK」

  

  • Welcome to the Inno Setup Script Wizard : 「Next」をクリック。

  

  • Application Information : アプリの名前とバージョンを設定する。他は空欄でも可。

  

  • Application Folder : インストールフォルダの名前を設定する。

  

  • Application Files : アプリの実行ファイルを指定し、さきほど作成した deployフォルダを追加する。フォルダを追加すると「Should files in subfolders of xxxx also be included?」と聞かれるので「Yes」と答える。またここで「Allow user to start the application after Setup has finished」にチェックするとインストール完了時にアプリが起動するようになる。

  

  • Application File Association : 関連付けるべきファイル種別があれば、ファイル種別名と拡張子を設定する。なければチェックしない。
  • Application Shrotcuts : スタートメニューやデスクトップにショートカットを作成するか設定する。
  • Application Documentaion : インストール中に表示すべきライセンスファイルなどを設定する。なければ空欄で可。
  • Setup Install Mode : インストールモード (「すべてのユーザー」か「このユーザーのみ」か)を設定する。インストール時に選択させることも可能。
  • Setup Languages : インストール時の言語を選択する。(複数選択可)
  • Compiler Settings : ① インストーラの出力先フォルダを設定する。空欄ならスクリプトと同じ階層に Output という名前のフォルダが作られる。② インストーラのファイル名を設定する。(拡張子は除く) ③ インストーラのアイコンファイルを設定する。空欄ならデフォルトのアイコンになる。④ インストール時のパスワードを設定する。不要なら空欄にする。

  

  • Inno Setup Preprocessor : チェックするとスクリプトが簡単になる。チェックを外すと手動でスクリプトを改変しやすくなる。
  • 「You have successfully completed」と表示されたら「Finish」をクリック。

  

  • 「Would you like to compile the new script now?」と聞かれたら「Yes」と答える。その後「Would you like to save the script before compiling」と聞かれたら「Yes」と答える。

  

  

参考