如何从 header 文件正确制作 object 文件(使用带有 debian linux 机器的 I2C 板)
How to properly make a object file from header file (using an I2C board with a debian linux machine)
我有一些以前为 X86 架构编译的源文件。现在我需要为 ARM 架构编译它们。当我尝试使用类似
的东西时
g++ -c -x c++ foo.h
gcc -c -x c foo.h
它只给我很少的指示。我相信它不会 link 我的 header 文件到其他包含的文件。我只得到 "Disassembly of section .comment:"。
请注意它确实会提示我输入其他文件,例如,如果 foo 包含 foo1.h 和 foo2.h,如果我不在同一目录中包含 foo1 和 foo2 headers,则编译器不会没用。
我不明白的另一件事是 gcc 和 g++ 生成相同的汇编代码,可能是因为它们只生成注释部分,所以它们看起来相同。
关于我的问题的更多细节:
我正在使用 USB-I2C 转换器板。该板仅支持 x86/x64 架构。我设法访问源文件并获得 driver 设置。现在我需要一起测试所有内容。为此,我需要能够编译示例代码。当我想这样做时,它会调用需要在 .a 扩展名中的静态库。我需要创建自己的 library.a 文件。为此,我找到了源 c 文件 (.h header)。现在我需要在编译期间将它们 link 在一起并制作 object 文件,并最终将它们一起归档在一个 .a 文件中。
谢谢你的帮助。
编辑(更新):
我到目前为止所取得的成就的快速总结:
- 我能够从 github 存储库中找到 driver。
- 我能够制作模块
- 我还从 raspbian 源代码编译了一个新内核(我正在为 Raspberry PI3 这样做):
uname -a
Linux raspberrypi 4.9.35-v7+ #1 SMP Tue Jul 4 22:40:25 BST 2017 armv7l GNU/Linux
我能够正确加载模块:
lsmod
使用的模块大小
spi_diolan_u2c 3247 0
i2c_diolan_u2c 3373 0
diolan_u2c_core 4268 2 i2c_diolan_u2c,spi_diolan_u2c
lsusb
总线 001 设备 010:ID a257:2014
dmesg
[126.758990]i2c_diolan_u2c:加载out-of-tree模块污染内核。
[126.759241]i2c_diolan_u2c:未知符号diolan_u2c_transfer(错误0)
[ 130.651475] i2c_diolan_u2c: 未知符号 diolan_u2c_transfer (err 0)
[154.671532]usbcore:注册新接口driverdiolan-u2c-core
[5915.799739]usb 1-1.2:USB断开连接,设备号4
[10591.295014] USB 1-1.2:新的 full-speed USB 设备编号 6 使用 dwc_otg
[10591.425984] USB 1-1.2:发现新 USB 设备,idVendor=a257,idProduct=2014
[10591.425997] usb 1-1.2:新 USB 设备字符串:Mfr=1,Product=2,SerialNumber=0
[10591.426005] USB 1-1.2:产品:迪奥兰DLN1
[10591.426012] USB 1-1.2: 制造商: Diolan
我不确定的是:
如果内核 space 正确映射到物理硬件(如果加载的模块可以获取我的 diolan-board)!!!
进展:根据我的研究,我认为 hot-plug 协议可以解决这个问题,但不确定!
困惑:为什么 lsusb 仍然只显示设备 ID。我知道制造商和内核 driver 可以确定要显示的信息,但只显示 ID 对我来说似乎不合适
我现在想做的事情:
我想编写一个简单的 c 源代码或 python 代码来与我的设备交互。基本上我不知道如何在用户 space 和内核 space 之间建立联系。制造商提供了一些源代码示例、库等。但是,我已经放弃使用它们,因为它们是基于 qt 的另一种体系结构,而且我发现几乎不可能找到它们在静态库中使用的库的替代品(我通过恢复它们提供的 .a 存档文件来计算这些库对于 x86)
我只需要确切地知道下一步应该做什么,以便继续让董事会与 PI 合作。
谢谢:)
你不编译头文件,你编译包含它们的 C 文件。
头文件中的所有代码都应该是声明和类型定义,它们为编译器提供信息,但实际上并不生成任何机器代码。这就是为什么您的目标文件中没有任何内容。
您不进行任何object file from a header file. On Linux object files (and executables) are ELF files. Use file(1) (or objdump(1) ...)检查。
相反,应该包含一个头文件(来自 #include
preprocessor directive) in some *.cc
file (technically a translation unit)。
(你可以precompile headers,但这只对改善编译时间有用,它并不总是这样,并且是一个高级的和 GCC 特定的用法; 参见 this)
你把一个C++源文件(一些*.cc
文件)编译成一个后缀为.o
的目标文件(或者一个C源文件*.c
编译成一个后缀为[=的目标文件) 14=])
阅读更多关于 preprocessor 的内容,并花几天时间阅读 C 或 C++(它们是 不同的 编程语言)。另请阅读有关编译和链接的更多信息。
我建议使用 g++ -Wall -Wextra -g
编译您的 C++ 代码以获得所有警告(使用 -Wall -Wextra
)和调试信息(使用 -g
)。
将 C++ 中的一些 yourfile.cc
编译成目标文件 yourfile.o
的最小编译命令应该是
g++ -c -Wall -Wextra -g yourfile.cc
(你可以删除 -Wall -Wextra -g
但我 强烈 建议保留它们)
您可能需要向 g++
添加其他参数。他们订购很重要。阅读有关 Invoking GCC
的章节
请注意 yourfile.cc
很可能包含一些(通常是几个)#include
指令(通常在其开头附近)
您很少需要 -x c++
选项到 g++
(或 -x c
和 gcc
)。我一生只用过一次。在你的情况下,这肯定是一个错误。
您经常使用一些 build automation tool like GNU make. So you just use make
to compile (but you need to write a Makefile
- 其中 tab 很重要)
请注意,有些库可以是 header only(但这不是很常见),那么您不会从它们构建任何共享或静态 ELF 库,而只是在您自己的 C 或C++ 代码。
附录
关于您的 http://dlnware.com/sites/dlnware.com/files/downloads/linux_setup.2.0.0.zip package (which indeed is poorly documented), you should look at the several examples given in the linux_setup/examples/
directory. Such code all have a #include "../common/dln_generic.h"
(for instance, 4th line of examples/leds_gui/main.cpp
) which itself have other includes. All the examples are Qt applications and provide a *.pro
file for qmake
(它本身从 .pro
文件中为 make
生成 Makefile
)。并且根本没有提及将 -x c++
传递给 g++
。
我有一些以前为 X86 架构编译的源文件。现在我需要为 ARM 架构编译它们。当我尝试使用类似
的东西时g++ -c -x c++ foo.h
gcc -c -x c foo.h
它只给我很少的指示。我相信它不会 link 我的 header 文件到其他包含的文件。我只得到 "Disassembly of section .comment:"。 请注意它确实会提示我输入其他文件,例如,如果 foo 包含 foo1.h 和 foo2.h,如果我不在同一目录中包含 foo1 和 foo2 headers,则编译器不会没用。
我不明白的另一件事是 gcc 和 g++ 生成相同的汇编代码,可能是因为它们只生成注释部分,所以它们看起来相同。
关于我的问题的更多细节: 我正在使用 USB-I2C 转换器板。该板仅支持 x86/x64 架构。我设法访问源文件并获得 driver 设置。现在我需要一起测试所有内容。为此,我需要能够编译示例代码。当我想这样做时,它会调用需要在 .a 扩展名中的静态库。我需要创建自己的 library.a 文件。为此,我找到了源 c 文件 (.h header)。现在我需要在编译期间将它们 link 在一起并制作 object 文件,并最终将它们一起归档在一个 .a 文件中。 谢谢你的帮助。
编辑(更新):
我到目前为止所取得的成就的快速总结: - 我能够从 github 存储库中找到 driver。 - 我能够制作模块 - 我还从 raspbian 源代码编译了一个新内核(我正在为 Raspberry PI3 这样做):
uname -a
Linux raspberrypi 4.9.35-v7+ #1 SMP Tue Jul 4 22:40:25 BST 2017 armv7l GNU/Linux
我能够正确加载模块:
lsmod 使用的模块大小 spi_diolan_u2c 3247 0 i2c_diolan_u2c 3373 0 diolan_u2c_core 4268 2 i2c_diolan_u2c,spi_diolan_u2c
lsusb 总线 001 设备 010:ID a257:2014
dmesg [126.758990]i2c_diolan_u2c:加载out-of-tree模块污染内核。 [126.759241]i2c_diolan_u2c:未知符号diolan_u2c_transfer(错误0) [ 130.651475] i2c_diolan_u2c: 未知符号 diolan_u2c_transfer (err 0) [154.671532]usbcore:注册新接口driverdiolan-u2c-core [5915.799739]usb 1-1.2:USB断开连接,设备号4 [10591.295014] USB 1-1.2:新的 full-speed USB 设备编号 6 使用 dwc_otg [10591.425984] USB 1-1.2:发现新 USB 设备,idVendor=a257,idProduct=2014 [10591.425997] usb 1-1.2:新 USB 设备字符串:Mfr=1,Product=2,SerialNumber=0 [10591.426005] USB 1-1.2:产品:迪奥兰DLN1 [10591.426012] USB 1-1.2: 制造商: Diolan
我不确定的是: 如果内核 space 正确映射到物理硬件(如果加载的模块可以获取我的 diolan-board)!!! 进展:根据我的研究,我认为 hot-plug 协议可以解决这个问题,但不确定! 困惑:为什么 lsusb 仍然只显示设备 ID。我知道制造商和内核 driver 可以确定要显示的信息,但只显示 ID 对我来说似乎不合适
我现在想做的事情: 我想编写一个简单的 c 源代码或 python 代码来与我的设备交互。基本上我不知道如何在用户 space 和内核 space 之间建立联系。制造商提供了一些源代码示例、库等。但是,我已经放弃使用它们,因为它们是基于 qt 的另一种体系结构,而且我发现几乎不可能找到它们在静态库中使用的库的替代品(我通过恢复它们提供的 .a 存档文件来计算这些库对于 x86)
我只需要确切地知道下一步应该做什么,以便继续让董事会与 PI 合作。 谢谢:)
你不编译头文件,你编译包含它们的 C 文件。
头文件中的所有代码都应该是声明和类型定义,它们为编译器提供信息,但实际上并不生成任何机器代码。这就是为什么您的目标文件中没有任何内容。
您不进行任何object file from a header file. On Linux object files (and executables) are ELF files. Use file(1) (or objdump(1) ...)检查。
相反,应该包含一个头文件(来自 #include
preprocessor directive) in some *.cc
file (technically a translation unit)。
(你可以precompile headers,但这只对改善编译时间有用,它并不总是这样,并且是一个高级的和 GCC 特定的用法; 参见 this)
你把一个C++源文件(一些*.cc
文件)编译成一个后缀为.o
的目标文件(或者一个C源文件*.c
编译成一个后缀为[=的目标文件) 14=])
阅读更多关于 preprocessor 的内容,并花几天时间阅读 C 或 C++(它们是 不同的 编程语言)。另请阅读有关编译和链接的更多信息。
我建议使用 g++ -Wall -Wextra -g
编译您的 C++ 代码以获得所有警告(使用 -Wall -Wextra
)和调试信息(使用 -g
)。
将 C++ 中的一些 yourfile.cc
编译成目标文件 yourfile.o
的最小编译命令应该是
g++ -c -Wall -Wextra -g yourfile.cc
(你可以删除 -Wall -Wextra -g
但我 强烈 建议保留它们)
您可能需要向 g++
添加其他参数。他们订购很重要。阅读有关 Invoking GCC
请注意 yourfile.cc
很可能包含一些(通常是几个)#include
指令(通常在其开头附近)
您很少需要 -x c++
选项到 g++
(或 -x c
和 gcc
)。我一生只用过一次。在你的情况下,这肯定是一个错误。
您经常使用一些 build automation tool like GNU make. So you just use make
to compile (but you need to write a Makefile
- 其中 tab 很重要)
请注意,有些库可以是 header only(但这不是很常见),那么您不会从它们构建任何共享或静态 ELF 库,而只是在您自己的 C 或C++ 代码。
附录
关于您的 http://dlnware.com/sites/dlnware.com/files/downloads/linux_setup.2.0.0.zip package (which indeed is poorly documented), you should look at the several examples given in the linux_setup/examples/
directory. Such code all have a #include "../common/dln_generic.h"
(for instance, 4th line of examples/leds_gui/main.cpp
) which itself have other includes. All the examples are Qt applications and provide a *.pro
file for qmake
(它本身从 .pro
文件中为 make
生成 Makefile
)。并且根本没有提及将 -x c++
传递给 g++
。