-1

A complete newbie here. I am learning to read the codes on suckless.org. They are written in C, and are most quite short, so I think it's a good start.

The problem is I know too little to start with. Wandering around on the site, I found that the suckless community has their own coreutils, which are also very short. echo.c on this page is one of the shortests. I include its header here:

/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <string.h>
#include "util.h"

I'd like to compile it and see how this version of echo works, and come back to understand the code. The goal is to repeat this process until I'm comfortable enough to read the source codes of their their larger programs like sent, dmenu, dwm.

In the code, the header #include "util.h" suggests me to put util.h, which is another file in the link above, together with echo.c. I also include arg.h and compat.h because the header of util.h says

#include <sys/types.h>

#include <regex.h>
#include <stddef.h>
#include <stdio.h>

#include "arg.h"
#include "compat.h"

I further checked arg.h and compat.h. Neither of them includes customized header files, so I think I'm good to go. Now the folder tree looks like

$ tree
.
├── arg.h
├── compat.h
├── echo.c
└── util.h

and I run $ gcc echo.c -o echo.o. However, I got an error

/usr/bin/ld: /tmp/cc2VjXNO.o: in function `main':
echo.c:(.text+0x20): undefined reference to `argv0'
/usr/bin/ld: echo.c:(.text+0x27): undefined reference to `argv0'
/usr/bin/ld: echo.c:(.text+0x8d): undefined reference to `putword'
/usr/bin/ld: echo.c:(.text+0xc8): undefined reference to `fshut'
collect2: error: ld returned 1 exit status

Apparently, these undefined arguments are in those header files. Searching around on the net, I further tried

$ gcc -c . echo.c -o echo.o
gcc: warning: .: linker input file unused because linking not done

It spits a warning, but anyway an echo.o is delivered. I chmod it to executable, and run it by $ ./echo.o, but my shell complains

zsh: exec format error: ./echo.o

I spent another hour trying to solve this.. by try and error, but in vain. Would you please point out what's going on? And what should I do?

(Any other suggestions will also be very appreciated.)

Student
  • 400
  • 3
  • 10
  • https://en.wikipedia.org/wiki/Compiler – Hannu Mar 17 '20 at 18:09
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – KamilCuk Mar 17 '20 at 20:05
  • 1
    Remove the `-c .`. `I got an error` The symbols are not defined. So include them in your compilation. You usually can't take one file from a project and compile it separately from all the else without including all the dependencies. – KamilCuk Mar 17 '20 at 20:07
  • The project probably comes with a Makefile or similar. You should use that instead of trying to compile individual files manually. – that other guy Mar 17 '20 at 20:16
  • @thatotherguy Yes it does include a Makefile! I will try to compile with it. Maybe my problem lies in the fact that I don't fully understand what `gcc` does on the headers `#include `, `#include "XYZ.h"` and the difference between these. – Student Mar 17 '20 at 20:33
  • 1
    The header files includes constant and function declarations that are needed by whatever it is you include in your source file that needs them. For example, if you include `puts ("my dog has fleas.");` in your code, then you need to `#include ` for the standard I/O function declaration for `puts()`. If you get used to checking the manual page for each function you use, e.g. [man 3 puts](http://man7.org/linux/man-pages/man3/puts.3.html), it will tell you under `"SYNOPSIS"` exactly which header is needed. No magic. – David C. Rankin Mar 17 '20 at 21:28
  • 2
    When compiling with `gcc` always enable warnings by including `-Wall -Wextra -pedantic` and do not accept code until it compiles without warning (also suggest including `-Wshadow` to catch any shadowed variables). Your basic compile (not including the warnings options) is `gcc -o nameyouwant yoursource.c [other.c ...]` to compile `yoursource.c` into the executable named `nameyouwant`. (you can specify as many `other.c` files as you need) Add `-O0` to `-O3` for no to almost full *Optimization*. Add `-std=c11` to specify the `C11 standard`. That's it in a nutshell. – David C. Rankin Mar 17 '20 at 21:34
  • @DavidC.Rankin That's good tips for newbies. Thank you. – Student Mar 18 '20 at 16:59

1 Answers1

2

You try to compile a program with library that you don't have. The header you're using needs a dynamic or static library (either .a or .o on linux). That's why you get linker input file unused because linking not done.

zsh: exec format error: ./echo.o if you use .o extension with -o argument, you're either making or linking a .o object file (static lib). With gcc -c . echo.c -o echo.o, you're creating a static library (called object) that you won't be able to execute.

By the way, I'd stay away for now from this kind of code, it's very not friendly user for a learner.

Asperio
  • 46
  • 4
  • Thanks for your answer! I figured that it's inevitable to learn what the makefile says. And also thanks for your advice. I'm thinking of learning to swim by diving into deep ocean, hoping that will make me learn faster. It work best if I have experienced friends around, but for this case.. I better take your advice. – Student Apr 14 '20 at 14:56