compilation - Proper way to include C code from directories other than the current directory -
i have 2 directories, sorting , searching (children of same directory), have .c source files , .h header files:
mbp:c $ ls sorting array_tools.c bubble_sort.c insertion_sort.c main selection_sort.c array_tools.h bubble_sort.h insertion_sort.h main.c selection_sort.h mbp:c $ ls searching array_tools.c array_tools.h binary_search.c binary_search.h linear_search.c linear_search.h main main.c within searching, building executable needs use insertion_sort function, declared in insertion_sort.h , defined in insertion_sort.c inside sorting. following compilation produces executable:
mbp:searching $ clang -wall -pedantic -g -iquote"../sorting" -o main main.c array_tools.c binary_search.c linear_search.c ../sorting/insertion_sort.c however, able include functions arbitrary directories including header using #include , providing compiler search path. need precompile .c files .o files beforehand? man page clang lists following option:
-i<directory> add specified directory search path include files. but following compilation fails:
mbp:searching $ clang -wall -pedantic -g -i../sorting -o main main.c array_tools.c binary_search.c linear_search.c undefined symbols architecture x86_64: "_insertion_sort", referenced from: _main in main-1a1af0.o ld: symbol(s) not found architecture x86_64 clang: error: linker command failed exit code 1 (use -v see invocation) main.c has following includes:
#include <stdio.h> #include <stdlib.h> #include "linear_search.h" #include "binary_search.h" #include "array_tools.h" #include "insertion_sort.h" i not understand link between header files, source files, , object files. include function defined in .c file, sufficient include homonymous header file, given .c file in same directory header? have read multiple answers here on so, man page clang , number of tutorials, unable find definitive, clear answer.
in response @spectras:
one one, give compiler source file work on. instance:
cc -wall -ipath/to/some/headers foo.c -o foo.o
running
mbp:sorting $ clang -wall insertion_sort.c -o insertion_sort.o produces following error:
undefined symbols architecture x86_64: "_main", referenced from: implicit entry/start main executable ld: symbol(s) not found architecture x86_64 clang: error: linker command failed exit code 1 (use -v see invocation)
okay, it's mixed bit. let's see how 1 typically compiles simple multi-file project.
one one, give compiler source file work on. instance:
cc -c -wall -ipath/to/some/headers foo.c -o foo.o the -c flag tells compiler want object file, should not run linker.
the compiler runs preprocessor on source file. among other things, every time sees
#includedirective, searches include paths named file , copy-pastes it, replacing#includecontent. done recursively.this step
.hinclude merged source file. call whole thing translation unit.you can see result of step using
-eflag , inspect result, instance:cc -wall -ipath/to/some/headers foo.c -e -o foo.testlet's make short other steps not relevant question. compiler creates object file resulting source code. object file contains binary version of code , data in translation unit, plus metadata used put , other stuff (like debugging info).
you can inspect contents of object file using
objdump -xd foo.o.
note done each source file, means headers parsed , compiled again , again , again. that's reason should declare stuff , not contain actual code: end code in every object file.
once done, link object files executable, instance:
cc foo.o bar.o baz.o -o myprogram this step gather all, resolve dependencies , write executable binary. may pull in external object files using -l, when -lrt or -lm.
for instance:
- foo.c includes bar.h
- bar.h contains declaration of function do_bar:
void do_bar(int); - foo.c can use it, , compiler generate foo.o correctly
- foo.o have placeholders , information requires
do_bar - bar.c defines implementation of
do_bar. - so bar.o have information “hey if needs
do_bar, got here”. - linking step replace placeholders actual calls
do_bar.
finally, when pass multiple .c files compiled in question, compiler same thing, won't generate intermediate object files. overall process behaves same though.
so, error?
undefined symbols architecture x86_64: "_insertion_sort", referenced from: _main in main-1a1af0.o ld: symbol(s) not found architecture x86_64 clang: error: linker command failed exit code 1 (use -v see invocation) see? says linking step failed. means previous step went well. #include worked. it's in linking step, it's looking symbol (data or code) called _insertion_sort, , not find it. that's because symbol declared somewhere (otherwise source using not have compiled), definition not available. either no source file implemented it, or object file contains not given linker.
=> need make _insertion_sort's definition available. either adding ../sorting/insertion_sort.c source lists pass or compiling object file , passing that. or building library can shared 2 binaries (otherwise they'll each have copy embedded).
when there, starting use build toolsuite such cmake idea. take care of details you.
Comments
Post a Comment