我有2个Dirs和3个头文件存储在其中,如下所示:
目录A:包含头文件A和C. 目录B:包含头文件B
Dirs A和B是名为Apps的目录的子目录(这是其他一些目录的子目录)。
基本上,问题发生在类似的情况下,我从中解决了问题。因此,下面显示的C ++源文件很简单:
头文件A.h:
#ifndef A_H
#define A_H
class A
{
};
#endif /// A_H
头文件C.h:
#ifndef C_H
#define C_H
#include "B.h"
class C
{
};
A.h的测试员,即。 TestA.cpp:
/** TestA.cpp */
#include "A.h"
/// ...
int main()
{
}
C.h的测试员,即。 TestC.cpp:
/** TestC.cpp */
#include "C.h"
/// ...
int main()
{
}
Dir B包含1个C ++头文件B.h及其测试者TestB.cpp,两者都很简单:
头文件B.h:
#ifndef B_H
#define B_H
#include "A.h"
class B
{
};
#endif /// B_H
B.h的测试员,即。 TestB.cpp:
/** TestB.cpp */
#include "B.h"
/// ...
int main()
{
}
3个测试者TestA.cpp,TestB.cpp和TestC.cpp分别有3个makefile:MakeA,MakeB和MakeC。正如预期的那样,MakeA和MakeC在dir A中,MakeB在dir B中。
我没有展示MakeA和MakeB,因为它们正常工作。
MakeC中发生错误:
CPP = g++
OFLAG = -o
CFLAG = -std=c++11 -c
PROG1 = TestC
HC = C
HB = B
HA = A
HBDIR = ../B/
HADIR = ./
IHBDIR = -I$(HBDIR)
IHADIR = -I$(HADIR)
all : $(PROG1).o $(PROG1).exe run1
$(PROG1).o : $(PROG1).cpp $(HADIR)$(HC).h $(HBDIR)$(HB).h $(HADIR)$(HA).h
$(CPP) $(CFLAG) $(IHADIR) $(IHBDIR) $<
$(PROG1).exe : $(PROG1).o
$(CPP) $(OFLAG) $@ $^
run1:
$(PROG1)
此make文件无法找到头文件A(头文件B包含#),并出现以下错误:
In file ...
../B/B.h fatal error: A.h : no such file or directory
#include "A.h"
compilation terminated
显然,make正在B.h的dir中寻找A.h(因为B.h #includes A.h)。但是,我已经定义了符号HADIR(as ./),它应该导致make在默认目录中搜索,即Dir A.
请注意:
1)头文件引用是简单和线性的:A.h是B.h的#included,包括C.h的#include。
2)我不希望在源文件中硬编码dir路径。它们必须只存储在makefile中,因为这是makefile的目的之一。
3)我知道有两种解决方案: a)将C.h,它的测试器和makefile重新定位到目录C.但是,我不想这样做,因为A.h和C.h在语义上是相关的。 b)在MakeC中,将HADIR定义为../A,而不是./但我不明白为什么我应该这样做。
使用MakeC作为输入makefile调用make实用程序的BAT文件如下:
cd /f/Files/C/SW/Applications/Samples/C++Samples/Introductory/
Classes/Apps/A/
make -f MakeC
感谢。
答案 0 :(得分:0)
有关哪些路径包含搜索的信息,请参阅this link。假设您使用的格式为include "file"
(带引号,而不是#include <file>
,这略有不同):
默认情况下,预处理器会查找包含的头文件 指令的引用形式#include&#34; file&#34;第一个相对于 当前文件的目录,然后在预配置的列表中 标准系统目录。例如,如果是/usr/include/sys/stat.h 包含#include&#34; types.h&#34;,GCC首先查找types.h / usr / include / sys,然后在通常的搜索路径中。
...
您可以使用许多命令行选项进行添加 搜索路径的其他目录。最常用的 选项是-Idir,它会导致在当前之后搜索dir 目录(对于指令的引用形式)和之前的 标准系统目录。您可以指定多个-I选项 命令行,在这种情况下搜索目录 从左到右的顺序。
注意
当前文件的目录
指的是从中调用gcc的目录,而不是源文件的目录(不是最好的措辞)。因此,如果从.c文件的目录中调用gcc,则需要在编译器选项中添加-IA -IB
标志,然后在#include
指令中不包含路径(假设gcc为从.c文件的目录中调用。)
如果您确实想要包含路径,它们必须相对于调用gcc的目录,或者其中一个包含-I
选项指定的路径。
----编辑-----
好的,我刚看了你的更新,似乎TestC.c在目录A中,我没有从原来的帖子中获取这意味着你要从目录A编译。在这种情况下我无法重现你的问题(至少在我的linux系统上没有):
[157]~/tmp/tmp9/A> find .. -type f -exec echo "------ " {} " ------" \; -exec more {} \;
------ ../A/A.h ------
#pragma message "A.h"
// blank
------ ../A/C.h ------
#pragma message "C.h"
#include "B.h"
------ ../A/testC.c ------
#pragma "message file.c"
#include "C.h"
int main() {}
------ ../B/B.h ------
#pragma message B.H
#include "A.h"
[157]~/tmp/tmp9/A> gcc -I. -I../B testC.c
In file included from testC.c:2:
C.h:1: note: #pragma message: C.h
In file included from C.h:2,
from testC.c:2:
../B/B.h:1: warning: expected a string after ‘#pragma message’
In file included from ../B/B.h:2,
from C.h:2,
from testC.c:2:
./A.h:1: note: #pragma message: A.h
[157]~/tmp/tmp9/A>
您的make命令应该回显用于构建测试程序的命令 - 将该输出附加到问题。
答案 1 :(得分:0)
每https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_2.html#SEC6:
第2.1节:包含语法
[#include with quotation marks]用于您自己程序的头文件。它在包含当前文件的目录中首先搜索名为file 的文件,然后在与&lt; file&gt;
相同的目录中搜索
由于我们正在讨论来自另一个标题的include-with-quotes,我们必须弄清楚什么是“当前文件”。我们的选择是:
第2.2节:包含操作
`#include'指令的工作原理是指导C预处理器扫描指定的文件作为输入,然后再继续使用当前文件的其余部分
对我来说,这个措辞暗示#include
充当“当前文件”处理的中断,在此期间包含的文件变为“当前”。 (如果#include
被解释为将扩展为或作为 #including
文件的一部分,请考虑如何编写此内容。)此外,如果{#1}}的引号版本在#including文件的上下文中被解释,它将会一直中断并且几乎没用。
因此#include
中的#include "A.h"
会查找相对于B.h
位置的A.h
。但B.h
不等于$HADIR
,因此此查找失败。
但请注意 $HBDIR
添加到应-I
搜索的地点列表 - 带角括号...... 也应< / strong>在#include
的“当前文件的目录”之后搜索 - 带引号...所以你的编译器正在用它的搜索做一些奇怪的事情。
我也确认gcc 4.8.5不会重现您的问题。这是我相对于目录#include
Prog
然后建立收益率:
[Prog]$ find ..
../Prog
../Prog/A.h
../Prog/MakeC
../Prog/TestA.cpp
../Prog/TestC.cpp
../Prog/C.h
../B
../B/B.h
../B/TestB.cpp
你使用的是什么编译器?(我敢打赌它是旧的(大约是gcc 2.9.6)还是由供应商定制以定位嵌入式平台)我见过有趣的是包括一些路径检查。
这是一个小型的设计演示,用于显示[Prog]$ make -f MakeC
g++ -std=c++11 -c -I./ -I../B/ TestC.cpp
g++ -o TestC.exe TestC.o
TestC
的正确行为 - 带引号:
INC / A.H
#include
INC / b.h
#pragma once
#include "b.h"
test.c的
#pragma once
extern int garbage;
然后
#include "inc/a.h"
请注意,主$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.c"
# 1 "inc/a.h" 1
# 1 "inc/b.h" 1
extern int garbage;
# 4 "inc/a.h" 2
# 1 "test.c" 2
文件直接包含.c
,并且编译器命令行上没有给出搜索路径,但它仍然找到"inc/a.h"
。
答案 2 :(得分:0)
OK, I've finally solved the problem as follows:
1) Make the BAT file set the default dir to 1 dir above the A and B dirs, ie, to the Apps dir, and invoke the make utility from there:
<?php
$colors_counter = 0;
$colors = array(0=>"blue", 1=>"red", 2=>"green", 3=>"yellow");
?>
@foreach($posts as $post)
<div class="header-{{ $colors[$colors_counter] }}">
{{ $post->name }}
</div>
<?php $colors_counter++; ?>
@endforeach
2) Modify the makefile to access each header explicitly from the dir in which it is stored, create the obj and exe file in a specified dir and invoke the exe file in the specified dir:
cd /f/Files/C/SW/Applications/Samples/C++Samples/Introductory/Classes/Apps/
make -f A/MakeC
As I've stated, I'm using g++ 4.8.1.
What worked for me, was to have the invoking BAT file set the default dir to one level above the dirs that contain the source files and in the makefile, specify the dirs explicitly.
---- EDIT ----
I'd like to suggest a possible reason for why this works.
First, notice that originally, the HADIR variable was set to ./ (the default dir).
As @lockcmpxchg8b said, the "default dir" could be interpreted as (a) wrt the original file or (b) the #included header file. These are the only 2 possibilities. Since the compiler can't find the #included header, it means it has selected the wrong possibility. This is obviously a version-specific gcc problem, since others can't repro the problem on later gcc versions.
Then, the solution is to avoid using ./ as a value for a dir symbol such as HADIR. Instead set the default dir outside make to another dir. In this case, it was done to the dir one level above A and B (viz. Apps). Then, the makefile's dir symbols can be made all wrt to that dir and would obviously not be ./
With values other than ./ (interpreted as the default dir by the compiler), the compiler interprets the value for the dir symbol as desired.
答案 3 :(得分:-1)
我想在你的&#34; B.h&#34;中,你应该这样做:fun bits(value: Int): BooleanArray {
var x = value.toDouble()
val result = BooleanArray (32)
for (i in 31 downTo 0) {
val d = Math.pow(2.0, i.toDouble())
if (x >= d) {
x -= d
result[i] = true
}
}
return result
}
好像&#34; A.h&#34;位于&#34; B.h&#34;的相邻目录中。目录。所以当&#34; B.h&#34;试图在当前目录中查找它,它无法找到它。
我在猜#include "(Adir)/A.h"