Programowanie w systemie UNIX/Kompilacja

Z Wikibooks, biblioteki wolnych podręczników.

Kompilacja[edytuj]

pliki[edytuj]

etapy[edytuj]

Etapy kompilacji

Głowne 4 etapy:


Zachowanie plików pośrednich :[2]

 gcc -save-temps


Wywołanie poszczególnych etapów z linii poleceń

 gcc -E -o p.i p.c //pre-processing step
 gcc -S -o p.s p.i // kompilacja do kodu assemblera
 gcc -c -o p.o p.s // assemblacja do kodu obiektowego, inaczej:  as -o p.o p.s
 gcc p.c //

W praktyce najczęściej korzystamy z:

  • 1 etapu ( proste projekty)
  • 2 etapów ( złożone projekty - w celu optymalizacji kompilacji)[3]

Przykłady[edytuj]

gcc - ręczna kompilacja[edytuj]

Jest kilka sposobów [4]


jeden plik[edytuj]

Najprostszy program

Najprostsza kompilacja programu skłądajacego sie z 1 plikku możemy dokonać za pomocą:

  • 1 komendy z linii poleceń
  • użycia Make[5]


linia poleceń[edytuj]

Plik z kodem programu, np. p.c skompiluj za pomocą komendy:

gcc p.c

Otrzymasz plik a.out (standardowa nazwa)

  • uruchom za pomocą:
./a.out


Możesz zmienić nazwę generowanego pliku. W tym celu skompiluj go za pomocą komendy:

gcc p.c -o p.out
  • uruchom za pomocą:
./p.out

Możesz włączyć wszystkie ostrzeżenia (ang. Warnings all)

gcc -Wall p.c


make[edytuj]

Plik makefile z wykorzystaniem 1 etapowej kompilacji

all:
    gcc p.c

z użyciem zmiennych:

# variables
SHELL = /bin/bash
CC = gcc	# compiler to use
CFLAGS = -Wall	# Extra flags to give to the C compiler
SOURCES=p.c
all:
	$(CC) $(SOURCES) $(CFLAGS)


Plik makefile z wykorzystaniem 2 etapowej kompilacji:

all: a.out

# conversion from object to executable
a.out: p.o
	 gcc p.o

# conversion from source file to object file
p.o: p.c
	 gcc -c p.c

#     
clean:
	 rm p.o

kilka plików[edytuj]

kilka plików programu[edytuj]

kilka plików programu
kilka plików programu

Możemy skompilować ręcznie:[6]

  • w 1 poleceniu
  • w osobnych poleceniach
  • za pomocą make

Jedno polecenie:

 gcc 1.c 2.c


Kilka poleceń:[7]

  gcc -c 1.c // c do obj
  gcc -c 2.c // c do obj
  gcc 1.o 2.o // obj do bin

biblioteki[edytuj]

Na przykładzie biblioteki matematycznej libm w wersji:

  • statycznej (zwykle /usr/lib/libm.a) i pliku nagłówkowym math.h (zwykle /usr/include/math.h)
  • ładowanej dynamicznie (/usr/lib/libm.so)

Aby skorzystać z tej biblioteki należy :

  • dodać w pliku p.c: #include <math.h>
  • w czasie kompilacji dołączyć bibliotekę libm: gcc p.c -lm


Kompilacja i linkowanie bibliotek:


   
# https://github.com/theicfire/c_objectfiles_example
all:
	@echo "Pick: static, dynamic1, dynamic2"

# -fPIC not needed anywhere, but (some) other programs like to have it (for some unkown reason to me)
static:
	gcc -Wall -fPIC -c sweet.c
	ar -cvq libsweet.a sweet.o
	@# List with ar -t libsweet.a... woahh note if we don't "make clean" the libsweet.a will just append
	@# the sweet.o. There will be multiple entries for it.
	gcc -o yaa main.c -L. -lsweet
	./yaa

dynamic1:
	gcc -Wall -fPIC -c sweet.c
	gcc -shared -o libsweet.so sweet.o
	gcc -o yaa main.c -L. -Wl,-rpath=`pwd` -lsweet
	./yaa

dynamic2:
	gcc -Wall -fPIC -c sweet.c
	gcc -shared -o libsweet.so sweet.o
	gcc -o yaa main.c -L. -lsweet

	@echo "====Note I have to change the library path!===="
	LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ./yaa



clean:
	rm -f *.a *.so *.o yaa

Narzędzia do kompilacji[edytuj]

bash[edytuj]

Sprawdzanie wyniku kompilacji za pomocą specjalnej zmiennej $? przechowującej wynik ostatniego polecenia:

# https://serverfault.com/questions/126756/gcc-compile-result-from-bash-script
./configure
if [ $? -ne 0 ]
then
    echo Configure failed
    exit 1
fi

make
if [ $? -ne 0 ]
then
    echo make failed
    exit 1
fi

make install 
if [ $? -ne 0 ]
then 
   echo make install failed
   exit 1
fi 

echo All steps Succeeded

Make[edytuj]

Program make jest nadzorcą kompilacji. Wykorzystuje plik reguł kompilacji nazywany zazwyczaj "makefile" i na jego podstawie decyduje które ze składników wielo-źródłowego programu muszą być skompilowane ponownie. Do oceny tego faktu używa pliku reguł i czasu modyfikacji plików. Aby skompilować swój program wprowadź komendę :

make

debug[edytuj]

Debugowanie pliku makefile:[8]

  • make -d ( Print debugging information )
  • make - n
  • make -np
  • make -nd
  • użycie info w pliku makefile


Formatowanie pliku makefile sprawdzimy za pomocą: [9]

  cat -e -t -v makefile

W wyniku:

  • tabulatory jako ^I
  • końcówki linii jako $

autoconf[edytuj]

Typowo:

./configure
make
make install

ale możliwa jest optymalizacja dla procesorów wielordzeniowych:[10]

./configure
make -j 2 # zamień 2 na liczbę rdzeni twojego procesora
make install


Automake[edytuj]

Automake czyta plik Makefile.am i tworzy plik Makefile.in

Ant[edytuj]

Apache Ant jest to narządzie do budowania programów [11]

Optymalizacja[edytuj]

Można przyspieszyć działanie programu przez odpowiednią kompilację [12] (opcje) i przetestowanie efektu. Np. dodanie opcji kompilacji:

-O3 -funroll-loops

lub

-O2

może dać 2-krotne skrócenie czasu wykonania programu. Porównaj efekty zaawansowanej optymalizacji tutaj [13]

Inne opcje:

-mtune=native 

generuje kod dostrojony do aktualnego procesora (na innym też się uruchomi).

-march=native

wykorzystuje wszystkie instrukcje używanego procesora (jeżeli inny procesor ich nie obsługuje, kod nie będzie działał).

Za pomocą instrukcji:

 gcc -O3 -Q --help=optimizers | grep disabled

sprawdzamy wszystkie wyłączone opcje. Przykładowy wynik:

  -fbranch-probabilities      		[disabled]
  -fbranch-target-load-optimize 	[disabled]
  -fbranch-target-load-optimize2 	[disabled]
  -fbtr-bb-exclusive          		[disabled]
  -fconserve-stack            		[disabled]
  -fcx-fortran-rules          		[disabled]
  -fcx-limited-range          		[disabled]
  -fdata-sections             		[disabled]
  -fdelayed-branch            		[disabled]
  -fexceptions                		[disabled]
  -ffinite-math-only          		[disabled]
  -ffloat-store               		[disabled]
  -fgcse-las                  		[disabled]
  -fgcse-sm                   		[disabled]
  -fgraphite-identity         		[disabled]
  -fipa-pta                   		[disabled]
  -floop-block                		[disabled]
  -floop-interchange          		[disabled]
  -floop-nest-optimize        		[disabled]
  -floop-parallelize-all      		[disabled]
  -floop-strip-mine           		[disabled]
  -fmerge-all-constants       		[disabled]
  -fmodulo-sched              		[disabled]
  -fnon-call-exceptions       		[disabled]
  -fnothrow-opt               		[disabled]
  -fomit-frame-pointer        		[disabled]
  -fopt-info                  		[disabled]
  -fpack-struct               		[disabled]
  -fpeel-loops                		[disabled]
  -freg-struct-return         		[disabled]
  -freorder-blocks-and-partition 	[disabled]
  -freschedule-modulo-scheduled-loops 	[disabled]
  -frounding-math             		[disabled]
  -fsched-pressure            		[disabled]
  -fsched-spec-load           		[disabled]
  -fsched-spec-load-dangerous 		[disabled]
  -fsched-stalled-insns       		[disabled]
  -fsched2-use-superblocks    		[disabled]
  -fschedule-insns            		[disabled]
  -fsection-anchors           		[disabled]
  -fsel-sched-pipelining      		[disabled]
  -fsel-sched-pipelining-outer-loops 	[disabled]
  -fsel-sched-reschedule-pipelined 	[disabled]
  -fselective-scheduling      		[disabled]
  -fselective-scheduling2     		[disabled]
  -fshort-double              		[disabled]
  -fshort-wchar               		[disabled]
  -fsignaling-nans            		[disabled]
  -fsingle-precision-constant 		[disabled]
  -fstrict-enums              		[disabled]
  -ftrapv                     		[disabled]
  -ftree-coalesce-inlined-vars 		[disabled]
  -ftree-loop-distribution    		[disabled]
  -ftree-loop-if-convert-stores 	[disabled]
  -ftree-lrs                  		[disabled]
  -funroll-all-loops          		[disabled]
  -funroll-loops              		[disabled]
  -funsafe-loop-optimizations 		[disabled]
  -funsafe-math-optimizations 		[disabled]
  -funwind-tables             		[disabled]
  -fvar-tracking-assignments-toggle 	[disabled]
  -fvar-tracking-uninit       		[disabled]
  -fvariable-expansion-in-unroller 	[disabled]
  -fvpt                       		[disabled]
  -fwhole-program             		[disabled]
  -fwrapv                     		[disabled]

Opcje obliczeń zmiennoprzecinkowych [14]

cpu-type[edytuj]

Typy CPU wg (mikro)architektury:

  • nocona
  • core2
  • nehalem
  • corei7
  • westmere
  • sandybridge
  • corei7-avx
  • ivybridge
  • core-avx-i
  • haswell
  • core-avx2
  • broadwell
  • skylake
  • skylake-avx512
  • cannonlake
  • icelake-client
  • icelake-server
  • cascadelake
  • tigerlake
  • cooperlake
  • bonnell
  • atom
  • silvermont
  • slm
  • goldmont
  • goldmont-plus
  • tremont
  • knl
  • knm
  • x86-64
  • x86-64-v2
  • x86-64-v3
  • x86-64-v4
  • eden-x2
  • nano
  • nano-1000
  • nano-2000
  • nano-3000
  • nano-x2
  • eden-x4
  • nano-x4
  • k8
  • k8-sse3
  • opteron
  • opteron-sse3
  • athlon64
  • athlon64-sse3
  • athlon-fx
  • amdfam10
  • barcelona
  • bdver1
  • bdver2
  • bdver3
  • bdver4
  • znver1
  • znver2
  • znver3
  • btver1
  • btver2
  • native

Polecenie:

 gcc -march=cpu-type

Wygeneruj instrukcje dla typu procesora z rodziny [15]


-march=CPU[,+EXTENSION...]
                          generate code for CPU and EXTENSION, CPU is one of:
                           generic32, generic64, i386, i486, i586, i686,
                           pentium, pentiumpro, pentiumii, pentiumiii, pentium4,
                           prescott, nocona, core, core2, corei7, l1om, k1om,
                           iamcu, k6, k6_2, athlon, opteron, k8, amdfam10,
                           bdver1, bdver2, bdver3, bdver4, znver1, znver2,
                           znver3, btver1, btver2
                          EXTENSION is combination of:
                           8087, 287, 387, 687, cmov, fxsr, mmx, sse, sse2,
                           sse3, sse4a, ssse3, sse4.1, sse4.2, sse4, avx, avx2,
                           avx512f, avx512cd, avx512er, avx512pf, avx512dq,
                           avx512bw, avx512vl, vmx, vmfunc, smx, xsave,
                           xsaveopt, xsavec, xsaves, aes, pclmul, fsgsbase,
                           rdrnd, f16c, bmi2, fma, fma4, xop, lwp, movbe, cx16,
                           ept, lzcnt, popcnt, hle, rtm, invpcid, clflush, nop,
                           syscall, rdtscp, 3dnow, 3dnowa, padlock, svme, sse4a,
                           abm, bmi, tbm, adx, rdseed, prfchw, smap, mpx, sha,
                           clflushopt, prefetchwt1, se1, clwb, avx512ifma,
                           avx512vbmi, avx512_4fmaps, avx512_4vnniw,
                           avx512_vpopcntdq, avx512_vbmi2, avx512_vnni,
                           avx512_bitalg, avx_vnni, clzero, mwaitx, ospke,
                           rdpid, ptwrite, ibt, shstk, gfni, vaes, vpclmulqdq,
                           wbnoinvd, pconfig, waitpkg, cldemote, amx_int8,
                           amx_bf16, amx_tile, movdiri, movdir64b, avx512_bf16,
                           avx512_vp2intersect, tdx, enqcmd, serialize, rdpru,
                           mcommit, sev_es, tsxldtrk, kl, widekl, uintr, hreset,
                           no87, no287, no387, no687, nocmov, nofxsr, nommx,
                           nosse, nosse2, nosse3, nosse4a, nossse3, nosse4.1,
                           nosse4.2, nosse4, noavx, noavx2, noavx512f,
                           noavx512cd, noavx512er, noavx512pf, noavx512dq,
                           noavx512bw, noavx512vl, noavx512ifma, noavx512vbmi,
                           noavx512_4fmaps, noavx512_4vnniw, noavx512_vpopcntdq,
                           noavx512_vbmi2, noavx512_vnni, noavx512_bitalg,
                           noavx_vnni, noibt, noshstk, noamx_int8, noamx_bf16,
                           noamx_tile, nomovdiri, nomovdir64b, noavx512_bf16,
                           noavx512_vp2intersect, notdx, noenqcmd, noserialize,
                           notsxldtrk, nokl, nowidekl, nouintr, nohreset
  -mtune=CPU              optimize for CPU, CPU is one of:
                           generic32, generic64, i8086, i186, i286, i386, i486,
                           i586, i686, pentium, pentiumpro, pentiumii,
                           pentiumiii, pentium4, prescott, nocona, core, core2,
                           corei7, l1om, k1om, iamcu, k6, k6_2, athlon, opteron,
                           k8, amdfam10, bdver1, bdver2, bdver3, bdver4, znver1,
                           znver2, znver3, btver1, btver2

Pełną listę możemy otrzymać za popmocą

gcc --target-help -march=foo
cc1: error: bad value (‘foo’) for ‘-march=’ switch
cc1: note: valid arguments to ‘-march=’ switch are: nocona core2 nehalem corei7 westmere sandybridge corei7-avx ivybridge core-avx-i haswell core-avx2 broadwell skylake skylake-avx512 cannonlake icelake-client icelake-server cascadelake tigerlake cooperlake bonnell atom silvermont slm goldmont goldmont-plus tremont knl knm x86-64 x86-64-v2 x86-64-v3 x86-64-v4 eden-x2 nano nano-1000 nano-2000 nano-3000 nano-x2 eden-x4 nano-x4 k8 k8-sse3 opteron opteron-sse3 athlon64 athlon64-sse3 athlon-fx amdfam10 barcelona bdver1 bdver2 bdver3 bdver4 znver1 znver2 znver3 btver1 btver2 native

Testowanie programu[edytuj]

Są 2 metody: [16]

Program Time[edytuj]

gcc -o prog main.c
time prog

Przykład użycia:

Testujemy ile czasu zajmie 4000 razy wypisanie tekstu (przykładowy kod):

const int iXmax = 4000;
const int iYmax = 4000;
  for(iY=0;iY<iYmax;++iY)
   {
     printf("iY/iYmax =   %d / %d \n", iY, iYmax);
     for(iX=0;iX<iXmax;++iX){}
   }

Skompilowany:

  gcc s.c -lm

Uruchomiony:

  time ./a.out
  real    0m0.267s
  user    0m0.120s
  sys    0m0.040s

Jeśli usuniemy komendę printf:

real    0m0.150s
user    0m0.140s
sys    0m0.020s

Różnica około 0.150 sekundy

Program gprof[edytuj]

Opis gprof

Kompilacja z opcją -pg powoduje, że po wykonaniu skompilowanego programu zostaną zapisanie do pliku gmon.out czasy wykonania poszczególnych funkcji

gcc -o prog main.c -pg
./proggprof prog > test1.prof

lub

gcc -o prg source.c -pg
gprof prg > gprof.out

Zobacz również[edytuj]

Bibliografia[edytuj]

  1. Scripts to build software libraries for various systems by Claude Heiland-Allen
  2. gcc online docs : Developer-Options save-temps
  3. stackoverflow question : trouble-with-c-compilation-via-gcc-command-line
  4. Building C programs on Linux from LinuxQuestions.org
  5. stackoverflow question: how-to-write-a-makefile-to-compile-a-simple-c-program
  6. Compiling-multiple-files - The GNU C Programming Tutorial
  7. GCC and Make Compiling, Linking and Building C/C++ Applications by Chua Hock-Chuan
  8. Managing Projects with GNU Make, Third Edition The Power of GNU Make for Building Anything By Robert Mecklenburg November 2004
  9. stackoverflow question: makefile4-missing-separator-stop
  10. Speed-up compile (make) time on dual-core (or multi-core) processor!
  11. Strona domowa Apache Ant
  12. Algorytmy przetwarzania obrazów i wstęp do pracy z biblioteką OpenCV Pod redakcją Ewarysta Rafajłowicza, Wojciecha Rafajłowicza i Andrzeja Rusieckiego
  13. The Computer Language Benchmarks Game
  14. Semantics of Floating Point Math in GCC
  15. gcc 86-Options
  16. gcc-function-for-find-execution-time - dyskusja na gamedev