Code Structure

Header file (.h)

It may contain:

  • Function prototypes

  • Macro definitions (shared among different source files)

  • Type definitions (shared among different source files)

Header file protection

If a source file includes the same header multiple times, compilation errors may occur (for example, if they contain a type definition)

To avoid this type of errors, #ifndef directive can be used in .h file.

#ifndef BOOLEAN_H
#define BOOLEAN_H
#define TRUE 1
#define FALSE 0
typedef int Bool
#endif

Code structure on several files

The program is divided into multiple groups of source files:

  • Utility source group A set of source files that contain the implementation of utility functions

  • Header file for utility functions A header file that defines the prototypes of the utility functions

  • Source group for main execution flow management These usually handle the program's input and output, and process them using the utility functions

Example:

  • vectorstats.c it contains functions for performing operations on integer vectors

  • vectorstats.h Contains the prototypes for declaring these functions

  • use_vectorstats.c

    • It reads a vector from the keyboard

    • It calls the functions provided in the vectorstats.c file

    • It includes the vectorstats.h header file

Generation of a unique file executable

  • It equires all source files to be available

  • There are no dependencies at runtime

  • COMPILATION PHASE All source files must be compiled For each source file, a corresponding object file is generated

  • LINKING The linker combines the generated object files to produce a single executable

First method

Direct compilation (creation of the executable file within a unique command)

gcc -o use_vectorstats  use_vectorstats.c  vectorstats.c

Second method

Step-by-step compilation

  • Generate the object files from the utility source files

  • Use the object files to create a single executable

gcc -c -o vectorstats.o  vectorstats.c
gcc -o use_vectorstats  use_vectorstats.c  vectorstats.o

Library

Collection of functions used to develop applications

  • Code and data can be shared between different applications

  • Reuse of code that has already been written (and compiled)

Static library

In static linking, the linker links the functions referenced in the application, and they become part of the generated output (executable or library).

OS
Extension
Name

Windows

.lib

Library

UNIX

.a

Archive

Advantages

  • Speed Linking with external libraries does not need to be performed each time, as the library is part of the executable itself.

    It is used on systems that always perform the same function.

How to use it

To use a static library in C, follow these steps:

  1. Create the static library: First, you need to compile your source code into an object file and then create the static library from those object files.

    gcc -c mylib.c -o mylib.o
    ar rcs libmylib.a mylib.o

    where:

    • -c compiles the source code (mylib.c) into an object file (mylib.o).

    • ar rcs creates the static library libmylib.a from the object file (mylib.o).

      • r inserts the object file into the archive (library).

      • c creates the library if it doesn’t exist.

      • s creates an index to optimize linking.

    • libmylib.a is the static library.

  2. Link the static library when compiling your C program: Now, when compiling your program, you need to tell the compiler where to find the static library and link it to your program.

    gcc -o myprogram myprogram.c -L/path/to/library -lmylib

    where:

    • -L/path/to/library specifies the path to the directory where libmylib.a is located (if it's not in a standard library directory).

    • -lmylib tells the linker to link the program with libmylib.a (without the lib prefix and .a suffix).

  3. Use the functions from the static library: In your C program, you include the header file for the static library and use its functions. For example, if mylib.h contains a function int add(int, int), you would use it like this:

    #include <stdio.h>
    #include "mylib.h"
    
    int main() {
        int result = add(2, 3);
        printf("Result: %d\n", result);
        return 0;
    }
  4. Compile and run the program: After linking the static library, you can compile and run your program like this:

    gcc -o myprogram myprogram.c -L/path/to/library -lmylib
    ./myprogram

    Since the static library is linked at compile-time, all the necessary code from the library is included directly in the executable, so there are no runtime dependencies for the static library.

Dynamic library

In dynamic linking, the components of a library are loaded into the program at runtime rather than being linked by the linker.

  • They remain separate from the program's code

  • The linker records in the executable:

    • the list of functions to be dynamically linked

    • the name of the library that contains them

    • the ordinal number of the function within the library

OS
Extension
Name

Windows

.dll

Dynamic Link Library

UNIX

.so

Shared object

Advantages

  • Sharing between different applications, resulting in savings of space and time.

  • Updating Libraries can be updated without recompiling the application, as long as the interface of the exported functions (prototypes) and classes (declarations) has not been modified.

  • Loading Functions are loaded on demand, only when needed.

How to use it

To use a dynamic library in C, follow these steps:

  1. Create the dynamic library: First, you need to compile your source code into a shared library. Here's an example:

    gcc -c -fPIC -o mylib.o mylib.c
    gcc -shared -o libmylib.so mylib.o

    where:

    • -c compiles the source code into an object file.

    • -fPIC generates position-independent code, necessary for shared libraries.

    • -shared tells the compiler to generate a dynamic/shared library.

    • libmylib.so is the resulting dynamic library.

  2. Link the dynamic library when compiling your C program: When compiling your C program, you need to link it with the shared library. Use the -L flag to specify the path to the library (if it's not in the default system paths) and the -l flag to tell the compiler which library to link.

    gcc -o myprogram myprogram.c -L/path/to/library -lmylib

    where:

    • -L/path/to/library is the path to the directory where the library is stored.

    • -lmylib links the library libmylib.so (without the lib prefix and .so suffix).

  3. Set the LD_LIBRARY_PATH (if needed): If the library is in a non-standard location, you may need to add the library path to the LD_LIBRARY_PATH environment variable so the program can find it at runtime.

    export LD_LIBRARY_PATH=/path/to/library:$LD_LIBRARY_PATH
  4. Use the functions from the dynamic library: In your C program, include the header file for your dynamic library, and use its functions just like any other function. For example, if mylib.h contains a function int add(int, int), you would use it like this:

    #include <stdio.h>
    #include "mylib.h"
    
    int main() {
        int result = add(2, 3);
        printf("Result: %d\n", result);
        return 0;
    }
  5. Run the program: When you run the program, the dynamic linker will load the library at runtime:

    ./myprogram

    If everything is set up correctly, the program will find libmylib.so and use the functions from it.

Errors from the linker

  • Typing errors If the name of a variable or function is not typed correctly, the linker will report it as missing.

  • Missing files If the linker cannot find the functions from a file named fileName.c, it might not know anything about that file (for example, the target for fileName.o might not have been specified in the makefile).

  • Missing libraries The linker might be unable to locate all the function libraries used within the program.

<math.h> Including <math.h> alone is not sufficient in many UNIX systems, and linking requires the -lm option so the linker can search for a system file containing the compiled <math.h> functions.

makefile

A file named makefile containing all the necessary information to build a program (in UNIX)

  1. Makefile creation the makefile is a sequence of directives, each in the following form:

    # command if needed
    target: dependencies_list
         action

    where:

    • target: name of a rule (usually the name of the file you want to produce)

    • dependencies_list: set of files that the target depends on

    • action: set of commands to execute in order to generate the target from the dependencies_list

Example:

executable_file : file1.o file2.o	
      gcc  -o executable_file  file1.o  file2.o

file1.o : file1.c  header1.h	
      gcc  -o file1.o  file1.c

file2.o : file2.c  header2.h
      gcc  -o file2.o  file2.c
  1. Calling the make command

    make target
    • It executes the action associated with the target after verifying that all its dependencies are satisfied.

    • If not, it searches for the target associated with the missing dependency and executes the corresponding action.

      • If the target is omitted, the first target in the Makefile is executed by default.

cmake

  • Automatic search for programs, libraries, files, and headers

  • Generation of static or dynamic code on different platforms

  • Compilation in a directory tree different from the source tree

  • Creation of complex commands and selection of optional components at runtime

  • Generation of workspaces and projects for common development environments (Xcode, Visual Studio, …)

CMakeLists

File di nome CMakeLists.txt contenente tutte le informazioni necessarie per fare il building di un programma

It can contain:

  • line comments

    # comment
  • commands

    command_name(parameter1, parameter2, ...)

Main commands

Command
Description

project(<name> [VERSION <major>[.<minor>]] [LANGUAGES <language> …] )

Defines a new project with: name: <name> version <major>.[<minor>] written in <language>

add_executable(<name> [WIN32] [MACOSX_BUNDLE] source1 [source2 …] )

It creates an executable for [WIN32], [MACOSX_BUNDLE] (if not specified, defaults to Unix) with the name <name> from the source files source1 source2 ...

cmake_minimum_required(VERSION major.minor)

It specifies the minimum CMake version required to build the project

include_directories ("path")

It indicates the path where the compiler will look for header files

add_subdirectory(src)

It creates a subdirectory named src

add_library(<name> [STATIC | SHARED] source1 [source2 …] )

It specifies the creation of a static or dynamic library named <name>

target_link_libraries(<target> LINK_PUBLIC <lib> …)

It links the library named <lib> to the executable named <target>

set_target_properties(<target> PROPERTIES prop1 value1.)

It defines build properties for the target <target>

Creation of the necessary files for compilation

CMake must be invoked in the directory that contains the CMakeLists.txt file.

cmake path

where:

  • path: directory that contains the source files

Compilation

make

Last updated