Difference between revisions of "MakeFile"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (The Lifetime example)
m (The Lifetime example)
Line 104: Line 104:
 
</pre>
 
</pre>
  
[[Image:HeaderFileGene.png]]
+
[[Image:HeaderFileGene.png|Center]]
  
 
The [http://udk.openoffice.org/common/man/tools.html#cppumaker cppumaker documentation] states
 
The [http://udk.openoffice.org/common/man/tools.html#cppumaker cppumaker documentation] states

Revision as of 12:01, 13 April 2009

Makefile structure

We will artificially divide the makefile in four parts :

  • the setting part
  • the compilation part
  • the execute part
  • the clean part

All makefiles provided with SDK have this structure. We can find very different compilation parts with each example provided. In this chapter we only discuss the setting part. If you have a look on the <OOSDK> directory you will see a « settings » directory. You have to use this directory if you want OS independent makefile. In general this is done with something like :

COMPONENT_NAME=ProfUnoLifetime
DKREGISTRYNAME=/usr/lib/openoffice/program/types.rdb
PRJ=../../../..
SETTINGS=$(PRJ)/settings

include $(SETTINGS)/settings.mk
include $(SETTINGS)/std.mk
include $(SETTINGS)/dk.mk

# Define non-platform/compiler specific settings
COMPONENT_NAME=ProfUnoLifetime
OUT_COMP_INC=$(OUT_INC)/$(COMPONENT_NAME)
OUT_COMP_GEN=$(OUT_MISC)/$(COMPONENT_NAME)
OUT_COMP_OBJ=$(OUT_OBJ)/$(COMPONENT_NAME)

CXXFILES = ProfUnoLifetime.cxx

OBJFILES = $(patsubst %.cxx,$(OUT_COMP_OBJ)/%.$(OBJ_EXT),$(CXXFILES))

The third line is directory-dependent : where your makefile lie and how do you reach the setting directory will change this line and the following, pointing toward the « settings » directory. Of course an other way is to use an absolute URL but portability is worse. The goal of other lines is to prepare compilation. We have let in red macros that seem not to be defined at first glance. But if you have a look to std.mk you will find the lacking definitions even if this files introduce other undefined macros which are in fact defined in settings.mk

Lifetime example: compilation part

The lifetime example is introduced in (page ). The file used to create this example is find in « <OOSDK>/examples/DevelopersGuide/ProfUNO/Lifetime ». The Lifetime directory contains a complicated makefile able of creating either a Java or a C++ example. We focus only on C++ code.

A shorter Makefile

We want to start from a shorter Makefile example than those given with SDK. For example the LifeTime example can be correctly compiled under Linux with this makefile :

# very simple makefile
CXXFILE = Test_Process.cxx
OBJFILE = Test_Process.o
OUTBIN = Test_Process
OUT_COMP_INC = ../../../../LINUXexample.out/inc/ProfUnoLifetime
OUT_COMP_OBJ = ../../../../LINUXexample.out/obj/ProfUnoLifetime
OUT_COMP_BIN = ../../../../LINUXexample.out/bin
CC_FLAGS = -c -O -fpic -fno-rtti
CC_DEFINES = -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3
PS = /
TYPES := \
	com.sun.star.uno.XNamingService \
	com.sun.star.uno.XComponentContext \
	com.sun.star.uno.XWeak \
	com.sun.star.uno.XAggregation \
	com.sun.star.lang.XMain \
	com.sun.star.lang.XMultiServiceFactory \
	com.sun.star.lang.XSingleComponentFactory \
	com.sun.star.lang.XTypeProvider \
	com.sun.star.lang.XComponent \
	com.sun.star.registry.XSimpleRegistry \
	com.sun.star.registry.XImplementationRegistration \
	com.sun.star.bridge.XBridgeFactory \
	com.sun.star.bridge.XUnoUrlResolver \
	com.sun.star.drawing.XDrawPage \
	com.sun.star.container.XHierarchicalNameAccess

TYPESLIST = $(foreach t,$(TYPES),-T$(t))
GENHPPFILES = $(foreach t,$(TYPES),$(OUT_COMP_INC)/$(subst .,/,$(t)).hpp)

ALL : \
    ProUNOLifetimeExamples

$(GENHPPFILES) :  $(subst /,$(PS),$(@D))
	mkdir -p $(OUT_COMP_INC)/$(subst /,$(PS),$(@D))
	cppumaker -Gc -BUCR -O$(OUT_COMP_INC) $(TYPESLIST) "/usr/lib/openoffice/program/types.rdb"

$(OUT_COMP_OBJ)/$(OBJFILE) : $(CXXFILE) $(GENHPPFILES)
	mkdir -p $(OUT_COMP_OBJ)/$(subst /,$(PS),$(@D))
	gcc $(CC_FLAGS) $(CC_INCLUDES) -I. \
	-I/usr/include -I../../../../LINUXexample.out/inc/examples \
	-I../../../../include -I../../../../LINUXexample.out/inc/ProfUnoLifetime $(CC_DEFINES) \
	-o$(OUT_COMP_OBJ)/$(OBJFILE) $(CXXFILE)

$(OUT_COMP_BIN)/$(OUTBIN) : $(OUT_COMP_OBJ)/$(OBJFILE)
	mkdir -p $(OUT_COMP_BIN)
	gcc -Wl -export-dynamic -L../../../../LINUXexample.out/lib -L../../../../linux/lib \
	-L/usr/lib/openoffice/program -o$(OUT_COMP_BIN)/$(OUTBIN) \
	$(OUT_COMP_OBJ)/$(OBJFILE) -lcppuhelpergcc3 -lcppu -lsalhelpergcc3 -lsal -lstlport_gcc

ProUNOLifetimeExamples : $(OUT_COMP_BIN)/$(OUTBIN)
	@echo --------------------------------------------------------------------------------
	@echo Please use one of the following commands to execute the examples!
	@echo
	@echo make ProfUnoLifetime.run
	@echo --------------------------------------------------------------------------------

ProfUnoLifetime.run : $(OUT_COMP_BIN)/$(OUTBIN)
	cd $(OUT_COMP_BIN) && $(OUTBIN)

This makefile is OS dependant. It only works under Linux. The makefiles provided with SDK are OS independent and then use more macros. We want now gives some details for each part of a makefile.

Header file generation

The Lifetime example

We begin with this example because it's the simplest example. First Figure 1.1 demonstrates how to generate the required hdl and hpp files starting from a rdb file and idl files. You will probably easier understand the makefile if you know how works the cppumaker command. As an example we give :

$ cppumaker -Gc -BUCR some.idl <OOo>/program/types.rdb -OSomeWhere 

Center

The cppumaker documentation states

  • -O<path> path describes the root directory for the generated output. The output directory tree is generated under this directory.
  • -T<name> name specifies a type or a list of types. The output for this [t1;...] type is generated. If no '-T' option is specified, then output for all types is generated.
  • -B<name> name specifies the base node.
  • -Gc generate only target files whose content will be changed.

A question comes at first : how we know what hpp files are needed ? For the time being I can't answer this question in a general manner, but I hope to have partially answered in previous chapters. The corresponding makefile part which generates all of the hpp files is shown below :

COMPONENT_NAME=ProfUnoLifetime
DKREGISTRYNAME=/usr/lib/openoffice/program/types.rdb
PRJ=../../../..
SETTINGS=$(PRJ)/settings
OUT_INC=$(PRJ)/LINUXexample.out/inc
OUT_COMP_INC=$(OUT_INC)/$(COMPONENT_NAME)
TYPES := \
	com.sun.star.uno.XNamingService \
	com.sun.star.uno.XComponentContext \
	com.sun.star.uno.XWeak \
	com.sun.star.uno.XAggregation \
	com.sun.star.lang.XMain \
	com.sun.star.lang.XMultiServiceFactory \
	com.sun.star.lang.XSingleComponentFactory \
	com.sun.star.lang.XTypeProvider \
	com.sun.star.lang.XComponent \
	com.sun.star.registry.XSimpleRegistry \
	com.sun.star.registry.XImplementationRegistration \
	com.sun.star.bridge.XBridgeFactory \
	com.sun.star.bridge.XUnoUrlResolver \
	com.sun.star.container.XHierarchicalNameAccess

TYPESLIST = $(foreach t,$(TYPES),-T$(t))
GENHPPFILES = $(foreach t,$(TYPES),$(OUT_COMP_INC)/$(subst .,/,$(t)).hpp)

# Targets
.PHONY: ALL
ALL : ProUNOLifetimeExample

include $(SETTINGS)/stdtarget.mk

$(GENHPPFILES) :
	-$(MKDIR) $(subst /,$(PS),$(@D))
	cppumaker -Gc -BUCR -O$(OUT_COMP_INC) $(TYPESLIST) $(DKREGISTRYNAME)

Again red text indicates macros that seem to be undefined but MKDIR and PS are defined in settings.mk file. An other way to construct header files is to use a makefile and an other tool : xml2cmp. You can find an example in <OpenOffice.org1.1_SDK>/examples/cpp/remoteclient directory.

A more sophisticated example

The hpp construction is not always so easy. This can occur every time you have a component (in the sense of chapter 13). The problem in this case is the cppumaker tool is unable to generate a hpp file if its corresponding interface not registered.

As you can see in Figure 1.2 you have to use idlc to create an urd file. This file and the types.rdb files are used to create a rdb file with regmerge. After and only after cppumaker is able to generate the hpp file corresponding to the starting IDL file. A complete example is given in the makefile in . We give here what is done in a shell under Linux to see this construction in action :

mkdir -p ../../../LINUXexample.out/misc/counter
idlc -I. -I../../../idl -O../../../LINUXexample.out/misc/counter XCountable.idl
idlc: compile 'XCountable.idl' ...
idlc: returned successful
Sun Microsystems (R) idlc Version 1.0

mkdir -p ../../../LINUXexample.out/bin
rm -f ../../../LINUXexample.out/bin/counter.uno.rdb
regmerge ../../../LINUXexample.out/bin/counter.uno.rdb /UCR ../../../LINUXexample.out/misc/counter/XCountable.urd
regmerge ../../../LINUXexample.out/bin/counter.uno.rdb / "/usr/lib/openoffice/program/types.rdb"
mkdir -p ../../../LINUXexample.out/misc
rm -f ../../../LINUXexample.out/misc/cpp_counter_types.flag
cppumaker -Gc -BUCR -O../../../LINUXexample.out/inc/counter  ../../../LINUXexample.out/bin/counter.uno.rdb
echo flagged > ../../../LINUXexample.out/misc/cpp_counter_types.flag
Here is the makefile corresponding part :
....
$(OUT_COMP_GEN)/%.urd : %.idl
	-$(MKDIR) $(subst /,$(PS),$(@D))
	idlc -I. -I$(IDL_DIR) -O$(OUT_COMP_GEN) $<

# This example type library will be extended by the office types
$(OUT_BIN)/%.rdb : $(GENURDFILES)
	-$(MKDIR) $(subst /,$(PS),$(@D))
	-$(DEL) $(subst /,$(PS),$@)
	regmerge $@ /UCR $(GENURDFILES)
	regmerge $@ / $(DKREGISTRYNAME) 

$(COMPONENT_TYPEFLAG) : $(COMPONENT_RDB) $(COMPONENT_XML)
	-$(MKDIR) $(subst /,$(PS),$(@D))
	-$(DEL) $(subst /,$(PS),$(COMPONENT_TYPEFLAG))
	cppumaker -Gc -BUCR -O$(OUT_COMP_INC) $(TYPESLIST) $(COMPONENT_RDB)
	echo flagged > $@
	.....

You are now ready to use gcc to compile your code.

Compiling with gcc

The compilation is achieved in two steps or more steps depending how many files we have to compile. The way is making object files first and then linking.

A two step compilation example

We give first a two step compilation example. You can find such example in

 <OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/CppBinding

or

<OpenOffice.org1.1_SDK>/examples/DevelopersGuide/ProfUNO/Lifetime

and probably elsewhere.

$(OUT_COMP_OBJ)/%.$(OBJ_EXT) : %.cxx $(GENHPPFILES)
	-$(MKDIR) $(subst /,$(PS),$(@D))
	$(CC) $(CC_FLAGS) $(CC_INCLUDES) -I$(OUT_COMP_INC) $(CC_DEFINES) $(CC_OUTPUT_SWITCH)$(subst /,$(PS),$@) $<

$(OUT_BIN)/%$(EXE_EXT) : $(OBJFILES)
	-$(MKDIR) $(subst /,$(PS),$(@D))
	-$(MKDIR) $(subst /,$(PS),$(OUT_COMP_GEN))
ifeq "$(OS)" "WIN"
	$(LINK) $(EXE_LINK_FLAGS) /OUT:$@ /MAP:$(OUT_COMP_GEN)/$(subst $(EXE_EXT),.map,$(@F)) \
	  $(OBJFILES) $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB) $(STLPORTLIB)
else
	$(LINK) $(EXE_LINK_FLAGS) $(LINK_LIBS) -o $@ $(OBJFILES) \
	  $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB) $(STLPORTLIB) $(STDC++LIB)
endif

We don't use red color because again all is defined : CPPUHELPERLIB .... in settings.mk

As you can see linking is done with a lot of library : cppuhelperlib, cppulib, salhelperlib ... I want to mention here that in the Lifetime example I have removed all libraries but keeped cppuhelperlib and this example works properly.

A three step compilation example

If you want to use helper as mentioned in Reflection helper, you have to manage such construction. We give a part of an other short makefile used to compile a binary with an helper :

$(OUT_COMP_OBJ)/$(OBJFILE) : $(CXXFILE) $(GENHPPFILES) $(HELPER).hpp
	-mkdir -p $(subst /,$(PS),$(@D))
	gcc $(CC_FLAGS) $(CC_INCLUDES) -I. -I/usr/include -I$(OUT_COMP_INC)/examples \
	-I../../../../include -I$(OUT_COMP_INC) $(CC_DEFINES) -o$(OUT_COMP_OBJ)/$(OBJFILE) $(CXXFILE)

$(OUT_COMP_OBJ)/$(HELPER).o : $(HELPER).cxx $(HELPER).hpp
	-mkdir -p $(OUT_COMP_OBJ)/
	gcc $(CC_FLAGS) $(CC_INCLUDES) -I. -I/usr/include -I$(OUT_COMP_INC)/examples \
	-I../../../../include -I$(OUT_COMP_INC) $(CC_DEFINES) -o$(OUT_COMP_OBJ)/$(HELPER).o $(HELPER).cxx


$(OUT_COMP_BIN)/$(OUTBIN) : $(OUT_COMP_OBJ)/$(OBJFILE) $(OUT_COMP_OBJ)/$(HELPER).o
	-mkdir -p $(OUT_COMP_BIN)
	gcc -Wl -export-dynamic -L../../../../LINUXexample.out/lib -L../../../../linux/lib \
	-L/usr/lib/openoffice/program 	$(OUT_COMP_OBJ)/$(HELPER).o \
	-o$(OUT_COMP_BIN)/$(OUTBIN) $(OUT_COMP_OBJ)/$(OBJFILE) -lcppuhelpergcc3 -lcppu \ 	
	-lsalhelpergcc3 -lsal -lstlport_gcc

where we see a first compilation of all cxx files into object files and a link (with gcc). The complete makefile is given in chapter 12 (see). Note that this makefile is OS dependant and works only on Linux systems. Here is what you see in a shell when using this kind of MakeFile :

gcc -c -O -fpic -fno-rtti  -I. -I/usr/include -I../../../../LINUXexample.out/inc/examples \
-I../../../../include -I../../../../LINUXexample.out/inc -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3 -o../../../../LINUXexample.out/obj/office_connect.o office_connect.cxx
mkdir -p ../../../../LINUXexample.out/obj/
gcc -c -O -fpic -fno-rtti  -I. -I/usr/include -I../../../../LINUXexample.out/inc/examples \
-I../../../../include -I../../../../LINUXexample.out/inc -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3 -o../../../../LINUXexample.out/obj/ReflectionHelper.o ReflectionHelper.cxx
mkdir -p ../../../../LINUXexample.out/bin
gcc -Wl -export-dynamic -L../../../../LINUXexample.out/lib -L../../../../linux/lib -L/usr/lib/openoffice/program \
../../../../LINUXexample.out/obj/ReflectionHelper.o \
-o../../../../LINUXexample.out/bin/office_connect ../../../../LINUXexample.out/obj/office_connect.o -lcppuhelpergcc3 -lcppu -lsalhelpergcc3 -lsal -lstlport_gcc

A four step compilation example

We encounter a four step example in <OpenOffice.org1.1_SDK>/examples/cpp/counter where two cxx files are compiled. The first counter.cxx is compiled first as conter.o and second as counter.uno.so and the second file countermain.cxx is compiled as countermain.o and then as countermain, a binary executable file. The Figure below shows us what is new in this makefile : constructing a dynamic library.

MakefileCounterEx.png

Here we give the makefile example :

....
COMPONENT_NAME=counter
COMPONENT_IMPL_NAME=$(COMPONENT_NAME).uno.$(SHAREDLIB_EXT)
COMPONENT_IMPL=$(SHAREDLIB_OUT)/$(COMPONENT_IMPL_NAME)
COMPONENT_RDB_NAME = $(COMPONENT_NAME).uno.rdb
COMPONENT_RDB = $(OUT_BIN)/$(COMPONENT_RDB_NAME)
.....
ifeq "$(OS)" "WIN"
$(SHAREDLIB_OUT)/%.$(SHAREDLIB_EXT) : $(SLOFILES) $(OUT_COMP_GEN)/%.def
	-$(MKDIR) $(subst /,$(PS),$(@D))
	-$(MKDIR) $(subst /,$(PS),$(OUT_COMP_GEN))
	$(LINK) $(LIBRARY_LINK_FLAGS) /OUT:$@ /MAP:$(OUT_COMP_GEN)/$(subst $(SHAREDLIB_EXT),map,$(@F)) \
	/DEF:$(OUT_COMP_GEN)/$(subst $(SHAREDLIB_EXT),def,$(@F)) $(SLOFILES) \
	$(CPPUHELPERLIB) $(CPPULIB) $(SALLIB) $(STLPORTLIB) msvcrt.lib kernel32.lib
else
$(SHAREDLIB_OUT)/%.$(SHAREDLIB_EXT) : $(SLOFILES)
	-$(MKDIR) $(subst /,$(PS),$(@D))
	$(LINK) $(LIBRARY_LINK_FLAGS) $(LINK_LIBS) -o $@ $^\
	$(CPPUHELPERLIB) $(CPPULIB) $(SALLIB) $(STLPORTLIB) $(STC++LIB)
endif

Perhaps is it more easy to understand with showing what happens with this makefile part under Linux :

gcc -c -O -fpic -fno-rtti -I. -I/usr/include -I../../../LINUXexample.out/inc/examples -I../../../include -I../../../LINUXexample.out/inc/counter -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3 -o../../../LINUXexample.out/slo/counter/counter.o counter.cxx
mkdir -p ../../../LINUXexample.out/lib
gcc -shared '-Wl,-rpath,$ORIGIN' -L../../../LINUXexample.out/lib -L../../../linux/lib -L/usr/lib/openoffice/program -o ../../../LINUXexample.out/lib/counter.uno.so ../../../LINUXexample.out/slo/counter/counter.o\
-lcppuhelpergcc3 -lcppu -lsal -lstlport_gcc

We want to show now other parts of the makefile.

Home Page

See also

Personal tools