Sie sind auf Seite 1von 9

8i: Building Makefiles and Libraries for the Oracle Precompilers This article covers the following important

concepts that programmers need to understand when developing 3GL programs on UNIX platforms: 1. 2. 3. 4. 5. 6. 7. What is the makefile? What are symbols and libraries? What is the difference between static and shared libraries? How to create the Oracle shared library How to create your static libraries How to create your shared libraries How to create your own customized makefile to compile and link Oracle precompiler programs 8. Common issues 1. What is the Makefile? ------------------------A makefile is a description file used by the UNIX 'make' utility. The makefile includes dependencies and rules for building a target executable. Such rules can be precompiling commands, compiling commands, linking commands, or commands for removing temporary files. The ultimate goal of the make utility is to build the final executable program using the rules contained within the makefile. The makefile can have any name. 2. What are Symbols and Libraries? ----------------------------------When you create a 3GL program, you have external references, global and local functions, and static and global variables. After compiling and producing the object file, you would have external, global, and local symbols. The linker assigns addresses to these variable and function symbols. Therefore, the symbols become names for memory addresses and are derived from the named functions. Object files are created when you compile your function source files. These functions can be linked with a main program to produce an executable, or bundled into one archived file called a library. So, the library becomes a repository for these object files referencing the defined symbols. 3. Static vs. Shared Libraries ------------------------------Static libraries have an extension .a which means the library is archived using the UNIX 'ar' utility. When linking with a static library, a physical copy of the library is attached to the executable program. That is, the object files and the libraries are linked together before calling the executable. This makes your executable size fairly large and may present resource (disk or memory) concerns. With a shared library, on the other hand, the library is sharable among many versions of different executable files. The entire copy of the library is not attached to the executable. Think of it as a pointer from the executable to the shared library. The shared library is dynamically linked to an executable at run time. The

shared or dynamic link has advantages over the static link. The size of the code to be executed can be considerably smaller. You may gain memory efficiency if many applications are to be run at the same time, and one copy of the shared library is used by all of them. 4. Oracle Shared Library ------------------------In Oracle V7.1 and earlier versions, all Oracle libraries were static which caused user-created applications to be very large. This was because all of the Oracle libraries were attached to the executable. Oracle first created a shared library for applications libraries in Oracle V7.2. Now, the Oracle runtime libraries for Precompilers, Oracle Call Interface (OCI), and Transaction Monitor (XA) are bundled into one shared library called libclntsh. Oracle, however, kept the static libraries in case you do not want to link shared. Note: OCI static libraries are in libclient.a beginning with Oracle V7.3. libclntsh may take extension .so, .a or .sl, depending on the platform. Even though Oracle creates the shared library during the installation, you may need to create it again if it was missed, or if you want to have another copy of it. Oracle provides a makefile called ins_rdbms.mk that you use to create libclntsh. % cd $ORACLE_HOME/rdbms/lib % make -f ins_rdbms.mk client_sharedlib If you wish to link your Pro*C or OCI program with the shared or static libraries, perform the following steps: a. Create libclntsh using ins_rdbms.mk. b. Set the environment variable LD_LIBRARY_PATH to $ORACLE_HOME/lib Note: Platforms such as HP-UX recognize SHLIB_PATH instead for dynamic linking. Consult your UNIX documentation for further detail. Using the demo_proc.mk file, the rules for building your Pro*C targets are: -- Shared linking build: $(OBJS) $(CC) -o $(EXE) $(OBJS) -L$(LIBHOME) $(PROLDLIBS) -- Static linking build_static: $(OBJS) $(CC) -o $(EXE) $(OBJS) -L$(LIBHOME) $(STATICPROLDLIBS) Using the demo_rdbms.mk file, the rules for building your OCI targets are: -- Shared linking build: $(LIBCLNTSH) $(OBJS) $(ECHODO) $(CC) $(LDFLAGS) -o $(EXE) $(OBJS) $(OCISHAREDLIBS) -- Dynamic linking build_static: $(OBJS) $(ECHODO) $(CC) $(LDFLAGS) -o $(EXE) $(OBJS) $(SSDBED) $(DEF_ON) \

$(OCISTATICLIBS) Note: Due to platform and Oracle version variations, the targets and makefiles themselves may appear slightly different from platform to platform. This article should be used as a GUIDELINE only. 5. Creating Your Static Library -------------------------------To address portability and reusability concerns, you may want to create libraries with your object files. Your libraries can be common Pro*C or C functions used by different applications. These libraries can be added to the link line of your Pro*C application. The following are four basic Pro*C functions: connect() - establishes the connection to the database sqr() - inserts into the table scott_tab disconnect() - closes the connection to Oracle sql_err() - prints any Oracle error codes that occur in the application These functions are stored in files fun2.pc, fun3.pc, fun1.pc, and fun4.pc, respectively. /* fun2.pc */ #include <stdio.h> #include "sqlca.h" void connect() { char *userid="scott/tiger"; exec sql whenever SQLERROR do sql_err(); exec sql connect :userid; printf("\n Connected To Scott\n"); sqr(); } /* fun3.pc */ #include "sqlca.h" void sqr() { int * sum, n, j; printf("\nHow many numbers do you wish to square? scanf(" %d",&n); sum= (int *)malloc(n*sizeof(int)); for(j=0; j<=n-1; j++) { printf("\nEnter %d number", j+1); scanf("%d", &sum[j]); } for(j=0; j<=n-1; j++) { exec sql insert into scott_tab values (:sum[j],:sum[j] * :sum[j]); } } /* fun1.pc */ #include "sqlca.h"

");

void disconnect() { exec sql whenever sqlerror do sql_err(); exec sql commit work release; } /* fun4.pc */ #include "sqlca.h" void sql_err() { printf("Error %d", sqlca.sqlcode); exit(1); } First precompile and compile the functions to generate the object files in two separate steps. %proc iname=fun2.pc Pro*C/C++: Release 8.1.5.0.0 - Production on Tue Feb 1 10:13:40 2000 (c) Copyright 1999 Oracle Corporation. All rights reserved. System default option values taken from: /u05/app/oracle/product/8.1.5/precomp/a dmin/pcscfg.cfg %cc -c -I $ORACLE_HOME/precomp/public fun2.c Precompiling and compiling fun3.pc, fun1.pc, and fun4.pc similarly you get their three object files as well. It is possible for one static library to contain all four functions, but here you create two archived static libraries: ar r libsqr.a fun2.o fun3.o ar r libdis.a fun1.o fun4.o Note, on some platforms, the linker does not automatically create the lookup table. You may need to run the following additional command 'ranlib libsqr.a'. Consult your UNIX manual for additional information about the 'ar' and 'ranlib' utilities. This additional step is not needed for Solaris 2.6. Now, you can call connect() and the three other functions outlined above, provided you add libsqr.a and libdis.a to the link line. The following is a simple calling Pro*C program, test.pc that references the functions that you created. #include "sqlca.h" main() { exec sql whenever SQLERROR do sql_err(); printf("\n Welcome\n"); connect(); disconnect(); printf("\n GoodBye\n"); } Before executing test.pc, you need to link libsqr.a, and libdis.a. If you

are using the Oracle provided makefile, demo_proc.mk, simply create a MYSTATLIB macro and add modify the link line as: MYSTATLIB= /u01/home/usupport/alatasi/shared/libsqr.a \ /u01/home/usupport/alatasi/shared/libdis.a build_static: $(OBJS) $(CC) -o $(EXE) $(OBJS) $(MYSTATLIB) -L$(LIBHOME) $(STATICPROLDLIBS) Note: The build_static target distributed with version 8.1.5 requires modifications to the STATICPROLDLIBS AND PROLDLIBS macros. 6. Creating Your Shared Library -------------------------------As with creating static libraries, creating shared libraries may differ slightly from one platform to another. The following is how a shared library is created for fun1.o, fun2.o, fun3.o, and fun4.o on a Solaris 2.6 machine: ld -G -o liballsh.so fun1.o fun2.o fun3.o fun4.o Note, the static and shared libraries are created from the system prompt. You could, however, include the linker command in your makefile or in a shell script. Now that you have created the shared library, add it to the link line in your makefile. If you are using demo_proc.mk, add liballsh.so to the 'build' target the same way you added the libsqr and libdis libraries. In your makefile, create a macro for liballsh.so and call it MYSHARLIB. MYSHARLIB= /u01/home/usupport/alatasi/shared/liballsh.so build: $(OBJS) $(CC) -o $(EXE) $(OBJS) $(MYSHARLIB) -L$(LIBHOME) $(PROLDLIBS) 7. Creating Your Own Makefile -----------------------------Oracle makefiles are multi-purpose. In addition to precompiling, compiling, and linking your applications, there are makefiles used for product installation (Pro*C, Pro*COBOL, and libclntsh). Oracle asks customers to use the Oracle-provided makefiles because they are fully supported. If customers need to add their own files or libraries, they can modify the Oracle provided makefiles as outlined in the prior section. A Customized Makefile --------------------This section contains an easy method to create a customized makefile. Since understanding the components of the UNIX 'make' utility is not the primary purpose of this bulletin, we assume that the reader has some familiarity with 'make'. We refer to the Pro*C makefile, demo_proc.mk, to build our makefile. The intent is to offer a model for producing a customized makefile, based off the Oracle provided makefiles, for educational purposes only. CUSTOMIZED MAKEFILES ARE NOT SUPPORTED BY ORACLE SUPPORT SERVICES. The first step is to build the target for your executables. Looking at demo_proc.mk, we see that the target 'build' is the one used to create any dynamically linked executable file. The dependency line contains the macro OBJS that lists the object files. OBJS and EXE can be specified on the UNIX command

line. The make command line should have at least the CC and LDFLAGS macros. So, your makefile may start with: build: $(OBJS) $(ECHO) $(CC) $(LDFLAGS) -o $(EXE) $(OBJS) You still need to add the Oracle libraries on your CC line so that they are linked to the OBJS file to produce the executable file (EXE). One easy way is to compile an Oracle-provided Pro*C sample program and save the output to a shell file: make - f demo_proc.mk build EXE=sample1 OBJS=sample1.o > myshell.sh When compiling sample1.pc on a Solaris machine, you will note the shared library, libclntsh.so, being linked: cc -o sample1 sample1.o -L/u05/app/oracle/product/8.1.5/lib/ -lclntsh Parsing this output file further reveals the static libraries and object files required for static linking. But remember, you can easily use the build_static target mentioned earlier to accomplish static linking. make -f demo_proc.mk build EXE=sample1 OBJS=sample1.o cc -o sample1 sample1.o -L/u05/app/oracle/product/8.1.5/lib/ -lclient8 /u05/app/oracle/product/8.1.5/lib/libsql8.a /u05/app/oracle/product/8.1.5/lib/scorept.o /u05/app/oracle/product/8.1.5/lib/sscoreed.o /u05/app/oracle/product/8.1.5/rdbms/lib/kpudfo.o `cat /u05/app/oracle/product/8.1.5/lib/ldflags` -ln8 -lnl8 -lnro8 `cat /u05/app/oracle/product/8.1.5/lib/ldflags` -ln8 -lnl8 -lclient8 -lvsn8 -lcommon8 -lskgxp8 -lgeneric8 `cat /u05/app/oracle/product/8.1.5/lib/ldflags` -ln8 -lnl8 -lnro8 `cat /u05/app/oracle/product/8.1.5/lib/ldflags` -ln8 -lnl8 -lclient8 -lvsn8 -lcommon8 -lskgxp8 -lgeneric8 /u05/app/oracle/product/8.1.5/lib/libpls8.a /u05/app/oracle/product/8.1.5/lib/libplp8.a /u05/app/oracle/product/8.1.5/lib/libpls8.a -ltrace8 -lnls8 -lcore8 -lnls8 -lcore8 -lnls8 `cat /u05/app/oracle/product/8.1.5/lib/sysliblist` -lm -lthread When comparing to Oracle version 7.2.2, notice that the link map looked quite different. Thus, Oracle recommends using our makefile to insulate you from library changes in a future release. make - f proc.mk build OBJS=sample1.o EXE=sample1 ld - dy /u04/oracle/V7224/lib/Croat /u04/oracle/V7224/lib/court/u04/oracle/Very24/lib/__fstd.o -R /opt/SUNWcluster/lib -YP, /opt/SUNWconn/dni/lib:/opt/SUNWspro/lib:/usr/openwin/lib:/opt/cobol/coblib: /u04/oracle/V7224/lib:/opt/SUNWcluster/lib:/usr/ccs/lib:/usr/lib -Qy -lc /u04/oracle/V7224/lib/crtn.o -L/u04/oracle/V7224/lib -o sample1 sample1.o -lsql /u04/oracle/V7224/lib/osntab.o -lsqlnet -lora -lsqlnet -lora -lpls -lnlsrtl3 -lc3v6 -lcore3 -lnlsrtl3 -lcore3 -lsocket -lnsl -lm -ldl -laio -lposix4 -lsocket -lnsl -lm -ldl -laio -lposix4

Now you can copy the Oracle shared library that the linker used to produce the executable into our makefile: build: $(OBJS) $(ECHO) $(CC) $(LDFLAGS) -o $(EXE) $(OBJS) \ -L/u05/app/oracle/product/8.1.5/lib -lclntsh Pay attention to the command lines within the makefile. If lines continue, add a backslash (\) to the end of the first line and start the next line with a tab. Adding INCLUDE, CFLAGS, and CC macros to our makefile results in a complete makefile that compiles and links any Pro*C program if user-defined files or libraries are not needed. INCLUDE= $(ORACLE_HOME)/precomp/public CFLAGS= -I$(INCLUDE) CC=cc #To include sqlca and other headers

If you precompile your Pro*C program separately as: proc iname=test.pc you can call our makefile to create the executable: make -f ourmake.mk EXE=test OBJS=test.o Note that the LD_LIBRARY_PATH environment variable should contain the path to the Oracle libraries-- $ORACLE_HOME/lib. Otherwise, you must specify this path using the linking macro (LDFLAGS) or specify the full path of the Oracle libraries on the CC line. To complete the basic components of the makefile, add the Pro*C precompiler. Since the 'build' target depends on OBJS which has no prerequisites or rules, a suffix rule is used here to cause the make utility to invoke the C compiler to create the object files. After including the Pro*C precompiler and the suffix rule, our makefile constitutes a complete makefile which precompiles, compiles, and links any Pro*C program with Oracle shared libraries. Here it is: INCLUDE= $(ORACLE_HOME)/precomp/public CFLAGS= -I$(INCLUDE) CC=cc PROC= $(ORACLE_HOME)/bin/proc .SUFFIXES: .o .c .pc .pc.o: $(PROC) iname=$*.pc $(CC) $(CFLAGS) -c $*.c #To include sqlca and other headers

build: $(OBJS) $(ECHO) $(CC) $(LDFLAGS) -o $(EXE) $(OBJS) -lclntsh make -f ourmake.mk EXE=test OBJS=test.o For simplicity, we did not use the PROCFLAGS macro to specify the precompiler options. It can be added to the .pc.o suffix rule. We have so far put together the basic steps to write a customized makefile. It is very likely that you will need to organize the file differently and add your own object files and shared/archived libraries. For instance, the Oracle libraries

might be bundled together under the macro ORACLELIBS, or Oracle shared and static libraries might be assigned to macros LIBSHR and LIBSTAT respectively. Your makefile may look like: INCLUDE= $(ORACLE_HOME)/precomp/public #To include sqlca and other headers CFLAGS= -I$(INCLUDE) CC=cc PROC= $(ORACLE_HOME)/bin/proc ORACLELIBS= $(ORACLE_HOME)/lib/libclntsh.so MYSHARLIB=/u05/home/tsupport/malshous/liballsh.so .SUFFIXES: .o .c .pc .pc.o: $(PROC) iname=$*.pc $(CC) $(CFLAGS) -c $*.c build: $(OBJS) $(ECHO) $(CC) $(LDFLAGS) -o $(EXE) $(MYSHARLIB) $(OBJS) \ $(ORACLELIBS) The CC line is very clear, and easy to understand and maintain. As we have mentioned earlier, Oracle gives users an option to link with shared or static libraries. We can incorporate that into our makefile. In addition, we can add also the libraries that we created earlier: libsqr, libdis, and liballsh. The last thing that should be mentioned before putting out the last version of our makefile is the linker. How do you include your library in the link line? The linker searches the following to find libraries specified on the link line: - Paths assigned to the LD_LIBRARY_PATH environment variable - Default paths, e.g. /usr/lib and /lib - Paths passed by the linking flags -L and -l in the makefile. Ensure that the LD_LIBRARY_PATH includes these paths. - Libraries specified with complete paths We will use the linking flags to specify the path to the libraries that we have created. We will put these flags in the macro, LDFLAGS, in the makefile. We will assign two paths to LDFLAGS, one for the Oracle libraries, and the other for ours. LDFLAGS=-L$(LIBHOME) -L$(MYLIBHOME) Now, any library in LIBHOME or MYLIBHOME can be linked using the -l option. Note, it is very likely that the path to the Oracle libraries is already assigned to LD_LIBRARY_PATH. Here is the final version of our makefile: #This is our makefile # INCLUDE= $(ORACLE_HOME)/precomp/public #To include sqlca and other headers CFLAGS= -I$(INCLUDE) -dy LDFLAGS=-L$(LIBHOME) -L$(MYLIBHOME) PROC= $(ORACLE_HOME)/bin/proc LIBHOME=/u05/app/oracle/product/8.1.5/lib MYLIBHOME=/u01/home/usupport/alatasi/shared CC=cc MYSHARLIB= -lallsh MYSTATLIB= -lsqr -ldis

ORACLELIBS=clntsh .SUFFIXES: .o .c .pc .pc.o: $(PROC) iname=$*.pc $(CC) $(CFLAGS) -c $*.c build: $(OBJS) $(ECHO) $(CC) $(LDFLAGS) -o $(EXE) -l$(MYSHARLIB) $(OBJS) \ -l$(ORACLELIBS) 8. Common Issues ----------------Q. I modified the Oracle provided makefile, and now I am getting undefined symbols at link time. A. You may be using libraries that are not specified on your link line, or the library may be misplaced. The simplest way to solve the problem is to: 1. Use the 'nm' or 'ar' utilities to search for the symbols where your libraries are located. For example, mysymbol is an undefined symbol: nm *.a | grep mysymbol 2. Add the library to different places on the CC link line. 3. If you eliminate the undefined symbol error, remove the unnecessary copies using a trial-and-error approach. Some of the most common undefined symbol errors are sqlcex or sqlctx. These symbols are referenced in libsql.a or libclntsh.so. Ensure that the libsql or libclntsh is linked properly on your link line. The code in this bulletin was initially developed on a Solaris 2.4 machine using RDBMS 7.2.2/ProC 2.1.2, and later updated to Solaris 2.6 using RDBMS/Pro*C 8.1.5. Due to platform and version variances, this article should be used as a GUIDELINE to understand the Oracle provided makefiles. Q. I am attempting to statically link my application and receive undefined symbol errors. A. You need to map the static library references exactly, including the repetitions of some static libraries, shown earlier in the section on static linking.

Das könnte Ihnen auch gefallen