Basics: Boilerplate, And Executables

Single Monolithic Executable

  • Toolchain: Basics

  • Default output name: a.out

    $ gcc hello-single.c
    $ ./a.out
    Hello World
    
  • Explicit output name

    $ gcc -o hello-single hello-single.c
    $ ./hello-single
    Hello World
    
  • Wish list item: out-of-source build (Git requires me to .gitignore output files, for example)

  • ⟶ CMake

Building With CMake

  • CMakeLists.txt (top-level, others will follow once we have subdirectories)

    CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
    PROJECT(Demo)
    ADD_EXECUTABLE(hello-single hello-single.c)
    
  • CMAKE_MINIMUM_REQUIRED(): required by CMake; used to declare which features we will need (or fail)

  • PROJECT(): used in many corners, e.g. package names

    • VERSION parameter (optional); will use it later

  • ADD_EXECUTABLE()

Building With CMake: Separate Source And Build Directories

  • Source directory, e.g. ~/My-Projects/01-single

    • Version controlled

  • Build directory, e.g. ~/My-Builds/01-single-x86_64

    • Not version controlled ⟶ does not interfere with version control (no need to .gitignore build directory)

    • Completely resurrectable

    • Not subject to backups

    • Cheap storage medium

  • Simplest way of building

    • Change to build directory

    • Call cmake to build Makefile skeleton (or ninja) from the source directory

    • Call make (or ninja, for that matter) in the build directory

Create Makefile structure
$ cd ~/My-Builds/01-single-x86_64
$ cmake ~/My-Projects/01-single
-- The C compiler identification is GNU 12.2.1
-- The CXX compiler identification is GNU 12.2.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.7s)
-- Generating done (0.0s)
-- Build files have been written to: /home/jfasch/My-Builds/01-single-x86_64
Build using make
$ make
[ 50%] Building C object CMakeFiles/hello-single.dir/hello-single.c.o
[100%] Linking C executable hello-single
[100%] Built target hello-single

Executables Consisting Of Multiple Sources

  • Programs are rarely so simple

  • Separate compilation units

  • ⟶ potential code re-use

  • ADD_EXECUTABLE() can take more than one source file parameters

ADD_EXECUTABLE(hello-modular hello-main.c hello.c)

Problem: Duplicate Compilation

Problem: More Functionality

  • Download hello-name.{h,c} (add new function hello_name())

  • Call in both executables. Live-hack commandline args.

    • hello-first takes only argv[1]

    • hello-second is more elaborate: all the rest

#ifndef HELLO_NAME_H
#define HELLO_NAME_H

void hello_name(const char* name);

#endif
#include "hello-name.h"
#include <stdio.h>

void hello_name(const char* name)
{
    printf("Hello %s\n", name);
}

Solution: Libraries

  • Bag of object files

  • Come in static and shared flavors