2018年01月08日

make + guile を使うメモ 2018

make + guile を使うメモ 2018
はじまり
だいぶ前にmake 4.0がリリースされてguile言語がバインドされた。
Makefileの中にguile言語が記述できるというもの。
(ただし、guile機能はオプション扱いでmake 4.x系でも非バインド(使えない)のものもある)

guile言語はインタプリタ型の汎用言語なので、makeの標準関数だけではできなかった
いろいろな処理が自由に書けることになる。
今までも $(shell ...) 関数で外部コマンドを呼び出せばそこそのことはできていたが、
Windows(32bit)(DOS窓,PowerShell)とLinux系(msys2/cygwin)で共用しようと思うと
Windows側に追加ツールが必要で、かつ、互換性やコマンド同士の干渉に留意が必要だった。

make 4.x系でguile言語を使えばどのプラットフォームでも使えるMakefileが作成できる
ことになるのだった。

make 4.x + guile機能はデフォルトで Onなのか?
今は2018年初頭。 デフォルトの対応状況をしらべてみた。
guile機能有効化
msys2 なし 後述
cygwin あり 不要
[Lu|U]buntu 16.04(Linux)なし $sudo apt-get install make-guile
guile機能が有効化どうか確認する方法: Makefile内に以下を記述し、
all:
    @echo $(.FEATURES)
makeしてみると、
target-specific order-only second-expansion else-if shortest-stem
undefine oneshell archives jobserver output-sync guile load
上記の様にguileが含まれていれば有効になっている。 Windows DOS窓/PowerShell/msys2上でguile機能を使う (1) まず既存のmake.exeがある場合はそれが呼ばれないようにする。 やり方は色々あるが、make.exeをmake.exe.orgにリネームするのが簡単か。 (2) make with guile をダウンロード https://sourceforge.net/projects/ezwinports/files/ から make-4.2.1-with-guile-w32-bin.zip をダウンロードし、解凍する。 (3) 出てきたファイル群を D:\usr以下にコピーする。 Windowsの環境変数PATHに D:\usr\binを追加。 Windows DOS窓/PowerShell上からはこれで使える。 msys2: $ pacman -R make で既存のmakeを削除。 ~/.bashrc 内に export PATH=$PATH:/d/usr/bin を追加し、 $source ~/.bashrc で使用可能になる。 ドライブDがない場合: ドライブCしかない場合、或いは、ドライブD以外にインストールしたい場合は、 (a) 適当なドライブ(仮にC:)・フォルダ(仮にmakegとする)に上記解凍したファイル群をコピーする。 (b) Winodws環境変数に以下の2つを新規追加。 (i) 変数名: GUILE_LOAD_COMPILED_PATH 変数値: c:\makeg\lib\guile\2.0\ccache (ii)変数名: GUILE_LOAD_PATH 変数値: c:\makeg\share\guile\2.0 (c) Windowsの環境変数PATHに c:\makeg\binを追加。 msys2で使いたい時は、 ~/.bashrcに上記同様に追加。 以上で make + guile機能が使える様になる。 guile関数を実際に使ってみた GUILE_SCRIPT: 関数群の適当な名前。 define 名前 .... endef で関数群を定義。 $(guile $(GUILE_SCRIPT) ) で関数群をロード。 緑の部分で、定義した関数を使用した。 関数 genTargetName は引数文字列の先頭から3文字をカットした文字列を返す関数。 (やりたかったのは、Makefileを実行したフォルダの名前から先頭の3文字をカットしたものを、 TARGET名にしたかった。)(注1) Makefile
# guile関数定義
define GUILE_SCRIPT
	(define (genTargetName dirName)\
		(substring dirName 3 (string-length dirName)))
endef
# guile関数ロード
$(guile $(GUILE_SCRIPT) )

ARC        = thumbv7em-none-eabihf
FLASH_EXE  = d:/STM32-ST-LINK-Utility/ST-LINK\ Utility/ST-LINK_CLI.exe

DIRNAME    = $(notdir $(CURDIR))
# guile関数呼び出し
TARGET     = $(guile (genTargetName "$(DIRNAME)" ) )
TARGET_DBG = $(TARGET)_debug
TARGET_REL = $(TARGET)_release
... 
関数定義をやめれば同じ内容をもっと短くも書ける。 Makefile
ARC        = thumbv7em-none-eabihf
FLASH_EXE  = d:/STM32-ST-LINK-Utility/ST-LINK\ Utility/ST-LINK_CLI.exe

DIRNAME    = $(notdir $(CURDIR))
# guile関数呼び出し
TARGET     = $(guile (substring "$(DIRNAME)" 3 (string-length "$(DIRNAME)"))))
TARGET_DBG = $(TARGET)_debug
TARGET_REL = $(TARGET)_release
... 
guile関数の定義部分だけ別ファイルに書いてロードすることもできる。 $(guile (load "script_foo.scm")) makeのguile機能について makeの標準関数の一つとして「guile」という名前の関数が増えたことになる。 引数1つの関数なので、 $(guile 引数) と言う形になる。 guile関数は最初に、makeによって通常の方法で評価(展開)され、 次にguileインタプリタで評価される。 Makefile内は文字列しか扱えないので、guileの引数も文字列である必要がる。 guileインタプリタでの評価結果(返り値)は文字列としてMakefile内で使用できる。 guile返り値の型変換 guileインタプリタ内部で扱う型は、makeへの返り値となった時、 以下の様にすべて文字列に変換される。
guile内の型変換後のmake内の文字列
#f 空文字。 空文字はMakefile内ではfalseとして扱われる。
#t '#t'。 '#t'は文字なのでMakefile内ではtrueとなる。
シンボルと数値 シンボルと数値はそれらを表す文字列となる。
文字 表示可能な文字は、同じ文字になる。
文字列 表示可能な文字のみを含む文字列は、同じ文字列になる。
リスト リストは上記ルールに従って、再帰的に平坦化される。 例: (a b (c d) e) は、 Makefile内では'a b c d e' となる。
その他 上記以外の型はエラーとなる。(将来扱える型が増える可能性を否定しない)
従って、エラーを避けるなら上記の有効な型に置き換える工夫が必要。
make + guile 資料 このページをguileで検索 https://www.gnu.org/software/make/manual/make.html guile 資料 guile トップページ https://www.gnu.org/software/guile/ guile2.2.3 ドキュメント https://www.gnu.org/software/guile/manual/ (注) Macは非所有なのでAC。 (注1) ひょっとするとguileをつかわずmakeの標準関数でできるかどうかは未確認。 ざっとみたけど、 ?だった。
posted by Copyright (C) avrin All Rights Reserved. at 23:24| Comment(0) | その他 | このブログの読者になる | 更新情報をチェックする

2018年01月07日

Rust言語でWin32apiしてみたメモ 2018

Rust言語でWin32apiしてみたメモ 2018
はじまり
Rust言語の練習のためWin32APIのファイルオープンダイアログを起動する
簡単なソフトを作ってみたメモ。

Rust winapiのページ
https://github.com/retep998/winapi-rs

今時、Win32API直たたきはアレだけど、一応やってみた。
./target/debug/win32_fopen_dlg.exe
or
./target/release/win32_fopen_dlg.exe
をコマンドラインから実行してファイルを選択すると、ファイル名を表示するだけ。
ファイル未選択でキャンセルすると別なメッセージが出るだけ。
なソフト。

以下のソースコードは日本語を含むので「UTF-8」で保存する必要がある。
src/main.rs
/*
 * Windows File open dialog demo.
 * rustc 1.22.1 (05e2e1c41 2017-11-22): stable.
 * This file must be saved as UTF-8 format.
 *
 * 2018/01/02 by audin
 */
#![windows_subsystem = "windows"]

extern crate winapi;
extern crate user32;

use std::env;
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use std::mem::size_of;
use winapi::um::commdlg::{OPENFILENAMEW, OFN_HIDEREADONLY};
use winapi::um::commdlg::GetOpenFileNameW;
use std::result;

const SZW_SIZE: usize = 512;
// Type alias to simplify representation.
type Result<T> = result::Result<T,String>;
type TSzwBuf   = [u16; SZW_SIZE];

// Open the fileopen dialog with Windows GUI.
#[allow(non_snake_case)]
fn file_open_dialog() -> Result<String> {
    let szwFilter = str_to_szw("プログラム:(*.exe)\0*.exe\0すべて:(*)\0*\0");
    let szwTitle  = str_to_szw("ファイルを選択します");
    let mut szw_buf: TSzwBuf = [0; SZW_SIZE];
    let mut dlgOpen = OPENFILENAMEW {
        lStructSize:       size_of::<OPENFILENAMEW>() as u32, //DWORD,
        hwndOwner:         null_mut(),                        // HWND,
        hInstance:         null_mut(),                        // HINSTANCE,
        lpstrFilter:       szwFilter.as_ptr(),                // LPCWSTR,
        lpstrCustomFilter: null_mut(),                        // LPWSTR,
        nMaxCustFilter:    0,                                 // DWORD,
        nFilterIndex:      0,                                 // DWORD,
        lpstrFile:         szw_buf.as_mut_ptr(),              // LPWSTR,
        nMaxFile:          szw_buf.len() as u32,              // DWORD,
        lpstrFileTitle:    null_mut(),                        // LPWSTR,
        nMaxFileTitle:     0,                                 // DWORD,
        lpstrInitialDir:   null_mut(),                        // LPCWSTR,
        lpstrTitle:        szwTitle.as_ptr(),                 // LPCWSTR,
        Flags:             OFN_HIDEREADONLY,                  // DWORD,
        nFileOffset:       0,                                 // WORD,
        nFileExtension:    0,                                 // WORD,
        lpstrDefExt:       null_mut(),                        // LPCWSTR,
        lCustData:         0,                                 // LPARAM,
        lpfnHook:          None,                              // LPOFNHOOKPROC,
        lpTemplateName:    null_mut(),                        // LPCWSTR,
        pvReserved:        null_mut(),                        // *mut c_void,
        dwReserved:        0,                                 // DWORD,
        FlagsEx:           0,                                 // DWORD,
    };

    match unsafe { GetOpenFileNameW(&mut dlgOpen) } {
        0 => Err("Nothing is selected !".to_string()),
        _ => szw_to_string( &szw_buf ),
    }
}

// Convert from TSzwBuf([u16;512]) to String type.
fn szw_to_string( szwbuf: &TSzwBuf ) -> Result<String> {
    szwbuf.iter()
        .position(|wch| wch == &0)
        .ok_or("String : Can't find zero terminator !".to_owned())
        .and_then(|ix| String::from_utf16( &szwbuf[..ix] )
                              .map_err(|e| e.to_string()))
}

// Convert from String to Vec<u16> with trailing \0.
fn str_to_szw(str_body: &str) -> Vec<u16> {
    return OsStr::new(str_body)
        .encode_wide()
        .chain(once(0))  // 終端文字\0を追加
        .collect::<Vec<u16>>();
}

fn main() {

    let args = env::args().collect::<Vec<String>>();

    if args.len() >= 2 {
        println!("{}", &args[1]);
    }
    else {
        match file_open_dialog() {
            Ok(file_path) => println!("{}", file_path),
            Err(e)        => println!("{}", e),
        };
    }
}
上のコードの (1) 黄色い部分で、 コンソールウインドウを出さない様にしている。 (2) 赤い部分は、winapi 0.3.0以降で変更になった書き方。 winapi 0.2.8 までは use winapi::GetOpenFileNameW; の様に短く書けたんだけど winapi 0.3.0以降は上記のフル指定で書く必要がある。 さらに Cargo.tomlに追加設定が必要。 Cargo.toml
[package]
name = "win32_fopen_dlg"
version = "0.1.0"
authors = ["audin"]

[dependencies]
user32-sys="0.2.0"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.3", features = ["winuser","commdlg"] }
上で、winapi 0.3.0以降を使う時は緑色の部分の追加が必要。 さらに赤い部分で、どのモジュールファイルを使うのかを指定する必要がある。 例えば、GetOpenFileNameW()というAPIの指定方法は、以下のページの一番上の行の検索欄に "GetOpenFileNameW"を入れる。 https://docs.rs/winapi/*/x86_64-pc-windows-msvc/winapi/index.html すると以下の様にフル指定方法がわかる。 https://docs.rs/winapi/*/x86_64-pc-windows-msvc/winapi/um/index.html?search=GetOpenFileNameW また例えば、 USB_DEVICE_SPEEDという定数を使いたい場合、 https://docs.rs/winapi/*/x86_64-pc-windows-msvc/winapi/shared/usbspec/type.USB_DEVICE_SPEED.html?search=USB_DEVICE_SPEED 上の様になるので、Cargo.tomlの featuresは、 features = ["winuser","commdlg","usbspec"] となり、ソースコードには use winapi::shared::usbspec::USB_DEVICE_SPEED; を追加する。 umとかsharedの様な上位階層はfeaturesに指定する必要はない様だ。 native-windows-gui Win32APIのGUIラッパーを作った人がいました。 https://github.com/gabdube/native-windows-gui gitでクローンして Cargo.tomlのあるフォルダで、 cargo run --example showcase cargo run --example canvas cargo run --example templating などと、exapmlesフォルダの中のファイルをコンパイルすると、 ./target/debug/examples/*.exe ができるので実行する。 iniファイルを操作するライブラリ ライブラリというかクレイトと言うらしい。 rust-ini https://crates.io/crates/rust-ini gitリポ https://github.com/zonyitoo/rust-ini 使い方 https://docs.rs/rust-ini/0.10.0/ini/ Windowsのレジストリを操作するライブラリ winreg https://crates.io/crates/winreg gitリポ https://github.com/gentoo90/winreg-rs 試したところちゃんと動きました。
posted by Copyright (C) avrin All Rights Reserved. at 09:01| Comment(0) | Rust言語 | このブログの読者になる | 更新情報をチェックする

2018年01月06日

Crystal言語 (Ruby系コンパイラ) 2018

Crystal言語はRubyの仕様を限定した、
ネイティブコードコンパイラらしい。

ちょっと試してみるか。

と思ったけど Windows非対応みたいなので放置することにした。
orz




posted by Copyright (C) avrin All Rights Reserved. at 20:56| Comment(0) | その他 | このブログの読者になる | 更新情報をチェックする

Rust言語: xargo.exe, cargo-clone.exeをWindows上でインストールする方法 2018

Rust言語: xargo.exe, cargo-clone.exeをWindowsでインストール方法 2018
はじまり
Rust言語の「msvc版」の話。

Rust言語のソースをWindows上で「ARMマイコン等」にクロスコンパイルする場合、
cargo-clone.exe
xargo.exe
のコンパイル、インストールが必要らしい。 と思ったが、 cargo-cloneはなくてもOK(gitで直接持ってくればOK)、 xargoはバイナリが入手できるので cargo-cloneもxargoも無理に自前でコンパイルする必要はない様だ。 以下は参考程度。 前提条件: (1) Rustは「nightly版」が必要。
$ rustup default nightly
で切り替わる。 (2) cmakeがインストールされ、実行ファイルにPATHが通っていること。 (3) 「VS2017用 x86(またはx64) Native Tools」のコマンドライン上で作業を行うこと。 (VS2015用でもいいらしい。未確認) 手順
cargo install cargo-clone
cargo install xargo
でコンパイル、インストールされる。 時間は結構かかる。 ポイント: 普段は「msys2のコンソール」か「PowerShell上」でRust言語のコンパイルをしているが、 上記ツールのインストール時は(3)のコマンドライン上で実行しないとだめだった。 cmakeがないと「libssh2-sys」のコンパイルで失敗するし、 (3)上じゃない場合、最後の最後にリンクで失敗する。 orz orz xargo.exe バイナリ: xargoについてはコンパイル済みのバイナリがここから入手可能です。 https://github.com/japaric/xargo/releases Rustのバージョン: このブログを書いた時点のバージョン nightly-i686-pc-windows-msvc - rustc 1.24.0-nightly (8e7a609e6 2018-01-04) stable-i686-pc-windows-msvc - rustc 1.23.0 (766bd11c8 2018-01-01) 結果: ARM STM32マイコンのコンパイルをやってみたが、 多重定義エラーで玉砕中 orz 引き続き調査中。 ただし、Linux上でやれば無問題の可能性も否定できない。
error[E0152]: duplicate lang item found: `panic_fmt`.
  --> examples\panic.rs:32:1
   |
32 | / unsafe extern "C" fn rust_begin_unwind(
33 | |     args: core::fmt::Arguments,
34 | |     file: &'static str,
35 | |     line: u32,
...  |
48 | |     intrinsics::abort()
49 | | }
   | |_^
   |
   = note: first defined in crate `cortex_m_rt`.

error: aborting due to previous error

error: Could not compile `cortex-m-quickstart`.
サポートするクロスコンパイルターゲット:
$ rustc --print target-list
aarch64-linux-android
aarch64-unknown-cloudabi
aarch64-unknown-freebsd
aarch64-unknown-fuchsia
aarch64-unknown-linux-gnu
aarch64-unknown-linux-musl
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv4t-unknown-linux-gnueabi
armv5te-unknown-linux-gnueabi
armv7-linux-androideabi
armv7-unknown-cloudabi-eabihf
armv7-unknown-linux-gnueabihf
armv7-unknown-linux-musleabihf
asmjs-unknown-emscripten
i586-pc-windows-msvc
i586-unknown-linux-gnu
i686-apple-darwin
i686-linux-android
i686-pc-windows-gnu
i686-pc-windows-msvc
i686-unknown-cloudabi
i686-unknown-dragonfly
i686-unknown-freebsd
i686-unknown-haiku
i686-unknown-linux-gnu
i686-unknown-linux-musl
i686-unknown-netbsd
i686-unknown-openbsd
mips-unknown-linux-gnu
mips-unknown-linux-musl
mips-unknown-linux-uclibc
mips64-unknown-linux-gnuabi64
mips64el-unknown-linux-gnuabi64
mipsel-unknown-linux-gnu
mipsel-unknown-linux-musl
mipsel-unknown-linux-uclibc
msp430-none-elf
powerpc-unknown-linux-gnu
powerpc64-unknown-linux-gnu
powerpc64le-unknown-linux-gnu
s390x-unknown-linux-gnu
sparc64-unknown-linux-gnu
sparc64-unknown-netbsd
sparcv9-sun-solaris
thumbv6m-none-eabi
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
wasm32-experimental-emscripten
wasm32-unknown-emscripten
wasm32-unknown-unknown
x86_64-apple-darwin
x86_64-linux-android
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
x86_64-rumprun-netbsd
x86_64-sun-solaris
x86_64-unknown-bitrig
x86_64-unknown-cloudabi
x86_64-unknown-dragonfly
x86_64-unknown-freebsd
x86_64-unknown-fuchsia
x86_64-unknown-haiku
x86_64-unknown-linux-gnu
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl
x86_64-unknown-netbsd
x86_64-unknown-openbsd
x86_64-unknown-redox
posted by Copyright (C) avrin All Rights Reserved. at 14:12| Comment(0) | Rust言語 | このブログの読者になる | 更新情報をチェックする

Rust言語でSTM32マイコンメモ 2018

Rust言語でSTM32マイコンメモ 2018
はじまり
(1) 
2018年初頭。素晴らしいページを発見したのでひとまず。メモ
STM32F4Discoveryボード用
ARM Cortex-M 32ビットマイコンでベアメタル "Safe" Rust
https://qiita.com/tatsuya6502/items/7d8aaf3792bdb5b66f93

上のページの方の解説が丁寧で感激しました。

発見したばかりなのとLinux用なので、Windows上でも可能かどうか試してみようと
思います。

オリジナルの英語記事はSTM32F3Discoveryボードのようです。
https://japaric.github.io/discovery/02-requirements/README.html


ちなみに、
レジスタ直設定型の LEDチカチカ + 簡易プリエンプティブ型マルチタスク
で、コンパイル後の

FLASHサイズ1440バイト、SRAM 4バイト

だそうです。

これは試したい。


(2) 
    Rustで組み込みプログラム(Cortex-M)
    http://park11.wakwak.com/~nkon/homepc/rust_embedded/

    このページはNucleoでSTM32Cubeを使っている。
    そのうちためそう。

posted by Copyright (C) avrin All Rights Reserved. at 13:51| Comment(0) | Rust言語 | このブログの読者になる | 更新情報をチェックする