🐯

ia16-elf-gcc で cmake を使ってみた

2024/10/13に公開

ia16-elf-gcc で MSDOS exe を作れてるのだから、watcom 同様 cmake を使いたく。

で公開されてるやり方に倣えば ia16-elf-gcc でも cmake できたのでそのメモです。

手順

お試しの例としては、まず watcom で試した のと同じような環境を用意します。

CMakeLists.txt は

CMakeLists.txt
cmake_minimum_required(VERSION 3.22)

project(hello)

add_executable(hello src/hello.c)

ubuntu 22.04 環境の cmake は ver.3.22 のようで、Watcom に合わせた 3.24 だとエラーになってしまう...ので、とりあえず今回は 3.22 を設定しています。

コンパイラ設定は ia16-elf-exe-toolchain.cmake toolchain.cmake を用意します。

たのしい組み込みCMake を見様見真似で

ia16-elf-exe-toolchain.cmake
# toolchain
set(CMAKE_C_COMPILER ia16-elf-gcc)
set(CMAKE_CXX_COMPILER ia16-elf-g++)
set(CMAKE_AR ia16-elf-ar CACHE FILEPATH "Arhiver")
set(CMAKE_RANLIB ia16-elf-ranlib CACHE FILEPATH "Ranlib")
set(CMAKE_AS ia16-elf-as)
set(CMAKE_NM ia16-elf-nm)
set(CMAKE_OBJDUMP ia16-elf-objdump)

# to pass compiler test
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# target
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR I86)

set(CMAKE_SYSROOT "/usr/ia16-elf")
set(CMAKE_INCLUDE_PATH "${CMAKE_SYSROOT}/include")
set(CMAKE_LIBRARY_PATH "${CMAKE_SYSROOT}/lib")
set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# flags
set(CMAKE_C_FLAGS   "-Wall -Wextra -fno-stack-protector -static -march=i8086 -mcmodel=small ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -fno-stack-protector -static -march=i8086 -mcmodel=small ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-fnothrow-opt -fdelete-dead-exceptions -fno-rtti -fno-exceptions ${CMAKE_CXX_FLAGS}")

# Extension
set(CMAKE_EXECUTABLE_SUFFIX ".exe")
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".exe")
set(CMAKE_EXECUTABLE_SUFFIX_C ".exe")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".exe")

のように作成。

cmake  -DCMAKE_TOOLCHAIN_FILE=../ia16-elf-exe-toolchain.cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../

をすれば Makefile 作成、それを make でビルドできれば ok.

ここでは CMAKE_BUILD_TYPE=MinSizeRel を指定してみました。
hello 程度では意味ありませんが、 Release だと -O3 が使われ太りやすいようなので、MinSizeRel でプログラムサイズを減らす指定を選びました。

ia16-elf-exe-toolchain.cmake について

set(CMAKE_SYSROOT "/usr/ia16-elf") 等、もろに ubuntu 22.04 用の ia16-elf-gcc の環境に依存しています。
その他もそれっぽく設定してみただけ。(不要/デフォルトでよさそうなものは削除)

FLAGS はお好みで...なんだけど。
-march=i8086 -mcmodel=small をデフォルト設定とて入れています。これは、

  add_compile_options(-march=i80186 -mcmodel=medium)

等、後付オプションで前の設定を上書きできる類なので。
(デフォルト設定しておなないと微妙な生成になってそうで)

まあ c++ の場合は tiny か small しか設定できないので、これでいいか、と。

C++ 専用のオプションでは "例外" は無しにしています。お好み次第ですが 16bit 86系/MSDOS でこのへんが効率的に扱えそうにも思えず。(使えなかったか使い物にならなかったか... 実装できたとしても setjump 系だろうで)

考元から追加しているモノとしては、実行ファイル拡張子を設定しているところでしょうか。
CMakeLists.txt 側で出力ファイル名を明示しなくてもいいように、と。

ただ、set(CMAKE_EXECUTABLE_SUFFIX ".exe") では、拡張子付加できませんでした。
ググって ここ で話に出てた拡張子別の設定を試しみたら .exe がついたので、それで吉と。

と、この例では入れていませんが、他ターゲットとの兼ね合いで CMAKE_BUILD_TYPE=MinSizeRel でなく Release でビルドして、サイズ優先したい時は

set(CMAKE_C_FLAGS_RELEASE   "-Os -DNDEBUG" CACHE STRING "description")
set(CMAKE_CXX_FLAGS_RELEASE "-Os -DNDEBUG" CACHE STRING "description")

を追加するのも手です。

※ toolchain.cmake で変数を設定する場合、物によっては見ての通り CACHE …… も指定する必要があるようです。CMakeのツールチェインで変数を扱う際の注意点 を参考。 (しかし、どの変数が付けなきゃいけなくて、どの変数がなくていいのかよくわからない)

com ファイル生成

前記は exe 固定にしてしまったので、tiny モデルで com を作るときは別途 toolchain.cmake を用意することにします。
内容は small → tiny、".exe" → ".com" に置換しただけのものですが。

ia16-elf-com-toolchain.cmake
# toolchain
set(CMAKE_C_COMPILER ia16-elf-gcc)
set(CMAKE_CXX_COMPILER ia16-elf-g++)
set(CMAKE_AR ia16-elf-ar CACHE FILEPATH "Arhiver")
set(CMAKE_RANLIB ia16-elf-ranlib CACHE FILEPATH "Ranlib")
set(CMAKE_AS ia16-elf-as)
set(CMAKE_NM ia16-elf-nm)
set(CMAKE_OBJDUMP ia16-elf-objdump)

# to pass compiler test
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# target
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR I86)

set(CMAKE_SYSROOT "/usr/ia16-elf")
set(CMAKE_INCLUDE_PATH "${CMAKE_SYSROOT}/include")
set(CMAKE_LIBRARY_PATH "${CMAKE_SYSROOT}/lib")
set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# flags
set(CMAKE_C_FLAGS   "-Wall -Wextra -fno-stack-protector -static -march=i8086 -mcmodel=tiny ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -fno-stack-protector -static -march=i8086 -mcmodel=tiny ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-fnothrow-opt -fdelete-dead-exceptions -fno-rtti -fno-exceptions ${CMAKE_CXX_FLAGS}")

# Extension
set(CMAKE_EXECUTABLE_SUFFIX ".com")
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".com")
set(CMAKE_EXECUTABLE_SUFFIX_C ".com")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".com")

ビルドは

cmake  -DCMAKE_TOOLCHAIN_FILE=../ia16-elf-com-toolchain.cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../
make

ubuntu 22.04 で cmake ver.3.24 以上を使えるように

watcom c/c++ と共通の CMakeLists.txt を書く場合は、やっぱり ver.3.24 以上が使えないと辛い... と探してみると

にやり方が公開されていました。

この方法で ubuntu 22.04 でも cmake公式(kitware)のaptリポジトリを追加でき、現行の version(3.30) の cmake が使えるようになりました。

おわりに

cmake は沼...

Discussion