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 #include directive, searches include paths named file , copy-pastes it, replacing #include content. done recursively.

    this step .h include merged source file. call whole thing translation unit.

    you can see result of step using -e flag , inspect result, instance:

    cc -wall -ipath/to/some/headers foo.c -e -o foo.test 
  • let'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

Popular posts from this blog

python Tkinter Capturing keyboard events save as one single string -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

javascript - Z-index in d3.js -