c - 如何在 Gradle 中为 C 源代码构建二进制文件,但不可执行?
问题描述
我是堆栈溢出的新手,我想了解如何在 Gradle 上构建 c 二进制文件(不是可执行程序)。
现在,我无法构建 c 二进制文件(不是可执行程序)。有一个错误,但是我不知道如何更改 build.gradle 文件。
终端错误是...
> Executing task: gradle build <
:compileTestExecutableTestC
:linkTestExecutable
/opt/sparc/bin/.../sparc/lib/crt0.o: In function `zerobss':
/home/build/.../crt0.S:71: undefined reference to `main'
collect2: ld returned 1 exit status
:linkTestExecutable FAILED
output.txt 是...
See file:///home/ethan/gradle_test/vscode_example/build/tmp/linkTestExecutable/output.txt for all output for linkTestExecutable.
linking test failed.
/opt/...lib/crt0.o: In function `zerobss':
/home/build/.../crt0.S:71: undefined reference to `main'
collect2: ld returned 1 exit status
Finished linkTestExecutable, see full log file:///home/ethan/gradle_test/vscode_example/build/tmp/linkTestExecutable/output.txt.
The c binary does not include 'main' function, so I got this error in my opinion. The c binary runs on power-up and provides bootrom entry code.
build.gradle 下面是我用来构建 c 二进制文件的。
apply plugin: 'c'
model {
components{
test(NativeExecutableSpec){ // test should be src/<folder> name. and <folder> should include cpp for cpp compilation
targetPlatform("sparc_test") // should be platforms item(sparc_test)
targetBuildTypes("release")
binaries.all {
cCompiler.args '-c -Wall'
linker.args '--cref -N --verbose'
}
sources {
c {
source {
srcDir "./src/test/c/rom_eeprom"
include "*.c"
}
exportedHeaders {
srcDirs "./src/test/c/include"
}
}
}
}
}
platforms{
sparc_test{ // should not use '-'. sparc_test can by any word
architecture "sparc" // sparc can be any word
}
}
toolChains{
sparc_gcc(Gcc) { // sparc_gcc can by any thing. Gcc should be used
target("sparc_test") // define platform tool chain
{
path '/opt/bcc/sparc/bin' // tool chain path
cCompiler.executable 'sparc-gcc' // C compiler
cppCompiler.executable 'sparc-g++' // C++ compiler
assembler.executable 'sparc-gcc'
linker.executable 'sparc-gcc'
}
}
}
buildTypes{
release
}
}
c 二进制程序代码由 rom.S 和 eeprom.c 组成。
rom.S eeprom.c I do want the build.gradle to work like below
| | ==> compile
v v
rom.o eeprom.o
| |
--------------------
| ==> link
v
rom_eeprom.elf
| ==> objcopy
v
rom_eeprom.bin
如何成功构建这个 c 二进制程序?
任何建议都有帮助,谢谢
首先,感谢@thebusybee。
从@thebusybee 回答,我更改了编译器和链接器选项,但链接失败。
即使我添加了汇编插件和汇编代码,gradle 也无法编译汇编代码(因为没有生成汇编代码的目标文件)。而且 gradle 也不能像 make 那样链接目标文件。
这是我的 build.gradle
apply plugin: 'c'
apply plugin: 'assembler'
model {
components{
test(NativeExecutableSpec){ // test should be src/<folder> name. and <folder> should include cpp for cpp compilation
targetPlatform("sparc") // should be platforms item(sparc)
targetBuildTypes("release")
binaries.all {
cCompiler.args '-c -mv8 -Wall -fno-builtin -O2 -O'
linker.args '--cref -N --verbose -Map bl_low.map -T linkprom'
assembler.args '-xarch=v8'
}
sources {
c {
source {
srcDir "./src/test/c/bl_low"
include "*.c"
}
exportedHeaders {
srcDirs "./src/test/c/include"
}
}
}
sources {
asm {
source {
srcDir "./src/test/c/bl_low"
include "**/*.S"
}
}
}
}
}
platforms{
sparc{ // should not use '-'. sparc can by any word
architecture "sparc-v8" // sparc can be any word
}
}
toolChains{
sparc_gcc(Gcc) { // sparc_gcc can by any thing. Gcc should be used
target("sparc") // define sparc platform tool chain
{
path '/opt/bcc/sparc-elf-4.4.2/bin/' // tool chain path
cCompiler.executable 'sparc-elf-gcc' // C compiler
cppCompiler.executable 'sparc-elf-g++' // C++ compiler
assembler.executable 'sparc-elf-gcc' // work with sparc-elf-g++ rather than sparc-elf-as
linker.executable 'sparc-elf-gcc' // work with sparc-elf-g++ rather than sparc-elf-ld
}
}
}
buildTypes{
release
}
}
如何更改 build.gradle 以编译汇编代码和链接对象,然后生成 .elf 文件?
最后,我决定不使用 gradle 来构建 c,汇编项目。相反,我尝试使用 bazel ......谢谢@thebusybee,很抱歉没有完成这个问题。
无论如何,我的最后一个 build.gradle 是......
apply plugin: 'c'
apply plugin: 'assembler'
model {
components{
test(NativeExecutableSpec){ // test should be src/<folder> name. and <folder> should include cpp for cpp compilation
targetPlatform("leon3_ft") // should be platforms item(leon3_ft)
targetBuildTypes("release")
binaries.all {
cCompiler.args "-mv8", "-Wall", "-fno-builtin"
linker.args "-Xlinker", "--cref", "-Xlinker", "-N", "-Xlinker", "--verbose", "-Xlinker", "-Map", "-Xlinker", "bl_low.map", "-Xlinker", "-T", "-Xlinker", "linkprom"
assembler.args "-mv8", "-Wall", "-fno-builtin"
}
sources {
c {
source {
srcDir "./src/test/c/bl_low"
include "*.c"
}
exportedHeaders {
srcDirs "./src/test/c/include", "./src/test/c/bl_low"
}
}
asm {
source {
srcDir "./src/test/asm"
include "*.s"
}
}
}
}
}
platforms{
leon3_ft{ // should not use '-'. leon3_ft can by any word
architecture "sparc-v8" // sparc can be any word
}
}
toolChains{
sparc_gcc(Gcc) { // sparc_gcc can by any thing. Gcc should be used
target("leon3_ft") // define leon3_ft platform tool chain
{
path '/opt/bcc/sparc-elf-4.4.2/bin/' // tool chain path
cCompiler.executable 'sparc-elf-gcc' // C compiler
cppCompiler.executable 'sparc-elf-g++' // C++ compiler
assembler.executable 'sparc-elf-gcc' // Assembler. Use GCC
linker.executable 'sparc-elf-ld' // work with sparc-elf-g++ rather than sparc-elf-ld
}
}
}
buildTypes{
release
}
}
错误信息是...
> Executing task: gradle clean; gradle build <
BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
> Task :assembleTestExecutableTestAsm FAILED
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s: Assembler messages:
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:61: Error: Unknown opcode: `func_export(_romwindow_overflow)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:62: Error: Unknown opcode: `func_export(_romwindow_underflow)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:63: Error: Unknown opcode: `func_export(_romInit)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:64: Error: Unknown opcode: `func_export(romInit)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:65: Error: Unknown opcode: `data_export(_sdata)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:66: Error: Unknown opcode: `func_export(_cold)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:67: Error: Unknown opcode: `func_export(bl_low)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:74: Error: Unknown opcode: `func_import(romStart)'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:83: Error: Unknown opcode: `_wrs_text_seg_start'
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:108: Error: Unknown opcode: `bad_trap '
/home/ethan/gradle_test/vscode_example/src/test/asm/romInit.s:109: Error: Unknown opcode: `bad_trap '
...
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':assembleTestExecutableTestAsm'.
> A build operation failed.
Assembler failed while compiling romInit.s.
See the complete log at: file:///home/ethan/gradle_test/vscode_example/build/tmp/assembleTestExecutableTestAsm/output.txt
> Assembler failed while compiling romInit.s.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 2s
1 actionable task: 1 executed
<The terminal process terminated with exit code: 1
Terminal will be reused by tasks, press any key to close it.
解决方案
如果你有一个可用的 makefile,你可以将命令的所有选项转移到 Gradle 配置中。
您可以调用make来-n
打印命令而不执行它们。附加选项-B
假定必须构建所有目标。因此,查看构建二进制文件的所有命令的命令将是:
make -nB
我确信-nostartfiles
链接器命令上有一个选项。;-) 但是根据您的评论,我们现在知道命令行是:
sparc-elf-gcc -c -mv8 -Wall -fno-builtin -O2 -O ../include -c romInit.S
sparc-elf-gcc -c -mv8 -Wall -fno-builtin -O2 -O ../include -c eeprom.c
sparc-elf-gcc -c -mv8 -Wall -fno-builtin -O2 -O ../include -c bl_low.c
sparc-elf-ld --cref -N --verbose -Map bl_low.map -T linkprom -o bl_low.elf romInit.o memcpy.o memset.o strlen.o crc.o led.o eeprom.o bl_low.o
sparc-elf-objcopy -Obinary -v -S -g -x -X bl_low.elf bl_low.bin
从这些我们找到编译器和链接器标志:
编译器:(-c -mv8 -Wall -fno-builtin -O2 -O
最后一个-c
是重复的)
链接器:--cref -N --verbose -Map bl_low.map -T linkprom
最后一个构建步骤是将 ELF 文件转换为二进制文件。
因为您的链接描述文件linkprom
很可能不包含标准启动代码,所以不需要main()
函数。
推荐阅读
- c# - 为什么我的 sql 查询适用于 mssql 而不适用于 Visual Studio?
- android - Rxjava 大号 迭代然后跳过记录
- java - com.mysql.jdbc.CommunicationsException:通信链路故障(glassfish+mysql))
- mysql - 如何更新 mysql 文件中指定的用户?
- c# - 如何从具有某些条件的数据库特定列值生成字符串,并且每个列值分隔成逗号(,)
- c# - LINQ 比较对象变量和聚合结果
- java - 在我的项目中,使用拖放选项时,只有当我们同时使用 Robot 类时它才会执行,问题是屏幕应该打开!每次
- forth - J1 Forth CPU程序理解
- android - 如何遍历 Firebase 实时数据库?
- ruby-on-rails - 如何在控制器中拥有与视图相同的功能访问权限