0

I'm new in stack overflow and I want to get some idea how I can build c binary(NOT executable program) on Gradle.

Now, I could not build c binary(NOT executable program). There is an error, however I don't know how to change build.gradle file.

terminal error is ...

> 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 is...

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. 

The build.gradle is below I used to build c binary.

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
    }
}

The c binary program code consists of rom.S and 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

How can I build this c binary program successfully?

Any suggestion is helpful, Thanks

First, Thanks to @thebusybee.

From @thebusybee answer, I changed the compiler and linker options, but the linking failed.

linking failed error occurred. Linker is finding main function.

Even though I added assembler plugin and assembly code, gradle can not compile assembly code(because assembler code's object file is not generated). And also gradle can not link object files as make did.

Here is my 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
}

}

How can I change build.gradle to compile assembly code and link objects, then generate .elf file?

Finally, I decided not to use gradle on building for c, assembly project. Instead, I try to use bazel... Thank you @thebusybee and, sorry not to complete this problem.

Anyway, the last my build.gradle is...

    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
        }
    }

Error message is...

    > 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.
Ethan
  • 1
  • 1

1 Answers1

0

If you have a working makefile you can transfer all the options of the commands to the Gradle config.

You can call make with -n which prints the commands without executing them. The additional option -B pretends that all targets have to be build. So the command to see all commands to build your binary will be:

make -nB

I was sure that there is a -nostartfiles option on the linker command. ;-) But from your comment we now know that the command lines are:

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

And from these we find the compiler and linker flags:

Compiler: -c -mv8 -Wall -fno-builtin -O2 -O (the last -c is a duplicate)

Linker: --cref -N --verbose -Map bl_low.map -T linkprom

And there is a final build step to convert the ELF file into a binary file.

Because your linker script linkprom most probably does not include the standard startup code, there is no need for a main() function.

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • Thanks to your Answer. I checked my makefile, but there are not '-n' or '-nostartfiles' option. ' CFLAGS = -c -Wall -fno-builtin -O2 -I ./include LDFLAGS = --cref -N --verbose -Map $(name).map -T eepromlink ' I've read link script 'eepromlink', there was entry point function with 'ENTRY()' linker script command, so 'main' wasn't needed I think. Now, I am looking for a way to notify linker of entry point instead of 'main' function in gradle. – Ethan Sep 17 '19 at 04:10
  • Would you mind to post the output of the command I just wrote in my edited answer, please? – the busybee Sep 17 '19 at 05:55
  • I appriciate your help. Here is make -nB 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 – Ethan Sep 17 '19 at 06:28
  • As you said, linkprom does not have standard startup code. Anyway, I failed linking again... with the 'make -nB' compiler and linker flags. Please reference my post above – Ethan Sep 17 '19 at 07:32
  • I never used Gradle so I don't know. Is it possible to see the command lines Gradle calls? Looking at them should give us some clue. – the busybee Sep 17 '19 at 08:27
  • I see, thank you to reply. :) Gradle call is simple. I just call "gradle build" in command line and then, gradle builds project code with build.gradle file like cmake or make. I use cmake or make, but want to change them to another better one.One of I have searched is Gradle. – Ethan Sep 17 '19 at 08:33
  • OK, then, which commands lines are printed? BTW, do you know that you can [edit] your post? (The link here might be for my answer, not your question. Anyway, you should see an "edit" link below your question.) You can update it with our new findings and use the formating possibilities. – the busybee Sep 17 '19 at 09:08