#include_nextについて(gcc, clangのinclude pathについて)
はじめに
nuttxをclangでビルドしたときに以下のようなエラーが出ました。
In file included from stdio/lib_dtoa_engine.c:41:
In file included from /home/saitoyutaka/spresense/nuttx/include/math.h:52:
/home/saitoyutaka/spresense/nuttx/../sdk/include/arch/math.h:42:15: fatal error: 'math.h' file not found
#include_next <math.h>
^~~~~~~~
1 error generated.
ERROR: clang -v failed: 1
#include_next
がよくわからなかったので調べてみました。
include_next ドキュメント
gccのドキュメントはここ
include_nextはいつからあるか。
不明。
gccのコードを取ってきて、grepしたら以下のようなものが引っかかりました。
1998年くらいには #include_next
というものはあったのでしょうか。
1998-12-16 Zack Weinberg
* cpplib.c (do_include): Treat #include_next in the
primary source file as #include plus warning. Treat
#include_next in a file included by absolute path as an
error. fp == CPP_NULL_BUFFER is a fatal inconsistency.
include_nextを試しに使ってみる
以下のようにファイルを用意。
.
├── inc
│ └── h1.h
├── inc2
│ └── include
│ └── h1.h
└── src
└── main.c
ファイルの中身はそれぞれ以下のようにする。
#include <stdio.h>
#include <h1.h>
int main(void){
printf("hello %d\n", INC_NUM1);
printf("hello %d\n", INC_NUM_TEST);
return 0;
}
#define INC_NUM1 11
#define INC_NUM_TEST 11
#include_next <h1.h> // inc2/include/h1.h
#define INC_NUM_TEST 12
以下のようにコンパイル。
INC_NUM_TEST
の値が12(include/h1.h)となる。
$ gcc -isystem ../inc -isystem ../inc2/include main.c
$ ./a.out
hello 11
hello 12
clangではどうか。
$ clang -isystem ../inc -isystem ../inc2/include main.c
$ ./a.out
hello 11
hello 12
上記のように、#include_next
を使うと、
inc/h1.h
の次にある検索パスのinc2/include/h1.h
が読み込まれます。
sdk/include/arch/math.hに以下のようにコメントが書かれていますが、
#ifndef SDK_INCLUDE_ARCH_MATH_H
#define SDK_INCLUDE_ARCH_MATH_H
/* XXX: #include_next directive is only in GCC. */
#include_next <math.h>
最近(?)はclangでも#include_nextは使用できるようになっているようでした。
"はじめに"で書いたエラーはなんで出た?
次に、以下のようなコードを用意します。
#include <math.h>
#include_next <math.h>
int main(void){
return 100;
}
今度は、arm用にコンパイルをします。
$ arm-none-eabi-gcc -mabi=aapcs -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c sample.c
sample.c:2:2: warning: #include_next in primary source file
2 | #include_next <math.h>
| ^~~~~~~~~~~~
$ file sample.o
sample.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped
ワーニングはでるけど、コンパイルはできる。
つづいてclagで確認。
$ clang -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -c sample.c
sample.c:1:10: fatal error: 'math.h' file not found
#include <math.h>
^~~~~~~~
1 error generated.
#include
のところでファイルがないよ、とエラーとなりました。
原因はコンパイル時のオプションのに-v
をつけるとわかります。
gccの場合
#include <...> search starts here:
以降の出力に注目。
$ arm-none-eabi-gcc -mabi=aapcs -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c -v sample.c
Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
Target: arm-none-eabi
<省略>
#include "..." search starts here:
#include <...> search starts here:
/home/saitoyutaka/arm-gcc/gcc-arm-none-eabi-10-2020-q4-major/bin/../lib/gcc/arm-none-eabi/10.2.1/include
/home/saitoyutaka/arm-gcc/gcc-arm-none-eabi-10-2020-q4-major/bin/../lib/gcc/arm-none-eabi/10.2.1/include-fixed
/home/saitoyutaka/arm-gcc/gcc-arm-none-eabi-10-2020-q4-major/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/include
End of search list.
GNU C17 (GNU Arm Embedded Toolchain 10-2020-q4-major) version 10.2.1 20201103 (release) (arm-none-eabi)
compiled by GNU C version 4.8.4, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.18-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: e9addb35ad3a920a846c18a834db924d
sample.c:2:2: warning: #include_next in primary source file
2 | #include_next <math.h>
| ^~~~~~~~~~~~
<省略>
clangの場合
$ clang -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -c -v sample.c
clang version 11.0.0 (https://github.com/llvm/llvm-project.git 0160ad802e899c2922bc9b29564080c22eb0908c)
Target: arm-none-unknown-eabi
<省略>
#include "..." search starts here:
#include <...> search starts here:
/home/saitoyutaka/clang/clang+llvm-11.0.0-x86_64-linux-gnu-ubuntu-20.04/lib/clang/11.0.0/include
End of search list.
sample.c:1:10: fatal error: 'math.h' file not found
#include <math.h>
^~~~~~~~
1 error generated.
clangの場合includeパスが
/home/saitoyutaka/clang/clang+llvm-11.0.0-x86_64-linux-gnu-ubuntu-20.04/lib/clang/11.0.0/include
のみです。
しかもパスの名前からするとarm用っぽくない。
不明点
arm-none-eabi-gcc
の場合
/lib/gcc/arm-none-eabi/10.2.1/include
/lib/gcc/arm-none-eabi/10.2.1/include-fixed
/lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/include
のパスはデフォルトで入る?
まとめ
いろいろ、調べてみましたが原因は
インクルードパスの設定ができていないことが原因でいた。
#include_next directive is only in GCC.
というコメントが
あったので、最初はclangでは(include_nextを使用しないで)どうやるのかな、
と考えていろいろ調べてしまっていました。(はー)
Discussion