# Things to remember when compiling/linking C/C++ software

by Angel Leon. March 17, 2015.

Include Paths

On the compilation phase, you will usually need to specify the different include paths so that the interfaces (.h, .hpp) which define structs, classes, constans, and functions can be found.

With gcc and llvm include paths are passed with -I/path/to/includes, you can pass as many -I as you need.

In Windows, cl.exe takes include paths with the following syntax:
/I"c:\path\to\includes\ you can also pass as many as you need.

Some software uses macro definition variables that should be passed during compile time to decide what code to include.

Compilation flags

These compilation-time variables are passed using -D,
e.g. -DMYSOFTWARE_COMPILATION_VARIABLE -DDO_SOMETHING=1 DDISABLE_DEPRECATED_FUNCTIONS=0

These compilation time flags are by convention usually put into a single variable named CXXFLAGS, which is then passed to the compiler as a parameter for convenience when you’re building your compilation/make script.

Object files

When you compile your .c, or .cpp files, you will end up with object files.
These files usually have .o extensions in Linux, in Windows they might be under .obj extensions.

You can create an .o file for a single or for many source files.

Static Library files

When you have several .o files, you can put them together as a library, a static library. In Linux/Mac these static libraries are simply archive files, or .a files. In windows, static library files exist under the .lib extension.

They are created like this in Linux/Mac:

ar -cvq libctest.a ctest1.o ctest2.o ctest3.o

libctest.a will contain ctest1.o,ctest2.o and ctest2.o

They are created like this in Windows:

LIB.EXE /OUT:MYLIB.LIB FILE1.OBJ FILE2.OBJ FILE3.OBJ

When you are creating an executable that needs to make use of a library, if you use these static libraries, the size of your executable will be the sum of all the object files statically linked by the executable. The code is right there along the executable, it’s easier to distribute, but again, the size of the executable can be bigger than it needs to… why? because, sometimes, many of the .o files, or even the entire .a file you’re linking against might be a standard library that many other programs need.

Shared Libraries (Dynamic Libraries)

So shared or dynamic libraries were invented so that different programs or libraries would make external (shared) references to them, since they’re “shared” the symbols defined in them don’t need to be part of your executable or library, your executable contain symbols whose entry points or offset addresses might point to somewhere within themselves, but they will also have symbols whose entry points are expected to exist on shared libraries which need only be loaded once in a single portion of the operating shared memory, thus not just making the size of your executable as small as it needs to be, but you won’t need to load the library for every process/program that needs its symbols.

On Linux shared files exist under the .so (shared object) file extension, on Mac .dylib (dynamic library), and in Windows they’re called .dll (dynamic link libraries)

Another cool thing about dynamic libraries, is that they can be linked during runtime, not just compile time. An example of runtime dynamic libraries are browser plugins.

In Linux .so files are created like this:

gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0   *.o
  • -Wall enables all warnings.
  • -c means don’t run the linker.
  • -fPIC means “Position Independent Code”, a requirement for shared libraries in Linux.
  • -shared makes the object file created shareable by different executables.
  • -Wl passes a comma separated list of arguments to the linker.
  • -soname means “shared object name” to use.

In Mac .dylib files are created like this:

clang -dynamiclib -o libtest.dylib file1.o file2.o -L/some/library/path -lname_of_library_without_lib_prefix

In Windows .dll files are created like this:

LINK.EXE /DLL /OUT:MYLIB.DLL FILE1.OBJ FILE2.OBJ FILE3OBJ

Linking to existing libraries

When linking your software you may be faced with a situation on which you want to link against several standard shared libraries.
If all the libraries you need exist in a single folder, you can set the LD_LIBRARY_PATH to that folder. By common standard all shared libraries are prefixed with the word lib. If a library exists in LD_LIBRARY_PATH and you want to link against it, you don’t need to pass the entire path to the library, you simply pass -lname and you will link your executable to the symbols of libname.so which should be somewhere inside LD_LIBRARY_PATH.

Tip: You should probably stay away from altering your LD_LIBRARY_PATH, if you do, make sure you keep its original value, and when you’re done restore it, as you might screw the build processes of other software in the system which might depend on what’s on the LD_LIBRARY_PATH.

If you have some other libbar.so library on another folder outside LD_LIBRARY_PATH you can explictly pass the full path to that library /path/to/that/other/library/libbar.so, or you can specify the folder that contains it -L/path/to/that/other/library and then the short hand form -lbar. This latter option makes more sense if the second folder contains several other libraries.

Useful tools

Sometimes you may be dealing with issues like undefined symbol errors, and you may want to inspect what symbols (functions) are defined in your library.

On Mac there’s otool, on Linux/Mac there’s nm, on Windows there’s depends.exe (a GUI tool that can be used to see both dependencies and the symbol’s tables. Taking a look at the “Entry Point” column will help you understand clearly the difference between symbols linking to a shared library vs symbols linking statically to the same library)

Useful command options

See shared library dependencies on Mac with otool

otool -L libjlibtorrent.dylib 
libjlibtorrent.dylib:
    libjlibtorrent.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

See shared symbols with nm (Linux/Mac)
With nm, you can see the symbol’s name list.
Familiarize yourself with the meaning of the symbol types:
* T (text section symbol)
* U (undefined – useful for those undefined symbol error),
* I (indirect symbol).
*
If the symbol is local (non-external) the symbol type is presented in lowercase letters, for example a lowercase u represents an undefined reference to a private external in another module in the same library.

nm‘s documentation says that if you’re working on Mac and you see that the symbol is preceeded by + or - it means it’s an ObjectiveC method, if you’re familiar with ObjectiveC you will know that + is for class methods and - is for instance methods, but in practice it seems to be a bit more explicit and you will often see objc or OBJC prefixed to those methods.

nm is best used along with grep 😉

Find all Undefined symbols

nm -u libMacOSXUtilsLeopard.jnilib
_CFRelease
_LSSharedFileListCopySnapshot
_LSSharedFileListCreate
_LSSharedFileListInsertItemURL
_LSSharedFileListItemRemove
_LSSharedFileListItemResolve
_NSFullUserName
_OBJC_CLASS_$_NSArray
_OBJC_CLASS_$_NSAutoreleasePool
_OBJC_CLASS_$_NSDictionary
_OBJC_CLASS_$_NSMutableArray
_OBJC_CLASS_$_NSMutableDictionary
_OBJC_CLASS_$_NSString
_OBJC_CLASS_$_NSURL
__Block_copy
__NSConcreteGlobalBlock
__dyld_register_func_for_add_image
__objc_empty_cache
__objc_empty_vtable
_calloc
_class_addMethod
_class_getInstanceMethod
_class_getInstanceSize
_class_getInstanceVariable
_class_getIvarLayout

Manifest on Internet’s Evolution

(Forgotten draft from May 31st 2010)

I’m a little sad to see some of the paths the internet is taking lately. I personally think it’s enough about the infatuation that people have with “Social Networking”, enough, it’s boring and it makes us waste precious time as a race.

Technology is coming together for you to re-assess those technological ambitions that were not possible 10 years ago. Our networks are faster than ever, our home computers are several orders of magnitude more powerful, with multicore processing, gigs of RAM, powerful video cards, and what are we doing? Sending 140 chars at the time, and wasting time on Facebook a huge but simple friend database that can be resumed for external access to a simple 6 file “SDK”.

I write this (ongoing) manifest to inspire you to not waste your time on building the next social bullshit web “service”. I want you to think of yourself as the entrepreneur or scientist that truly changed the world for the better in a little way, not the one that made the entire world waste it’s time for you to make some bucks.

Everyone is in the Clouds, wake up, use those powerful CPUs
It’s like we forgot that we have powerful CPUs and hardware in our computers, like we forgot all the amazing technology we’ve created over the years and fell for the o-mighty-cloud. While at it we’re stuck with HTML5 and Javascript of all languages.

If we’re indeed going to rebuild and create new things for the browser, why the hell do we have to do it with such a limited set of technologies. Since I think we’ll be stuck in it, it’s time to create better IDEs and debugging tools for it, or start making those new browsers support the latest iterations in ECMA, to have proper Object Oriented support, a freaking binary primitive data type, threading and lower level I/O.

And why are we all buying this cloud crap, it’s like going back to mainframe/dummy terminal all over again, and paying for it. If things keep going this way, I might as well go back to a Pentium II with 64mb ram.

It’s about how we imagine the future
Think the future is not happening the way you thought it would be? Re-imagine, do something about it.

Stop cloning crap, build on top of it If you’re too late in the game
Competition is good, but you should recognize when you’re too late to enter the game unless you have something truly compelling and new to offer, on which case you might try to do business with the market leaders. For example, we don’t need another Twitter clone. Twitter was not the first on their space, Jaiku was there before (google even bought them) but they didn’t win. Remember what happened to Pwnce?