Programowanie w systemie UNIX/Kompilacja
Kompilacja
edytuj- środowiska
- architektury sprzętowearchitektury [1]
- architekturyu programowe ( biblioteki : w języku C )
pliki
edytuj- źródłowe ( c, h)
- obiektowe ( o)
- wynikowe
- programu : out
- biblioteki: so, a
etapy
edytujGłowne 4 etapy:
- Pre-processing (polecenie cpp)
- kompilacja (polecenie gcc)
- Assemblacja (polecenie as)
- linkowanie ( polecenie ld = linker )
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
edytujJest kilka sposobów [4]
jeden plik
edytujNajprostsza kompilacja programu skłądajacego sie z 1 plikku możemy dokonać za pomocą:
- 1 komendy z linii poleceń
- użycia Make[5]
linia poleceń
edytujPlik 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
edytujPlik 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
edytujkilka plików programu
edytujMoż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
edytujNa 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:
- rene nyffenegger notes: C-C-plus-plus GCC create-libraries
- How to link a shared library with GCC and CMake by PragmaticLinuxMarch 9, 2022
- yolinux TUTORIALS: LibraryArchives-StaticAndDynamic
# 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- make
- makedepend
- gccmakedep
bash
edytujSprawdzanie 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
edytujProgram 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
edytujDebugowanie 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 $
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
edytujAutomake czyta plik Makefile.am i tworzy plik Makefile.in
Ant
edytujApache Ant jest to narządzie do budowania programów [11]
Optymalizacja
edytujMoż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
edytujTypy 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
edytujSą 2 metody: [16]
Program Time
edytujgcc -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
edytujKompilacja 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- C/Używanie kompilatora
- C/Więcej o kompilowaniu
- profilowanie
- Odpluskwiane (ang. debugging), testy bezpieczeństwa
Bibliografia
edytuj- ↑ Scripts to build software libraries for various systems by Claude Heiland-Allen
- ↑ gcc online docs : Developer-Options save-temps
- ↑ stackoverflow question : trouble-with-c-compilation-via-gcc-command-line
- ↑ Building C programs on Linux from LinuxQuestions.org
- ↑ stackoverflow question: how-to-write-a-makefile-to-compile-a-simple-c-program
- ↑ Compiling-multiple-files - The GNU C Programming Tutorial
- ↑ GCC and Make Compiling, Linking and Building C/C++ Applications by Chua Hock-Chuan
- ↑ Managing Projects with GNU Make, Third Edition The Power of GNU Make for Building Anything By Robert Mecklenburg November 2004
- ↑ stackoverflow question: makefile4-missing-separator-stop
- ↑ Speed-up compile (make) time on dual-core (or multi-core) processor!
- ↑ Strona domowa Apache Ant
- ↑ Algorytmy przetwarzania obrazów i wstęp do pracy z biblioteką OpenCV Pod redakcją Ewarysta Rafajłowicza, Wojciecha Rafajłowicza i Andrzeja Rusieckiego
- ↑ The Computer Language Benchmarks Game
- ↑ Semantics of Floating Point Math in GCC
- ↑ gcc 86-Options
- ↑ gcc-function-for-find-execution-time - dyskusja na gamedev