Compile
Header (.h/hpp)
vs Implementation (.c/cpp)
Concepts
- Header(interface): only class and function declarations .
- Implementation: all the detailed definition.
How c++ compiles ?
-
compile
cpp
implementation intoobjects
.This only uses the
cpp
and the includedcpps/libs
files.
- linking all the
objects
to create the final binary executable / library.
what does #include do ?
Copy and paste code from the library to the current cpp
file.
WHY ?
- Historical Reason.
- the final executable code does not carry any symbol information.
- compiler is unable to search for symbol declarations alone.
- So we have to use header (interface) and
#include
. - Java's
import
can automatically recognize identifiers from implementation and dynamic library symbols.
-
Reduce compilation time:
- avoid re-compilation.
Libraries
A collection of resources to provide re-usable code.
Generally, any code you include can be viewed as a library.
Using at Compiling
This is the case when you have the source code of the library.
You have both libxxx.cpp
and libxxx.h
.
# the simplest example
# all files are assumed to be in the current dir.
g++ main.cpp libxxx.cpp
-
Header-only library
the full definitions and classes are visible to the compiler in a header file. (just
hpp
, nocpp
)Do not need to create a binary library file, and do not need to copy the implementation here.
- [+] don't need to be compiled. Just include it.
- [+] thus, compiler can better optimize it with the source code available.
- [-] changes to the library will cause re-compilation.
- [-] longer compilation time.
To compile:
g++ main.cpp -I /path/to/include/ # -I: directory that contains the header file.
Using at Linking
This is the case when the library is pre-compiled.
You only have libxxx.h
, and a compiled library file. (static or dynamic)
-
Static Library
When you include a static library, all the used library code are copied to your executable .
- [+] faster.
- [-] make the executable large.
- [-] changes to the code need re-linking and re-compiling.
Created by simply archive the object files.
# Create the object files (only one here) g++ -c unuseful.cpp # --> unuseful.o # Create the archive (insert the lib prefix) ar rcs libunuseful.a unuseful.o # --> libunuseful.a
-
Dynamic Library
When you include a dynamic library, your executable will load the used library code only at run time.
- [+] won't make executable large.
- [+] don't need re-compilation if your code is changed.
- [-] slower.
- [-] may fail to execute if the library is not found / corrupt.
Created by using
-shared
flag.# Create the object file with Position Independent Code [PIC] g++ -fPIC -c unuseful.cpp # --> unuseful.o # Crate the shared library (insert the lib prefix) g++ -shared -o libunuseful.so unuseful.o # --> libunuseful.so
Both kind of library should be compiled & linked by:
g++ main.cpp -I /path/to/include -L /path/to/lib -lunuseful
# -I tells where to find the header (.h)
# -L tells where to search the library (.so/.a)
# -lunuseful tells the name of the libraries to be used.
# -l:foo = foo.so
# -lfoo = libfoo.so
usepkg-config
to auto-find -l<libname>
g++ main.cpp `pkg-config <libname> --cflags --libs`
pkg-config --libs <library>
outputs the link arguments for library.
pkg-config --cflags <library>
outputs the include arguments and any other needed compile flags.
gcc / g++
Used to compile Single source code.
However, it is tedious to compile multiple source files with gcc one-by-one.
gcc main.c # default output is a.out
### 4 step:
# preprocess: main.i
# compile: main.s (assembly code)
# assemble: main.o (binary)
# link: a.out
# generate objects
gcc -c main.c # main.o
# generate asm
gcc -S main.c
# specify output file name
gcc main.c -o main
# include file
gcc main.c -include ./include/head.h
# this is the same to add #include <include/head.h> in main.c
# include dir
gcc main.c -I ./include/
# this makes it work for #include <head.h>
#include "file": 会先在当前目录查找你所制定的头文件, 如果没有, 回到默认的头文件目录找。如果使用-I制定了目录,会先在此目录查找, 然后再按常规的顺序去找。
#include <file>: 会到-I制定的目录查找, 查找不到, 然后将到系统的默认的头文件目录查找 。
# the equivalent ENV: C_INCLUDE_PATH, CPP_INCLUDE_PATH
# library dir
gcc main.c -L ./lib/ -l<libname>
# the equivalent ENV: LD_LIBRARY_PATH
# optimize
gcc main.c -O3 # O0 / O1(default) / O2 / O3
# warning
gcc main.c -w # no warning
gcc main.c -Wall # sall warning
# gdb debug information
gcc main.c -g
And g++
is for c++.
# specify standard
g++ -std=c++11 main.cpp
make
Batch-compile for multiple source files.
The behavior is determined by a makefile
.
However, it is still tedious to write
makefile
for large projects.
make # find makefile in current dir, and run g++
make clean # remove intermediate files
make install # install to where ?
makefile
example
### grammar (use Tab for all indent !!!)
# target ... : pre-requisites ...
# command
# ...
# declare variable
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o
# the first target is the final output !
# make will find dependencies automatically, so this order is OK.
edit : $(objects)
gcc -o edit $(objects)
### this is short for
# edit : main.o kbd.o command.o display.o \
# insert.o search.o files.o utils.o
# gcc -o edit main.o kbd.o command.o display.o \
# insert.o search.o files.o utils.o
main.o : defs.h
### this is short for
# main.o : main.c defs.h
# gcc -c main.c
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
rm edit $(objects)
.PHONY
表示clean
是一个“伪目标”。而在rm
命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。
even simpler
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
# all needs defs.h
$(objects) : defs.h
# else:
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
.PHONY : clean
clean :
rm edit $(objects)
compilers
- Visual C++: GUI compiler, mainly used in Windows.
-
gcc/g++: GNU Compiler Collection.
Standard compiler for Linux C/C++/Fortran/..., with a long history from 1987.
-
clang/clang++: or Low Level Virtual Machine (LLVM).
More modern general compiler, first released in 2003.
Mainly used to provide (slightly?) better performance than gcc.
LLVM is also used as the compilation framework for many new languages (Julia, Rust, Swift...).
Clang is developed by Apple Inc. to replace GCC for better support of LLVM and other new features.