how to generate hex files from c code and assembly code RISCV - c

I have some C Codes/ assembly codes and I want to compile it and generate hex files for RISCV pulppissimo. Can anyone help me with the steps for this.
Currently running the hello code
#include <stdio.h>
int main()
{
printf("Hello !\n");
return 0;
}
while compiling using riscv32 using the command riscv32-unknown-elf-gcc hello.c
getting error like this
RISCV/lib/gcc/riscv32-unknown-elf/7.1.1/../../../../riscv32-unknown-elf/bin/ld: cannot open linker script file riscv.ld: No such file or directory
collect2: error: ld returned 1 exit status

There is a perfect example in the git repository for the pulp platform boot code that can be used for answering your question. Since I do not have the toolchain you are using, I am using a toolchain I downloaded from the bootlin web site.
wget https://toolchains.bootlin.com/downloads/releases/toolchains/riscv32-ilp32d/tarballs/riscv32-ilp32d--glibc--bleeding-edge-2020.02-2.tar.bz2
mkdir -p /opt/bootlin
tar jxvf riscv32-ilp32d--glibc--bleeding-edge-2020.02-2.tar.bz2 -C /opt/bootlin
git clone git clone https://github.com/pulp-platform/boot-code
cd boot-code
edit the Makefile, and adjust the following lines in order to reflect the location for the toolchain you are using:
PULP_CC = riscv32-unknown-elf-gcc
PULP_LD = riscv32-unknown-elf-gcc
When using the bootlin toolchain, this would result in the two following lines:
PULP_CC = /opt/bootlin/riscv32-ilp32d--glibc--bleeding-edge-2020.02-2/bin/riscv32-buildroot-linux-gnu-gcc
PULP_LD = /opt/bootlin/riscv32-ilp32d--glibc--bleeding-edge-2020.02-2/bin/riscv32-buildroot-linux-gnu-gcc
The the same Makefile, replace the following line - the code does not compile as is I think:
CFLAGS += -Os -g -fno-jump-tables -I$(CURDIR)/include
by:
CFLAGS += -Os -g -fno-jump-tables -I$(CURDIR)/include -DMCHAN_CMD_ILE_BIT=21 -DMCHAN_CMD_ELE_BIT=20
You can now build the build/bootcode executable:
make
CC boot_code.c
In file included from /home/frant/mnt/git/boot-code/include/hal/chips/pulp/pulp.h:20,
from /home/frant/mnt/git/boot-code/include/hal/pulp.h:27,
from boot_code.c:18:
/home/frant/mnt/git/boot-code/include/hal/riscv/riscv_v5.h: In function ‘hal_cluster_id’:
/home/frant/mnt/git/boot-code/include/hal/riscv/riscv_v5.h:172:10: warning: implicit declaration of function ‘__builtin_pulp_ClusterId’ [-Wimplicit-function-declaration]
172 | return __builtin_pulp_ClusterId();
| ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/frant/mnt/git/boot-code/include/hal/chips/pulp/pulp.h:21,
from /home/frant/mnt/git/boot-code/include/hal/pulp.h:27,
from boot_code.c:18:
/home/frant/mnt/git/boot-code/include/hal/eu/eu_v3.h: In function ‘evt_read32’:
/home/frant/mnt/git/boot-code/include/hal/eu/eu_v3.h:43:11: warning: implicit declaration of function ‘__builtin_pulp_event_unit_read’ [-Wimplicit-function-declaration]
43 | value = __builtin_pulp_event_unit_read((int *)base, offset);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CC crt0.S
LD /home/frant/mnt/git/boot-code/build/bootcode
./stim_utils.py \
--binary=/home/frant/mnt/git/boot-code/build/bootcode \
--stim-bin=rom.bin \
--area=0x1a000000:0x01000000
Created stimuli generator
Added binary: /home/frant/mnt/git/boot-code/build/bootcode
Added target area: [0x1a000000 -> 0x1b000000]
Handling section (base: 0x1a000000, size: 0x57c)
Bypassing section (base:make
CC boot_code.c
In file included from /home/frant/mnt/git/boot-code/include/hal/chips/pulp/pulp.h:20,
from /home/frant/mnt/git/boot-code/include/hal/pulp.h:27,
from boot_code.c:18:
/home/frant/mnt/git/boot-code/include/hal/riscv/riscv_v5.h: In function ‘hal_cluster_id’:
/home/frant/mnt/git/boot-code/include/hal/riscv/riscv_v5.h:172:10: warning: implicit declaration of function ‘__builtin_pulp_ClusterId’ [-Wimplicit-function-declaration]
172 | return __builtin_pulp_ClusterId();
| ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/frant/mnt/git/boot-code/include/hal/chips/pulp/pulp.h:21,
from /home/frant/mnt/git/boot-code/include/hal/pulp.h:27,
from boot_code.c:18:
/home/frant/mnt/git/boot-code/include/hal/eu/eu_v3.h: In function ‘evt_read32’:
/home/frant/mnt/git/boot-code/include/hal/eu/eu_v3.h:43:11: warning: implicit declaration of function ‘__builtin_pulp_event_unit_read’ [-Wimplicit-function-declaration]
43 | value = __builtin_pulp_event_unit_read((int *)base, offset);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CC crt0.S
LD /home/frant/mnt/git/boot-code/build/bootcode
./stim_utils.py \
--binary=/home/frant/mnt/git/boot-code/build/bootcode \
--stim-bin=rom.bin \
--area=0x1a000000:0x01000000
Created stimuli generator
Added binary: /home/frant/mnt/git/boot-code/build/bootcode
Added target area: [0x1a000000 -> 0x1b000000]
Handling section (base: 0x1a000000, size: 0x57c)
Bypassing section (base: 0x1c000000, size: 0x1928)
objcopy --srec-len 1 --output-target=srec /home/frant/mnt/git/boot-code/build/bootcode /home/frant/mnt/git/boot-code/build/bootcode.s19
./s19toboot.py /home/frant/mnt/git/boot-code/build/bootcode.s19 boot_code.cde pulp 0x1c000000, size: 0x1928)
objcopy --srec-len 1 --output-target=srec /home/frant/mnt/git/boot-code/build/bootcode /home/frant/mnt/git/boot-code/build/bootcode.s19
./s19toboot.py /home/frant/mnt/git/boot-code/build/bootcode.s19 boot_code.cde pulp
And convert it into Intel Hex format:
/opt/bootlin/riscv32-ilp32d--glibc--bleeding-edge-2020.02-2/bin/riscv32-buildroot-linux-gnu-objcopy --output-target=ihex build/bootcode bootcode.ihex
cat bootcode.ihex
:020000041A00E0
:100000006F0080086F0040086F0000086F00C00795
:100010006F0080076F0040076F0000076F00C00689
../...
:081920000000000000000000BF
:040000051A000000DD
:00000001FF
Now that you have a working example for the pulp platform I think is your target, you should be able to adapt it to your needs.

Related

Should `linux-headers-$(uname -r)/include` be sufficient to compile against the Linux headers?

Say I have main.c:
#include <linux/list.h>
int main() {}
uname -r resolves to the 5.13.0-28-generic and I run Ubuntu 20.04 x86_64.
See what happens:
username#username-laptop:~$ gcc -o main -I/usr/src/linux-headers-$(uname -r)/include main.c
In file included from /usr/src/linux-headers-5.13.0-28-generic/include/linux/kernel.h:8,
from /usr/src/linux-headers-5.13.0-28-generic/include/linux/list.h:9,
from main.c:1:
/usr/src/linux-headers-5.13.0-28-generic/include/linux/linkage.h:8:10: fatal error: asm/linkage.h: No such file or directory
8 | #include <asm/linkage.h>
| ^~~~~~~~~~~~~~~
compilation terminated.
OK. Seems asm/linkage.h is platform-specific so I can't get if from the -generic headers. sudo find / -name linkage.h | grep x86 suggests the /usr/src/linux-hwe-5.13-headers-5.13.0-28/arch/x86/include include. So let's add that one too:
username#username-laptop:~$ gcc -o main -I/usr/src/linux-headers-$(uname -r)/include -I/usr/src/linux-hwe-5.13-headers-5.13.0-28/arch/x86/include main.c
In file included from /usr/src/linux-headers-5.13.0-28-generic/include/linux/kernel.h:11,
from /usr/src/linux-headers-5.13.0-28-generic/include/linux/list.h:9,
from main.c:1:
/usr/src/linux-headers-5.13.0-28-generic/include/linux/compiler.h:250:10: fatal error: asm/rwonce.h: No such file or directory
250 | #include <asm/rwonce.h>
| ^~~~~~~~~~~~~~
compilation terminated.
Have no idea what is wrong with my configuration. Any ideas?

Error no member named 'reqevents'; did you mean 'events' when building Redis on AIX

I'm upgrading from Redis 6.0.13 to 6.2.5 on AIX.
On 6.2.5, the build fails with this error:
MAKE hdr_histogram
cd hdr_histogram && make
make[3]: Entering directory '/home/jenkins/redis/deps/hdr_histogram'
/opt/atc-2.0/opt/gcc/bin/gcc -Wall -Os -g -DLUA_USE_POSIX -DLUA_USE_DLOPEN -include stdint-gcc.h -c hdr_histogram.c
make[3]: Leaving directory '/home/jenkins/redis/deps/hdr_histogram'
make[2]: Leaving directory '/home/jenkins/redis/deps'
CC adlist.o
CC quicklist.o
CC ae.o
In file included from ae.c:60:
ae_select.c: In function 'aeApiResize':
ae_select.c:52:37: warning: unused parameter 'eventLoop' [-Wunused-parameter]
52 | static int aeApiResize(aeEventLoop *eventLoop, int setsize) {
| ~~~~~~~~~~~~~^~~~~~~~~
In file included from /usr/include/poll.h:30,
from ae.c:41:
ae_select.c: In function 'aeApiPoll':
ae_select.c:89:43: error: 'aeEventLoop' has no member named 'reqevents'; did you mean 'events'?
89 | aeFileEvent *fe = &eventLoop->events[j];
| ^~~~~~
ae.c: In function 'aeCreateEventLoop':
ae.c:73:16: error: 'aeEventLoop' has no member named 'reqevents'; did you mean 'events'?
73 | eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);
| ^~~~~~
...
I checked the eventLoop struct, and it does indeed contain events, but I see the build failing because it's trying to access reqevents. I can't find reqevents anywhere in the project (with grep -R 'reqevents' .)
This error only happens on AIX 7.1 - Linux and macOS both work fine.
Do you know why req would be prepended to the struct members on AIX, and how I might solve the error?

C header found but function is still undefined

I am on Debian 10 and I want to develop an C application for PostgreSQL. This is why I installed a packages postgresql and libpq-dev. Later clearly installed header files inside the system folders:
┌───┐
│ $ │ ziga > ziga--workstation > 001--hello_world
└─┬─┘
└─> find /usr/include/ | grep libpq
/usr/include/postgresql/libpq-fe.h
/usr/include/postgresql/libpq
/usr/include/postgresql/libpq/libpq-fs.h
/usr/include/postgresql/libpq-events.h
/usr/include/postgresql/internal/libpq
/usr/include/postgresql/internal/libpq/pqcomm.h
/usr/include/postgresql/internal/libpq-int.h
But when I compile this simple C program:
#include <stdio.h>
#include <postgresql/libpq-fe.h>
int main(int argc, char * argv[]){
int v = PQlibVersion();
printf("Version of libpq: %d\n", v);
return 0;
}
compiler says:
gcc -std=c17 -Wall -Wpedantic -g -gdwarf-2 -o main.elf main.c
/usr/bin/ld: /tmp/ccVzig6T.o: in function `main':
/home/ziga/Dropbox/workspace/racunalnistvo/projects--pistam/2021-03-03--postgressql_c/001--hello_world/main.c:6: undefined reference to `PQlibVersion'
collect2: error: ld returned 1 exit status
make: *** [makefile:59: main.elf] Error 1
I don't understand. Header files are inside /usr/include where they should be found...
Is library not being found or what? It is also installed...
┌───┐
│ $ │ ziga > ziga--workstation > 001--hello_world
└─┬─┘
└─> find /usr/lib | grep libpq
/usr/lib/x86_64-linux-gnu/libpq.a
/usr/lib/x86_64-linux-gnu/libpq.so
/usr/lib/x86_64-linux-gnu/libpq.so.5
/usr/lib/x86_64-linux-gnu/pkgconfig/libpq.pc
/usr/lib/x86_64-linux-gnu/libpq.so.5.11
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/pqsignal.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/be-secure-openssl.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/auth.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/pqcomm.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/be-fsstubs.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/pqformat.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/ifaddr.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/be-secure.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/pqmq.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/crypt.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/be-secure-common.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/hba.bc
/usr/lib/postgresql/11/lib/bitcode/postgres/libpq/auth-scram.bc
/usr/lib/postgresql/11/lib/libpqwalreceiver.so
Can anyone tell me how to best solve this?
As the log says, The linker is unable to find any reference to PQlibVersion. Since the linker is running, it clearly is not a problem of compiling but linking.
/usr/bin/ld: /tmp/ccVzig6T.o: in function `main':
/home/ziga/Dropbox/workspace/racunalnistvo/projects--pistam/2021-03-03--postgressql_c/001--hello_world/main.c:6: undefined reference to `PQlibVersion'
collect2: error: ld returned 1 exit status
I think you should add linker options to link against the postgress library. Add -lpq option to you compiler arguments. For a more complete explanation, please read Building libpq Programs.

How to build a binary for C source code in Gradle, but not executable?

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

Reading data from matlab files into C

I'm trying to learn how to use the C API to reading Matlab .mat files, but it's not working as I expected:
I'd like to just open a very simple .mat file called test.mat, read a value from the file and store it in a C variable. I've created test.mat in Matlab using the following commands:
> value = 3;
> save ("test.mat", "value")
Below is my C code, which doesn't even compile - the compiler doesn't seem to find the header files. See below the code for compiler output. What am I doing wrong here?
Code:
#include <stdlib.h>
#include <stdio.h>
#include <mat.h>
#include <matrix.h>
int main(int argc, char *argv[]) {
double value;
MATFile *datafile;
datafile = matOpen("test.mat", "r");
mxArray *mxValue;
mxValue = matGetVariable(datafile, "value");
matClose(datafile);
value = *mxGetPr(mxArray);
mxFree(mxArray);
printf("The value fetched from the .mat file was: %f", value);
return 0;
}
Compiler output:
$ make animate_shot
cc -I/usr/local/MATLAB/R2011a/extern/include/ animate_shot.c -o animate_shot
/tmp/cczrh1vT.o: In function `main':
animate_shot.c:(.text+0x1a): undefined reference to `matOpen'
animate_shot.c:(.text+0x2f): undefined reference to `matGetVariable'
animate_shot.c:(.text+0x3f): undefined reference to `matClose'
animate_shot.c:(.text+0x4b): undefined reference to `mxGetPr'
animate_shot.c:(.text+0x5e): undefined reference to `mxFree'
collect2: ld returned 1 exit status
make: *** [animate_shot] Error 1
(the -I flag is specified with the line CPPFLAGS=-I/usr/local/MATLAB/R2011a/extern/include/ in my makefile, and I've verified that the directory exists and contains the header files mat.h and matrix.h).
UPDATE:
I've found that the libraries I need to link in are libmat.so and libmx.so (according to this MathWorks help article), residing in /usr/local/MATLAB/R2011a/bin/glnxa64/ on my system. I've therefore updated my makefile to this:
CPPFLAGS =-I/usr/local/MATLAB/R2011a/extern/include/
LDFLAGS = -L/usr/local/MATLAB/R2011a/bin/glnxa64 -l mat -l mx
Now, running make gives the following command:
cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/bin/glnxa64 -l mat -l mx animate_shot.c -o animate_shot
However, I still get the same errors. Any ideas?
This is a linker failure, not a compiler failure (and is unrelated to -I compiler option). You need to specify the directory in which the matlab .so files are located using -L flag and add a -l<matlab-lib-name> option to end of the compiler command that specifies the name of the matlab library.
For example:
cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/lib animate_shot.c -o animate_shot -lmatlab
(I don't know the exact directory into the which .so are located or the name of the matlab library)
Based on the comment providing further information:
cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/bin/glnxa64 animate_shot.c -o animate_shot -lmat -lmx

Resources