linux c 预编译头,c-GCC-多个预编译的标头和特定路径

博客讨论了一个大型Makefile项目在跨平台并行构建时遇到的预编译头文件(GCH)问题。作者指出,尽管预编译头文件可以提高构建速度,但当它们位于源文件路径之外时,GCC无法正确检测和使用它们。解决方案是创建一个伪匹配头文件以确保GCC在正确的目录中查找和使用预编译头文件。
摘要由CSDN通过智能技术生成

背景

我有一个正在处理的大型Makefile项目,我想整理一下.它构建了几十个子项目,每个子项目包含大约100个.cpp和.h文件.我已经对其进行设置,以便它能够为多种操作系统(Linux,OSX / Mac,QNX等)和多种体系结构(x86 / i386,x64 / amd64,armhf,arm64 / aarch64)构建调试版本并发布版本在平行下.这是因为这是一个庞大的项目,而使其快速构建的唯一方法是与多个工具链并行.

我有一个主要规则,那就是所有项目在构建时都应遵守将中间对象(即.o文件)存储在临时目录中的原则.因此,为Linux,arm64,发布模式构建test.c;将在当前工作目录的以下子目录中构建目标文件:

.tmp/Linux/arm64/release

问题

此功能在我的版本中可以正常工作,但是使用此设置,我似乎无法在GCC中正确使用预编译的标头(即.GCH文件).通过我的设置,我有一个stdafx.h / stdafx.cpp对.使用GCC,我可以很容易地创建一个stdafx.h.gch文件.但是,如果文件与源文件位于同一路径,则该项目似乎仅使用它(这会加快构建速度).如果预编译的头文件位于中间对象路径(即.tmp / Linux / arm64 / release)中,则不会检测到或使用该头文件.即使我将包含路径显式添加到包含gch文件的中间对象路径中,它也会失败.包含文件名本身的完整路径会导致将其视为无效的链接描述文件,并被忽略.

因此,我的第一个解决方法是制定一条规则,以强制所有OS / arch构建在初始预编译头生成时等待,而不是在每个OS / arch基础上构建gch.但是,如果我使用发布模式设置构建gch并尝试进行调试构建,则会收到以下警告:

warning: stdafx.h.gch: created with -gnone, but used with -gdwarf-2

首先,我不知道这是否会对我的构建产生严重的后果,其次,不同的操作系统可能会为gch生成传递不同的编译时定义标志,因此这不是“一刀切”的用例,因为据我所知.

如何解决此问题,以便预编译的标头位于$PWD以外的位置,并且GCC可以检测到它?我目前正在使用gcc v5.3.1.

谢谢.

解决方法:

这是您的问题的MVCE

场景:

main.c

#include

#include

int main(void)

{

puts(HW);

return 0;

}

w

#ifndef HW_H

#define HW_H

#define HW "Hello World"

#endif

生成文件

srcs := main.c

objs := $(addprefix tmp/,$(srcs:.c=.o))

pch := tmp/hw.h.gch

CPPFLAGS += -I.

.PHONY: all clean

all: hw

tmp:

mkdir -p tmp

tmp/%.o: %.c | $(pch)

gcc -c $(CPPFLAGS) -o $@ $<

$(pch): hw.h | tmp

gcc -c $(CPPFLAGS) -o $@ $<

ifdef ENFORCE_PCH

echo "#error Debug." >> $^

endif

hw: $(objs)

gcc -o $@ $^

clean:

sed -i '/^#error/d' hw.h

rm -fr hw tmp

该项目在tmp中输出其中间文件. .o文件去那里

PCH hw.h.gch也是如此.

生成并运行它:

$make && ./hw

mkdir -p tmp

gcc -c -I. -o tmp/hw.h.gch hw.h

gcc -c -I. -o tmp/main.o main.c

gcc -o hw tmp/main.o

Hello World

到现在为止还挺好.但是它实际上使用了PCH吗?让我们来看看:

$make clean

sed -i '/^#error/d' hw.h

rm -fr hw tmp

$make ENFORCE_PCH=true

mkdir -p tmp

gcc -c -I. -o tmp/hw.h.gch hw.h

echo "#error Debug." >> hw.h

gcc -c -I. -o tmp/main.o main.c

In file included from main.c:1:0:

./hw.h:5:2: error: #error Debug.

#error Debug.

^

Makefile:15: recipe for target 'tmp/main.o' failed

make: *** [tmp/main.o] Error 1

不,不是.我们知道,因为定义了ENFORCE_PCH,

在生成了#error指令后,将其添加到hw.h的末尾

好的tmp / hw.h.gch.因此,如果前者随后在任何地方#include-include

而不是后者,构建中断.它只是做了.

A precompiled header file is searched for when #include is seen in the compilation.

As it searches for the included file (see Search Path) the compiler looks for a

precompiled header in each directory just before it looks for the include file in

that directory. The name searched for is the name specified in the #include with ‘.gch’

appended. If the precompiled header file can’t be used, it is ignored.

因此,给定包含搜索路径.,指令#include< hw.h>会引发

gcc在使用./hw.h之前先检查PCH ./hw.h.gch

没有./hw.h.gch,它将使用./hw.h.

从刚刚引用的文档中可以看出,将tmp添加到包含搜索路径-CPPFLAGS = -Itmp -I. -应该引起

优先于./hw.h使用的tmp / hw.h.gch.但是实际上,这没有什么区别.

该文档省略了至关重要的条件.第二句话应改为:

As it searches for the included file (see Search Path) the compiler looks for a

precompiled header in each directory just before it looks for the include file in

that directory and will use the precompiled header for preference if the include file

is found.

要找到并使用,PCH必须是匹配头的同级.并考虑

这就是你想要的.否则,没有匹配的同级标头的a / foo.h.gch可能是

当存在b / foo.h.gch并具有匹配的b / foo.h时,感谢-Ia找到并使用了该命令,

后来的-Ib可以找到并使用它.显然,后者是更合理的选择.

有了这种见识,不难发现解决方案:如果您真的要编译和使用

不是源标头同级的PCH,请确保为其提供伪匹配标头

那是一个兄弟姐妹.您可以根据自己的喜好安排此项,例如

Makefile(固定)

srcs := main.c

objs := $(addprefix tmp/,$(srcs:.c=.o))

pch := tmp/hw.h.gch

# Seek headers in tmp first...

CPPFLAGS += -Itmp -I.

.PHONY: all clean

all: hw

tmp:

mkdir -p tmp

tmp/%.o: %.c | $(pch)

gcc -c $(CPPFLAGS) -o $@ $<

$(pch): hw.h | tmp

# Make phony header in tmp...

echo "#error You should not be here" > $(basename $@)

gcc -c $(CPPFLAGS) -o $@ $<

ifdef ENFORCE_PCH

echo "#error Debug." >> $^

endif

hw: $(objs)

gcc -o $@ $^

clean:

sed -i '/^#error/d' hw.h

rm -fr hw tmp

看到从tmp使用了PCH:

$make clean

sed -i '/^#error/d' hw.h

rm -fr hw tmp

$make ENFORCE_PCH=true && ./hw

mkdir -p tmp

# Make phony header in tmp...

echo "#error You should not be here" > tmp/hw.h

gcc -c -Itmp -I. -o tmp/hw.h.gch hw.h

echo "#error Debug." >> hw.h

gcc -c -Itmp -I. -o tmp/main.o main.c

gcc -o hw tmp/main.o

Hello World

标签:gcc,makefile,precompiled-headers,linux,c-4

来源: https://codeday.me/bug/20191118/2029866.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 交叉编译工具arm-linux-gcc-3.4.1.tar.bz2是一个用于在x86架构的计算机上编译生成运行在ARM架构处理器上的软件的工具。ARM处理器通常用于嵌入式系统和移动设备。 这个工具是一个tar.bz2格式的压缩文件,需要通过解压缩来获取其中的文件。一般的解压缩软件如tar和bzip2可以用来解压这个文件。解压缩后,我们可以得到一个目录,其中包含了交叉编译工具链的各个组件。 这个工具中最关键的组件是arm-linux-gcc,它是一款ARM架构的C编译器。它允许我们在x86架构的计算机上编译ARM平台的C语言源代码,并生成适用于ARM处理器的可执行程序。除了C语言,arm-linux-gcc还支持C++和其他一些常用的编程语言。 使用交叉编译工具arm-linux-gcc,我们可以在开发软件时将代码编译为ARM平台可执行文件,而不需要在ARM设备上进行开发和编译。这样可以提高开发效率并简化调试过程。开发人员可以直接在自己的PC上编写和测试代码,然后使用交叉编译工具生成ARM平台可执行文件,再将其上传到ARM设备上运行。 总之,交叉编译工具arm-linux-gcc-3.4.1.tar.bz2是一个用于在x86架构计算机上编译ARM平台可执行文件的工具链,它提供了一系列的工具和组件,其中最重要的是arm-linux-gcc编译器。使用这个工具,开发人员可以在PC上进行ARM开发和调试,提高开发效率并简化部署过程。 ### 回答2: arm-linux-gcc-3.4.1.tar.bz2是一种交叉编译工具。交叉编译是指在一种操作系统上编译运行在另一种操作系统中运行的程序。 arm-linux-gcc-3.4.1.tar.bz2是专门为ARM架构设计的编译工具。ARM架构是一种广泛应用于嵌入式设备中的处理器架构。由于ARM处理器具有低功耗、低成本和高性能的特点,因此在移动设备、智能家居、工业自动化等领域得到广泛应用。 arm-linux-gcc-3.4.1.tar.bz2是GNU Compiler Collection(GCC)的一个特定版本。GCC是一种开源的编译器套件,支持多种编程语言,包括C、C++和Fortran等。通过使用arm-linux-gcc-3.4.1.tar.bz2,开发人员可以在主机操作系统(通常是x86架构)上编译适用于ARM处理器的程序。 交叉编译工具arm-linux-gcc-3.4.1.tar.bz2使用.tar.bz2的压缩格式打包。用户需要先解压缩该文件,然后根据安装指南进行安装和配置。安装成功后,用户可以使用该工具链进行ARM架构的程序开发和编译。 在交叉编译过程中,需要设置正确的目标架构和其他相关参数,以确保生成的可执行文件可以在ARM设备上正确运行。交叉编译工具可以生成与目标设备兼容的二进制代码,并处理与特定硬件平台相关的问题,如指令集、内存管理等。 通过使用arm-linux-gcc-3.4.1.tar.bz2,开发人员可以更加方便地进行ARM设备上的软件开发。这个工具链为ARM平台上的开发者提供了编译、链接和调试等必要的工具。它有助于简化开发流程,提高开发效率,并确保生成的程序在ARM设备上的正确运行。 ### 回答3: 交叉编译工具arm-linux-gcc-3.4.1.tar.bz2 是一个用于ARM架构的交叉编译工具。交叉编译是指在一种平台上开发、编译和生成另一种平台上可执行的程序。ARM是一种广泛应用于嵌入式设备的处理器架构,通过使用交叉编译工具,开发者可以在PC机上编写并编译ARM架构的程序。 arm-linux-gcc-3.4.1.tar.bz2 是一个tar压缩和bzip2压缩的文件。tar是一种文件打包的格式,bzip2是一种压缩格式。因此,首先需要将该文件解压缩。可以使用tar和bzip2命令来进行解压缩操作。 解压缩后,可以得到一个目录,里面包含了arm-linux-gcc-3.4.1工具链的文件。工具链是一组可以在一台计算机上生成可在另一种架构上运行的程序的工具。 在使用交叉编译工具之前,还需要将工具链的路径添加到系统的环境变量中,这样系统才能够找到正确的工具链。 使用arm-linux-gcc-3.4.1工具链可以在PC机上编写ARM架构的程序,并通过交叉编译生成可在ARM设备上运行的可执行程序。通过交叉编译,开发者可以更方便地开发和调试ARM设备的程序,同时提高了开发效率。 总之,arm-linux-gcc-3.4.1.tar.bz2 是一个交叉编译工具,通过解压缩该文件并配置环境变量后,开发者可以在PC机上编写并编译ARM架构的程序。这样可以简化ARM设备的开发和调试过程,提高开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值