FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

ビルドシステムとしてCMakeを導入する

RISC-VシミュレータのビルドシステムとしてCMakeを導入してみた。

CMake

CMakeは、クロスプラットフォームのビルドシステム。LLVMなどで採用されているものだ。Makefileと違って、Windowsなどでもビルドシステムを構築することができるため、汎用的なシステムを構築できる。 今回は、CMakeを使って、Makefileを煩雑に書かずにビルド環境を構築できるようにした。

github.com

CMakeList.txtを記述して、

$ cat CMakeLists.txt
project (swimmer_riscv)

execute_process (COMMAND date +%Y%m%d OUTPUT_VARIABLE CMAKE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND git rev-parse --short HEAD OUTPUT_VARIABLE CMAKE_REVISION OUTPUT_STRIP_TRAILING_WHITESPACE)

set (VERSION ${CMAKE_VERSION})
set (REVISION ${CMAKE_REVISION})
set (CMAKE_BUILD_TYPE Debug)

configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")

add_custom_command (OUTPUT inst_list.h inst_decoder.c inst_decoder.h inst_riscv.h inst_operand.h inst_operand.c inst_mnemonic.c inst_call.c
  COMMAND ruby ./gen_arch_table.rb
  DEPENDS ./gen_arch_table.rb riscv_arch_table.rb
  )

add_custom_command (OUTPUT sysreg_impl.h sysreg_func.h sysreg_rw.h sysreg_rw.c
  COMMAND ruby ./gen_sysreg_table.rb
  DEPENDS ./gen_sysreg_table.rb riscv_sysreg_table.rb
  )

add_executable (../swimmer_riscv
                           swimmer_main.c env.c simulation.c trace.c inst_print.c inst_mnemonic.c
                           inst_call.c inst_decoder.c inst_riscv.c inst_operand.c
                           sysreg_rw.c sysreg_func.c)

このディレクトリで、

cmake .

とタイプすると、自動的にMakefileを生成してくれる。

ちなみに、Swimmer-RISCVは、最初に2つほどrubyスクリプトを動かして、アーキテクチャ情報に基いて命令デコーダと、システムレジスタ一覧を生成する。 これをコンパイル前に実行する必要があるのだが、これを実現しているのが、

add_custom_command (OUTPUT inst_list.h inst_decoder.c inst_decoder.h inst_riscv.h inst_operand.h inst_operand.c inst_mnemonic.c inst_call.c
  COMMAND ruby ./gen_arch_table.rb
  DEPENDS ./gen_arch_table.rb riscv_arch_table.rb
  )

add_custom_command (OUTPUT sysreg_impl.h sysreg_func.h sysreg_rw.h sysreg_rw.c
  COMMAND ruby ./gen_sysreg_table.rb
  DEPENDS ./gen_sysreg_table.rb riscv_sysreg_table.rb
  )

add_custom_command の意味は、OUTPUTの後に記述しているファイルが、COMMANDによって記述されているコマンドによって自動的に生成される。そして、そのCOMMANDを実行するためには、依存関係としてDEPENDSをチェックする必要がある、ということだ。上記の最初のadd_custom_commandの意味は、

inst_list.h inst_decoder.c inst_decoder.h inst_riscv.h inst_operand.h inst_operand.c inst_mnemonic.c inst_call.c を生成するためには、
ruby ./gen_arch_table.rb を実行する必要がある。このコマンドを実行するためには、
./gen_sysreg_table.rb riscv_sysreg_table.rb の依存関係をチェックする必要がある。

ということだ。これで、cmakeを叩くだけで自動的にMakefileが生成され、ビルドシステムが完成する。

$ ls
basic.h         CMakeFiles           CMakeLists.txt  env.c  gen_arch_table.rb    inst_print.c  inst_riscv.c  riscv_arch_table.rb    simulation.c  swimmer_main.c  swimmer_riscv.dir  #text.txt#  trace.h    version.h.in
CMakeCache.txt  cmake_install.cmake  dec_utils.h     env.h  gen_sysreg_table.rb  inst_print.h  Makefile      riscv_sysreg_table.rb  simulation.h  swimmer_main.h  sysreg_func.c      trace.c     version.h
$ cmake .
CMake Warning (dev) at CMakeLists.txt:22 (add_executable):
  Policy CMP0037 is not set: Target names should not be reserved and should
  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
  details.  Use the cmake_policy command to set the policy and suppress this
  warning.

  The target name "../swimmer_riscv" is reserved or not valid for certain
  CMake features, such as generator expressions, and may result in undefined
  behavior.
This warning is for project developers.  Use -Wno-dev to suppress it.

CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 3.0)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /home/vagrant/swimmer_riscv/src
$ make
[  7%] Generating sysreg_impl.h, sysreg_func.h, sysreg_rw.h, sysreg_rw.c
[ 14%] Generating inst_list.h, inst_decoder.c, inst_decoder.h, inst_riscv.h, inst_operand.h, inst_operand.c, inst_mnemonic.c, inst_call.c
Scanning dependencies of target swimmer_riscv
[ 21%] Building C object CMakeFiles/../swimmer_riscv.dir/swimmer_main.o
[ 28%] Building C object CMakeFiles/../swimmer_riscv.dir/env.o
/home/vagrant/swimmer_riscv/src/env.c: In function ‘TAB_enter’:
/home/vagrant/swimmer_riscv/src/env.c:160:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
     index = ((unsigned)key) % TABSIZE;
              ^
/home/vagrant/swimmer_riscv/src/env.c: In function ‘TAB_look’:
/home/vagrant/swimmer_riscv/src/env.c:170:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
     index = ((unsigned)key) % TABSIZE;
              ^
/home/vagrant/swimmer_riscv/src/env.c: In function ‘InsertMemTable’:
/home/vagrant/swimmer_riscv/src/env.c:200:34: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     TAB_enter ((TAB_table)table, (void *)addr, (void *)info);
                                  ^
/home/vagrant/swimmer_riscv/src/env.c:200:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     TAB_enter ((TAB_table)table, (void *)addr, (void *)info);
                                                ^
/home/vagrant/swimmer_riscv/src/env.c: In function ‘SearchMemTable’:
/home/vagrant/swimmer_riscv/src/env.c:212:29: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     return TAB_look (table, (void *)addr);
                             ^
/home/vagrant/swimmer_riscv/src/env.c:212:5: warning: return makes integer from pointer without a cast
     return TAB_look (table, (void *)addr);
     ^
[ 35%] Building C object CMakeFiles/../swimmer_riscv.dir/simulation.o
[ 42%] Building C object CMakeFiles/../swimmer_riscv.dir/trace.o
[ 50%] Building C object CMakeFiles/../swimmer_riscv.dir/inst_print.o
[ 57%] Building C object CMakeFiles/../swimmer_riscv.dir/inst_mnemonic.o
[ 64%] Building C object CMakeFiles/../swimmer_riscv.dir/inst_call.o
[ 71%] Building C object CMakeFiles/../swimmer_riscv.dir/inst_decoder.o
[ 78%] Building C object CMakeFiles/../swimmer_riscv.dir/inst_riscv.o
[ 85%] Building C object CMakeFiles/../swimmer_riscv.dir/inst_operand.o
[ 92%] Building C object CMakeFiles/../swimmer_riscv.dir/sysreg_rw.o
[100%] Building C object CMakeFiles/../swimmer_riscv.dir/sysreg_func.o
Linking C executable ../swimmer_riscv
[100%] Built target ../swimmer_riscv
$ ls
basic.h         cmake_install.cmake  env.c              gen_sysreg_table.rb  inst_decoder.h   inst_operand.c  inst_print.h  Makefile               simulation.c    swimmer_main.h     sysreg_func.h  sysreg_rw.h  trace.h
CMakeCache.txt  CMakeLists.txt       env.h              inst_call.c          inst_list.h      inst_operand.h  inst_riscv.c  riscv_arch_table.rb    simulation.h    swimmer_riscv.dir  sysreg_impl.h  #text.txt#   version.h
CMakeFiles      dec_utils.h          gen_arch_table.rb  inst_decoder.c       inst_mnemonic.c  inst_print.c    inst_riscv.h  riscv_sysreg_table.rb  swimmer_main.c  sysreg_func.c      sysreg_rw.c    trace.c      version.h.in
$