Two steps:
1. download intel parallel studio xe from the website 2. default installation folder is /opt/intel use find command to search for 'compilervars.sh' then add the environment variable into the system through: source compilervars.sh intel64 problem solved. CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice.
Note: When Cmake used for compiling a library: In this case, in build folder, the CMakeCache.txt is your old friend: configure. You need to make sure the CMakeCache.txt has the RIGHT configuration you want. Such as which compiler to use? What optimization flags to use? Otherwise you might find out your library is not that efficient.. Q & A: 1) How to check the variable in Cmake? grep Var CMakeCache.txt Introduction This is something I always want to write about, since it is a very big issue throughout a programmer's whole life. Makefile short code Makefile is a GNUMake program that helps you compiling the source code in a incremental way so that it can save a lot time. Here is a quick and dirty code I googled for whole night to obtain, cannot be found anywhere else. Basically this is an universal Makefile: - Makefile - src/*.cpp - build/*.o The Makefile below will automatically compiling everything in src and move them to build directory, to achieve build-compiling separation which is very important to clear your code structure. Final exe will be in the root directory ================================================================= Universal Makefile - separate build and debugging ================================================================= CC = g++ LD = g++ CFLAG = -Wall PROG_NAME = prog SRC_DIR = ./src BUILD_DIR = ./build BIN_DIR = ./bin SRC_LIST = $(wildcard $(SRC_DIR)/*.cpp) OBJ_LIST = $(BUILD_DIR)/$(notdir $(SRC_LIST:.cpp=.o)) .PHONY: all clean $(PROG_NAME) compile all: $(PROG_NAME) compile: $(CC) -c $(CFLAG) $(SRC_LIST) -o $(OBJ_LIST) $(PROG_NAME): compile $(LD) $(OBJ_LIST) -o $(BIN_DIR)/$@ clean: rm -f $(BIN_DIR)/$(PROG_NAME) $(BUILD_DIR)/*.o ================================================================= Brief on programming behind the scence Compiling and linking program has two key things that you need out-of-your-current code
Include is for the header files, which is a declaration for the main program that there exists a special stuff you need somewhere. Linking is to tell the program: hey here is the stuff you need, take them! The centre of our story is compiler. It will not complete unless compiler is specified. Let's take C++ programming language and take g++ compiler for example. First, we can get a clear idea of what compiler should do when it confronts a bunch of code. Take a example from Makefile (an automatic way to build and compile program): $(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET) Explanation $(CC): compiler $(CFLAGS): CLI option you need to parse to the compiler $(INC_PATH): directory to search for header files $(LIB_PATH): directory to search for library files (library files, *.a or *.so are just assemble of object files) $(OBJECT_FILES): your *.o files compiled by $(CC) from your source code like cpp,c AND library that you find in $(LIB_PATH) with header in $(INC_PATH) $(TARGET): your program! What we can conclude from the above example is
Remember the flags are overly simplified in the above Makefile case. In fact, we will need three things at the same time in specific:
A real case from C++ : (remember this is case by case for different compiler and different program) e.g., g++ -I/usr/include/x86_64-linux-gnu main.cpp -L/usr/lib/x86_64-linux-gnu -lboost_timer -lboost_system Art of order in compiling The c++ library resolve the undefined reference from left to right: from "the one don't resolve" to "the one resolve everything". Note 1. -v is the VERBOSE mode, which output every information FAQ
Extra notes
Introduction
I was looking into if cython could make *.a so that maybe speed can be even faster when calling python. However it ends up with a NOT. The basic reason is that Python Doesn't support static library. Even if you could make *.a from *.o, since cython already made the *.c file for you. So this notes will talk about two things.
Before moving on, first we need to make it clear about what is the processing of converting programming to a code that machine can run. compile -> link -> run Sometimes the compile and link is also called 'build'. ' Before talking about library, first we need to figure out what is link process, because once library is created in compiling process long time ago, it will only be called from linking process. In some cases, the library will be called from run process, which is called dynamically loaded libraries[1]. What's static and how to create a static library To talk about static, the first concept came out of your mind could be: static variable in C. Yes, it is saying the scope of the variable to be accessible is within the file (even though the variable is still lying somewhere in the memory). In contrast, extern is another concept about global variable. So what's the 'static' means in the 'static library' ? Good question. Actually it means 'global', not dynamic. Some where in the memory and not going to be changed. This is the meaning of static in static library. However, the later one usually refers to code/data segment in memory rather than just variables. The C compiler or any other compiler is just translating the language of human readable to computer readable, which is what we call, machine code. Usually there is an output of compiler, usually, it is a obj file. Usually, obj files contains: the definition of functions (code), definition of global variables. If you are not familiar with what a declaration and a definition is, please refer to [1]. To put it simple, the declaration is a promise that a definition of something exists somewhere else in the whole program, including the library you will probably use. Basically, when the compiler saw the source code, it just leave blanks to the referring location where he is not so sure about what to put in the code. Usually, the naming convention for static library is here
So finally let's come to how to build a static library. Use the tool: archiver: ar
The main.c is the code calling the static library, -lx means I searched for a library called libx.a -L. means -Ldir, so the dir is ., so it means searching for current directory. Then run the code ./statically-linked, then the code works. What's shared and how to create a shared library One of the biggest advantage of using a shared library is that, if static library, becomes extremely popular, then the executable in your computer that calling those static library will use a numerous number of useless meaningless disk space just because for static library it just copy the code in *.a to your executable. For this kinds of library, I mean, shared library, the normal linker will behaves a little bit different. When linker saw the reference in the code, it will not include the DEFINITION to the executable. Instead, it just writes down what's the missing variable and which library it should come from IN the executable. So, the acquiring of definition only comes at RUN-TIME. Now, this means that none of the executable has the copy of the *.so's source code. Another thing worthy to know is that if a symbol is pulled from a shared library, then the WHOLE library is mapped into the address space of the program, while for calling static library, only the missing symbol is copied. A useful tool need to be mentioned is the ldd, which can tells you the dependency of current *.so library. Step 1: when compiling the code, using -fPIC flag to force position independent code. so get *.o that is Position independant code, needed for shared libraries. gcc -c -fPIC mean.c -o mean.o Step 2: create the .so library gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1 mean.o Step 3: Link dynamic library with the main code gcc main.c -o dynamically_linked -L. -lmean For linking a dynamically library (*.so in unix-like system), you need to add the path to the library into the environment variable because the link stage is executed at the run time. set: LD_LIBRARY_PATH = . However this method is not recommended. See information here [2] Then run the dynamically linked code is fun. Flag explanation: -shared: This is actually an option to the linker, not the compiler. Since gcc contains its own linker. Produce a shared object which can then be linked with other objects to form an executable. -Wl: Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. So here, it is passing -soname libmean.so.1 to the linker, then linker will know the soname of the shared library is libmean.so.1, which would be helpful if there is multiple version of library. So it is saying that he API for libmean.so.1.0.1 is the same as libmean.so.1, which means for all 1.x.x, the API is the same. Then when other code ask to link the libmean.so.1.0.1, it will search for if the soname instead, so they don't have to specifically typing libmean.so.1.0.1 but libmean.so.1 is enough for them to linking the codes. Other voices[3]:
Appendix:
Reference: [1] Beginner's Guide to Linker |
AuthorShaowu Pan Archives
December 2017
Categories
All
|