How to make a 'makefile' in c - linux

I can't understand how I can produce a makefile for C code
I have the following .c file which normally I execute in the following manner:
gcc server.c -o server.out -lpthread
Once compiled, I run the .out file like this:
./server.out 4000
EDITED
I only need the make files to compile the program rather than running it too..

If naming your executable file server will do for you, then just
LDLIBS=-lpthread
all: server
in a file called Makefile will do. The you can just type
make
to build it.
Ortherwise your Makefile should contain:
server.out: server.c
gcc server.c -o server.out -lpthread
Except that it is a tabulation, not spaces before the text “gcc”.

To start , you can create a project in eclipse and it would create a makefile for you. And then you can start going into the details about what all is added and this can trim out things you understand are not necessary.

https://github.com/ChrisLundquist/OpenCL-Compiler/blob/master/Makefile
Is an example of a simple make file.

Related

CMakeList file to generate LLVM bitcode file from C source file

I am trying to generate LLVM bytecode file from a C source file (hello.c) using CMake. And below is my CMakeLists file.
###### CMakelists.txt ############
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_C_FLAGS "-emit-llvm")
project (hello)
add_executable(hello hello.c)
I am new to CMake and not sure if this is the right way. I could not find any rules to make *.bc in the generated MakeFile
. Please correct me here. I also tried "-save-temps"
Considering this for a single .c file. It would be really helpful if you could give me some hints on generating the same for a complete C project.
I think what you ultimately want is to be able to build a C-program
project with CMake and clang in which source files are compiled to LLVM bitcode
and the executable is linked from the bitcode files.
With CMake, asking clang to to link bitcode files means asking it to link in LTO mode,
with the -flto linkage option.
And you can get clang to compile to LLVM bitcode with the -flto compilation
option, or with the -emit-llvm option.
For illustration here is a Hello World project comprising two source files and one header:
$ ls -R
.:
CMakeLists.txt hello.c hello.h main.c
Here is the:
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project (hello)
set(CMAKE_C_COMPILER clang)
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-flto")
add_executable(hello main.c hello.c)
target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -flto)
#target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -emit-llvm)
It will work equally well with:
#target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -flto)
target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -emit-llvm)
Make a build directory for CMake and go there:
$ mkdir build
$ cd build
Generate the build system:
$ cmake ..
Build:
$ make
Scanning dependencies of target hello
[ 33%] Building C object CMakeFiles/hello.dir/main.c.o
[ 66%] Building C object CMakeFiles/hello.dir/hello.c.o
[100%] Linking C executable hello
[100%] Built target hello
You will not find any *.bc targets in the Makefiles, nor any *.bc files
generated:
$ egrep -r '.*\.bc'; echo Done
Done
$ find -name '*.bc'; echo Done
Done
because the compilation option -flto or -emit-llvm results in an output
file:
CMakeFiles/hello.dir/main.c.o
CMakeFiles/hello.dir/hello.c.o
that adheres to the usual CMake naming convention but is in fact not an object file
but an LLVM bitcode file, as you see:
$ file $(find -name '*.o')
./CMakeFiles/hello.dir/hello.c.o: LLVM IR bitcode
./CMakeFiles/hello.dir/main.c.o: LLVM IR bitcode
The program does the usual thing:
$ ./hello
Hello World!
Later
When I try " make hello.o " it should generate the object file right?
the cmd executes successfully but, could not find the generated object file. Am I doing it right?
You are doing it in one way that is right, though not the only way that is right, but
your expectations are wrong. Look again at:
$ file $(find -name '*.o')
./CMakeFiles/hello.dir/hello.c.o: LLVM IR bitcode
./CMakeFiles/hello.dir/main.c.o: LLVM IR bitcode
You can see there that the .o files that are made from hello.c and main.c
by the CMake-generated makefile are not called hello.o and main.o but hello.c.o
and main.c.o. CMake prefers a compiled filename to preserve the extension of the
source file, and append .o. That is a fairly common practice. So if you wanted
to use the makefile to compile hello.c, the most obviously right way would be
make hello.c.o.
Let's see what actually happens. In my CMake build directory:
$ make VERBOSE=1 hello.c.o
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/hello.c.o
make[1]: Entering directory '/home/imk/develop/so/scrap/build'
make[1]: 'CMakeFiles/hello.dir/hello.c.o' is up to date.
make[1]: Leaving directory '/home/imk/develop/so/scrap/build'
There was nothing to be done, because my hello.c.o was up to date. So I'll
delete it and repeat:
$ rm CMakeFiles/hello.dir/hello.c.o
$ make VERBOSE=1 hello.c.o
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/hello.c.o
make[1]: Entering directory '/home/imk/develop/so/scrap/build'
Building C object CMakeFiles/hello.dir/hello.c.o
clang -flto -o CMakeFiles/hello.dir/hello.c.o -c /home/imk/develop/so/scrap/hello.c
make[1]: Leaving directory '/home/imk/develop/so/scrap/build'
Now it has been recompiled.
However, because many people - like you - would expect hello.o to be compiled
from hello.c, CMake helpfully defines hello.o as a .PHONY target
that depends on hello.c.o:
$ egrep -A3 'hello.o.*:.*hello.c.o' Makefile
hello.o: hello.c.o
.PHONY : hello.o
So in fact I can do:
$ rm CMakeFiles/hello.dir/hello.c.o
$ make VERBOSE=1 hello.o
make -f CMakeFiles/hello.dir/build.make CMakeFiles/hello.dir/hello.c.o
make[1]: Entering directory '/home/imk/develop/so/scrap/build'
Building C object CMakeFiles/hello.dir/hello.c.o
clang -flto -o CMakeFiles/hello.dir/hello.c.o -c /home/imk/develop/so/scrap/hello.c
make[1]: Leaving directory '/home/imk/develop/so/scrap/build'
make hello.o is another way of making hello.c.o
The problem is that using the -emit-llvm flag does not produce a final binary and stops the configuration tests that CMake performs once that flag is used in them.
Apart from what's already been written about using the LTO infrastructure, you have 3 (or 2 and a half) other alternatives.
One is to use Whole-Program LLVM and use the commands provided to extract the relevant bitcode parts.
The other is to go the manual way of setting up custom targets (see add_custom_target and add_custom_command) on your CMake binary targets, that will get triggered on changes and will reproduce the desired outcome as if executed manually on the command line each time.
Now, on this last point, I had a similar need so I created a CMake project that provides that functionality (llvm-ir-cmake-utils), but allows you to hook up those custom targets on existing ones as you please and see fit without having to rewrite everything from scratch each time.
There are examples in the repo, but in short, it allows you to attach custom targets on already existing CMake targets, e.g.
[...]
add_executable(qux ${SOURCES})
[...]
# this will create a bitcode generating target
# and allow it to depend on the initial target in order to detect source code changes
llvmir_attach_bc_target(qux_bc qux)
add_dependencies(qux_bc qux)
[...]
After make,
$>file CMakeFiles/hello.dir/hello.c.o
CMakeFiles/hello.dir/hello.c.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
if
set(CMAKE_C_FLAGS "-emit-llvm")
written before
project (hello)
In order to obtain IR bitcode, I wrote:
###### CMakelists.txt ############
cmake_minimum_required(VERSION 2.8.9)
project (hello)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_C_FLAGS "-flto")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-flto")
add_executable(hello hello.c)
target_compile_options(hello PUBLIC ${CMAKE_C_FLAGS} -flto)
I worked several hours in order to have a Makefile working to compile from IR
code to native using lld, then with cmake it was much more faster.
Then reading at cmake generated Makefile, I was able to correct my Makefile:
clang -flto -flto <hello.c.o> ..
this worked but I do not know why -flto is written twice.
Thanl you very much for this post, showing clang as the centralized front end to various llvm provided commands.

Linux programming: Compile code with dependencies

I am new to linux programming and learning it from The Linux Programming Interface by Michael Kerrisk.
I have to compile my first program that has dependencies.
Directory structure:
--linux-programs
|--seek_io.c
|--lib
|--tlpi_hdr.h
|--error_functions.h
|--error_functions.c
|--get_num.h
|--ename.c.inc
I want to compile seek_io.c program with dependencies in the lib directory, so that I can see how the program works.
I tried a few things, absolutely clueless on how they work following this stackoverflow answer. I get all sorts of errors as I am an absolute beginner to Linux programming, not to programming, linux OS and C.
Trials:
gcc -I ./lib/ -c ./lib/error_functions.c and then gcc -o seek_io.c ./error_function.o gives error:
/usr/lib/gcc/x86_64-linux-gnu/crt1.o: In function _start:
(.text+0x20): undefined reference to main
collect2: error: ld returned 1 exit status
After this run, on ls I find that my seek_io.c is not listed.
Basically the author of the book says for tlpi_hdr.h file:
This header file includes various other header files used by many of the example programs, defines a Boolean data type, and defines macros for calculating the minimum and maximum of two numeric values. Using this header file allows us to make the example programs a bit shorter.
Link to codes for files mentioned above:
tlpi_hdr.h
error_functions.h
error_functions.c
get_num.h
get_num.c
seek_io.c
The problem is with your second gcc command, where you're using the -o file to specify the output file where to store the resulting executable file, but passing it the name of the C source file seek_io.c instead...
gcc -o seek_io.c ./error_function.o
This means link file error_function.o and store the executable in seek_io.c. This fails because there is no main function, which is needed for a standalone executable, so your C source file is not overwritten by the failing link command.
You can fix this easily by passing the -o option a proper output file name, which in the case (of this link command) should be the name of the executable that you want to create, such as seek_io:
gcc -o seek_io seek_io.c ./error_function.o
(But this will fail without a -I ./lib/, since seek_io.c includes tlpi_hdr.h which is in that directory. If you add it to that command, it should work.)
You can also decide to split the compile and link steps in two separate steps (the command above will both compile seek_io.c into an object file and then link the two object files into an executable) with:
$ gcc -I ./lib/ -c ./lib/error_functions.c
$ gcc -I ./lib/ -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o
One final nitpick is that for the -I flag to specify the directories where to search for the include files, the more common usage has no space between the flag itself and the directory name, so you'll most commonly see -I./lib or even -Ilib.
$ gcc -Ilib -c ./lib/error_functions.c
$ gcc -Ilib -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o

Simple makefile for C/C++ targets used with arm-linux-gcc

I would like to cross-compile a simple program for ARM architecture using the arm-linux-gcc suite of compilers [arm-linux-gcc (Buildroot 2011.08) 4.3.6]. I've attempted to use a simple makefile for compiling C code, and another simple makefile for compiling C++ code. For example, my makefile for C code is reproduced below, but it does not create an ELF binary for running on my embedded system. The host system is x64 GNU Linux.
Here is the listing of my very simple makefile for a C program:
CC=arm-linux-gcc
CFLAGS=-Wall
main: test.o
clean:
rm -f test test.o
The makefile reproduced above only creates an object file with extension .o, and does not create an ELF binary.
I've Googled for a good solution, but I can't seem to find one webpage showing example cross-compile ARM makefiles for both C and C++ programs. Perhaps an answer to this post could show such examples.
Have a look at the GNU make manual (info make), Section 10.2. It has a catalogue of the implicit rules, i.e. the rules where you don't need to explicitly state the commands. Like #GregHewgill thought, the "Linking a single object file" implicit rule builds N from N.o, but the name must match. Therefore, you can either name your executable like your object file, in which case
test:
or (more standard because it defines the all target)
all : test
completely suffice. You can also write out the rule explicitly, like Greg Hewgill also described. In this case, the standard rule is:
$(CC) $(LDFLAGS) N.o $(LOADLIBES) $(LDLIBS)
Include the LDFLAGS and LDLIBS in your Makefile, it makes life easier for users.
(sic: I think LOADLIBES is really LOADLIBS, and the author missed the -o).
Overall, I'd recommend autoconf and automake instead of hand-rolling makefiles. Gives you a bunch of Makefile features for very little work.
I tried your Makefile and changed the following:
test: test.o
It worked after this changed and created a binary called test. It seems that there is some implicit rule that knows how to link whatever if one of its dependencies is whatever.o.
Another way is to list the rule explicitly:
main: test.o
$(CC) -o $# $$
This uses the special macros $# (which means target) and $$ (which means dependencies).

Symbols from convenience library not getting exported in executable

I have a program, myprogram, which is linked with a static convenience library, call it libconvenience.a, which contains a function, func(). The function func() isn't called anywhere in myprogram; it needs to be able to be called from a plugin library, plugin.so.
The symbol func() is not getting exported dynamically in myprogram. If I run
nm myprogram | grep func
I get nothing. However, it isn't missing from libconvenience.a:
nm libconvenience/libconvenience.a | grep func
00000000 T func
I am using automake, but if I do the last linking step by hand on the command line instead, it doesn't work either:
gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/libconvenience.a `pkg-config --libs somelibraries`
However, if I link the program like this, skipping the use of a convenience library and linking the object files that would have gone into libconvenience.a directly, func() shows up in myprogram's symbols as it should:
gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/*.o `pkg-config --libs somelibraries`
If I add a dummy call to func() somewhere in myprogram, then func() also shows up in myprogram's symbols. But I thought that --export-dynamic was supposed to export all symbols regardless of whether they were used in the program or not!
I am using automake 1.11.1 and gcc 4.5.1 on Fedora 14. I am also using Libtool 2.2.10 to build plugin.so (but not the convenience library.)
I didn't forget to put -Wl,--export-dynamic in myprogram_LDFLAGS, nor did I forget to put the source that contains func() in libconvenience_a_SOURCES (some Googling suggests that these are common causes of this problem.)
Can somebody help me understand what is going on here?
I managed to solve it. It was this note from John Calcote's excellent Autotools book that pointed me in the right direction:
Linkers add to the binary product every object file specified explicitly on the command line, but they only extract from archives those object files that are actually referenced in the code being linked.
To counteract this behavior, one can use the --whole-archive flag to libtool. However, this causes all the symbols from all the system libraries to be pulled in also, causing lots of double symbol definition errors. So --whole-archive needs to be right before libconvenience.a on the linker command line, and it needs to be followed by --no-whole-archive so that the other libraries aren't treated that way. This is a bit difficult since automake and libtool don't really guarantee keeping your flags in the same order on the command line, but this line in Makefile.am did the trick:
myprogram_LDFLAGS = -Wl,--export-dynamic \
-Wl,--whole-archive,libconvenience/libconvenience.a,--no-whole-archive
If you need func to be in plugin.so, you should try and locate it there if possible. Convenience libraries are meant to be just that -- a convenience to link to an executable or lib as an intermediate step.

gcc compiled binaries give "cannot execute binary file"

I compile this program:
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
With this command:
gcc -c "hello.c" -o hello
And when I try to execute hello, I get
bash: ./hello: Permission denied
Because the permissions are
-rw-r--r-- 1 nathan nathan 856 2010-09-17 23:49 hello
For some reason??
But whatever... after changing the permissions and trying to execute again, I get
bash: ./hello: cannot execute binary file
I'm using gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
What am I doing wrong here? It's gotta be obvious... it's just too late for me to keep using my tired eyes to try and figure out this simple problem....
P.S. I do (sometimes) work on programs more sophisticated than Hello World, but gcc is doing this across the board...
Take the -c out. That's for making object files, not executables.
The -c flag tells it not to link, so you have an object file, not a binary executable.
In fact, if you ran this without the -o flag, you would find that the default output file would be hello.o.
For reference (and giggles), the man entry on the -c flag:
-c Compile or assemble the source files, but do not link. The linking stage simply is not done.
The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix .c, .i, .s,
etc., with .o.
Unrecognized input files, not requiring compilation or assembly, are ignored.
Compile with: gcc hello.c -o hello

Resources