Makefile para un componente de OpenOffice

A continuación explicaré el Makefile de ejemplo CppComponent que se encuentra en el SDK de OpenOffice, de Debian Squeeze, con esta explicación es más fácil hacer su propio Makefile, para sus propios componentes, que es una gran ayuda. Para efectos de entenderlo, es bueno tener presente la gráfica:

http://wiki.opdevel.com/OpenOffice?action=AttachFile&do=get&target=ComponentTools.png

Otra explicación muy buena sobre el Makefile está en [5], pero es otro diferente al que usaremos.

Primeras definiciones

Las dos primeras líneas del Makefile contendrán las definiciones de las variables PRJ y SETTINGS. PRJ es el path del sdk de openoffice, o sea el directorio /usr/lib/openoffice/basis3.2/sdk/, y SETTINGS es el path del directorio de settings del sdk, si estamos parados en el directorio /usr/lib/openoffice/basis3.2/sdk/examples/DevelopersGuide/Components/MyComponent entonces las dos primeras líneas serán así:

PRJ = ../../../..
SETTINGS = $(PRJ)/settings

Estructura de Directorios

Como vimos el directorio de compilación es diferente al directorio de las fuentes, el directorio de fuentes es en este caso:

pwd
/usr/lib/openoffice/basis3.2/sdk/examples/DevelopersGuide/Components/MyComponent

O sea el directorio de fuentes está en <OpenOffice.org1.1_SDK>/examples/DevelopersGuide/Components/MyComponent.

La estructura de directorios de la salida que se encontrará en /root/openoffice.org3.2_sdk/LINUXexample.out es:

├── bin
├── inc
│   └── com
│       └── sun
│           └── star
│               ├── <dirs>
│               ├── *.hdl
│               └── *.hpp
├── lib
│   └── counter.uno.so
├── misc
│   ├── oosdk_cpp_types.flag
│   ├── counter
│   │   └── XCountable.urd
│   └── CppComponentSample
│       ├── counter
│       │   └── META-INF
│       │       └── manifest.xml
│       ├── counter.uno.rdb
│       ├── Counter.urd
│       └── Linux_x86_64
│           └── counter.uno.so
└── slo

La estructura de los includes para C++ (que son los archivos .hpp) y para IDL (que son los archivos .hdl) es como sigue:

├── inc
│   └── com
│       └── sun
│           └── star
│               ├── beans
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── bridge
│               │   ├── *.hdl
│               │   ├── *.hpp
│               │   └── oleautomation
│               │       ├── *.hdl
│               │       ├── *.hpp
│               ├── connection
│               │   ├── *.hpp
│               │   └── *.hdl
│               ├── container
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── corba
│               │   ├── *.hdl
│               │   ├── *.hpp
│               │   ├── giop
│               │   │   ├── *.hdl
│               │   │   └── *.hpp
│               │   ├── iiop
│               │   │   ├── *.hdl
│               │   │   └── *.hpp
│               │   └── iop
│               │       ├── *.hdl
│               │       └── *.hpp
│               ├── io
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── java
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── lang
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── loader
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── reflection
│               │   ├── *.hdl
│               │   └── *.hp
│               ├── registry
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── script
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── security
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── task
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── test
│               │   ├── bridge
│               │   │   ├── *.hdl
│               │   │   └── *.hpp
│               │   ├── performance
│               │   │   ├── *.hdl
│               │   │   └── *.hpp
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── uno
│               │   ├── *.hdl
│               │   └── *.hpp
│               ├── uri
│               │   ├── *.hpp
│               │   └── *.hdl
│               └── util
│                   ├── logging
│                   │   ├── *.hdl
│                   │   └── *.hpp
│                   ├── *.hdl
│                   └── *.hpp

Esta estructura de directorios con sus archivos .hdl y .hpp, es generada por el cppumaker en la regla incluida en el archivo stdtarget explicado más adelante.

Incluciones de Makefiles externos

Luego de lo anterior vendrán las inclusiones de tres includes:

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

Existe una cuarta que sería stdtarget, pero no la vamos a incluir aquí, pues va a quedar luego de las variables que definamos, ya la veremos más tarde.

settings.mk

En este settings se incluyen las variables como el OS=LINUX, PS=/, CC=gcc, SHAREDLIB_EXT=so, los flags del compilador, etc, es bueno mirar este archivo, porque contiene todos las variables importantes que se usan para el Makefile. Claro este archivo está de tal forma que puede soportar Windows, o Solaris, no hay que hacer nada, pues el automáticamente revisa el sistema y cuadra las variables para Linux, hay que tener presente que se debió haber ejecutado setsdkenv_unix y luego modificado el archivo /root/.bashrc para agregar la línea de inclusión, explicada en [7].

std.mk

En este archivo de settings, están las variables estándar que se usan en los Makefiles, como es OUT que siempre termina en <algo>example.out, UNOPKG_EXT=uno.pkg, los directorios de la salida el directorio del idl IDL_DIR=$(PRJ)/idl, las variables URE_TYPES y URE_SERVICES, etc.

dk.mk

En este archivo están las definiciones de SDKVERSION=3.2, y de BUILDID=320m12(Build:9483). Pilas SDKVERSION debe estar en 3.2, o este tutorial no va a cuadrar muy bien.

Exploración de las variables inciales

Para explorar las variables iniciales, haga el siguiente Makefile.test, y ejecute make -f Makefile.test

PRJ=../../../..
SETTINGS=$(PRJ)/settings

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

all :
    echo $(URE_TYPES)

Debe imprimir algo como:

# make -f Makefile.test
echo ""/usr/lib/ure/share/misc/types.rdb""
/usr/lib/ure/share/misc/types.rdb

Pruebe en lugar de URE_TYPES, cualquier variable como por ejemplo OFFICE_SERVICES, o SDK_JAVA_UNO_BOOTSTRAP_FILES, SHAREDLIB_EXT etc... Es bueno jugar con esto para conocer qué tiene cada variable.

Archivos de Flags

Los archivos de Flags se utilizan para poder realizar reglas en determinada secuencia. Si por ejemplo deseamos realizar un archivo de extención .o, que le precede a otro archivo de extensión .o, una forma de hacerlo es usar otro archivo intermedio que nos indique cuando fue realizado el primer archivo, y así el segundo archivo dependerá de este archivo, dichos archivos intermedios son los archivos Flags.

Archivos Flags predefinidos

En el archivo stdtarget.mk, se define el archivo SDKTYPEFLAG ../../../../LINUXexample.out/misc/oosdk_cpp_types.flag, este usa una regla que la veremos más adelante.

Este flag se usa para hacer la instalación del registro, es una dependencia de la regla install que está en el archivo stdtarget.mk. Inicialmente se encuentra vacío, luego no se ejecuta nada, si se define entonces se puede definir un proceso de instalación. Por el momento no he profundizado en este tema.

Definiciones específicas para el proyecto

A continuación vienen las definiciones de las variables para el proyecto que queramos instalar:

SAMPLE_NAME=CppComponentSample
SAMPLE_INC_OUT=$(OUT_INC)/$(SAMPLE_NAME)
SAMPLE_GEN_OUT=$(OUT_MISC)/$(SAMPLE_NAME)
SAMPLE_SLO_OUT=$(OUT_SLO)/$(SAMPLE_NAME)
SAMPLE_OBJ_OUT=$(OUT_OBJ)/$(SAMPLE_NAME)

COMP_NAME=CppComponent
COMP_IMPL_NAME=$(COMP_NAME).uno.$(SHAREDLIB_EXT) 

APP1_NAME= TestCppComponent
APP1_BINARY= $(OUT_BIN)/$(APP1_NAME)$(EXE_EXT)

COMP_RDB_NAME = $(COMP_NAME).uno.rdb
COMP_RDB = $(SAMPLE_GEN_OUT)/$(COMP_RDB_NAME)
COMP_PACKAGE = $(OUT_BIN)/$(COMP_NAME).$(UNOOXT_EXT)
COMP_PACKAGE_URL = $(subst \\,\,"$(COMP_PACKAGE_DIR)$(PS)$(COMP_NAME).$(UNOOXT_EXT)")
COMP_UNOPKG_MANIFEST = $(SAMPLE_GEN_OUT)/$(COMP_NAME)/META-INF/manifest.xml
COMP_MAPFILE = $(SAMPLE_GEN_OUT)/$(COMP_NAME).uno.map

COMP_REGISTERFLAG = $(SAMPLE_GEN_OUT)/devguide_$(COMP_NAME)_register_component.flag
COMP_TYPEFLAG = $(SAMPLE_GEN_OUT)/devguide_$(COMP_NAME)_types.flag

IDLFILES = some.idl

CXXFILES = service2_impl.cxx

SLOFILES = $(patsubst %.cxx,$(SAMPLE_SLO_OUT)/%.$(OBJ_EXT),$(CXXFILES))

GENURDFILES = $(patsubst %.idl,$(SAMPLE_GEN_OUT)/%.urd,$(IDLFILES))

#TYPELIST=-Tmy_module.XSomething  \
#        -Tmy_modules.MyService1 \
#        -Tmy_module.MyService2
TYPELIST=com.sun.star.lang.XSingleServiceFactory \
        com.sun.star.lang.XMultiServiceFactory \
        com.sun.star.lang.XServiceInfo \
        com.sun.star.registry.XRegistryKey\
        foo.XCountable \
        foo.Counter

Incluya lo anterior en el Makefile, y comience a explorar las variables para entenderas. Hay básicamente cuatro grupos de variables, todas las que comienzan con SAMPLE; son las que se refieren al ejemplo CppComponentSample que son los directorios en dónde quedan guardados los archivos generados /root/openoffice.org3.2_sdk/LINUXexample.out/<dir>,las que comienzan con COMP son las que se refieren al componente CppComponent como tal y las que comienzan con APP; son las que se refieren a la aplicación TestCppComponent. El cuarto grupo son las otras, que vale la pena explorar en detalle:

Reglas

Aquí comenzamos con la sección de reglas, la primera regla que hay en el archivo es la regla por defecto es la que determina el objetivo último del Makefile que es la de crear el archivo SAMPLE_NAME, y se hace con el instructivo ALL, combinado con el .PHONY, para entender en detalle esto es mejor leer [1].

Primera regla

# Targets
.PHONY: ALL
ALL : \
        $(SAMPLE_NAME)

Claro como es la primera vez que se va a usar y no hay ninguna regla para construir el SAMPLE_NAME, va a botar un error:

make: *** No hay ninguna regla para construir el objetivo `CppComponentSample', necesario para `ALL'.  Alto.

Para evitar este error y podamos continuar con la explicación, debemos hacer la regla para crear el SAMPLE_NAME que es el archivo CppComponentSample, usemos una regla tonta que lista los archivos del directorio:

$(SAMPLE_NAME) :
        echo

Inclusión de stdtarget

Ante de la regla para el $(SAMPLE_NAME) y después de la regla que nombramos como la primera regla ponga el siguiente include:

include $(SETTINGS)/stdtarget.mk

Este include contiene la regla para el target del install en caso de que haya un archivo que sea un $(REGISTERFLAG), y también la regla para construir el archivo de flag /root/openoffice.org3.2_sdk/LINUXexample.out/misc/oosdk_cpp_types.flag que está en la variable $(SDKTYPEFLAG), también ayuda a construir los archivos .hdl, y .hpp a partir del types.rdb, vea la gráfica, por esto es muy importante utilizarlo, literalmente contiene los siguiente:

.SUFFIXES:

.SECONDARY:

ifeq "$(DEBUG)" "yes"
debug : ALL
endif

.PHONY: install
install: $(REGISTERFLAG)

$(SDKTYPEFLAG):  #$(URE_TYPES) $(OFFICE_TYPES)
        -$(MKDIR) $(subst /,$(PS),$(@D))
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$(SDKTYPEFLAG)))
        $(CPPUMAKER) -Gc -BUCR -O$(OUT_INC) $(URE_TYPES) $(OFFICE_TYPES)
        echo flagged > $@

Esta regla produce las siguientes sentencias:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
"/usr/lib/ure/bin/regmerge" /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter.uno.rdb /UCR /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/Counter.urd
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc
rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/misc/oosdk_cpp_types.flag

Lo que hacen estos comandos es primero crear el directorio misc, luego eliminar el archivo de flags, paso siguiente crear la estructura dentro del directorio inc con los archivos de cabezeras .hdl y .hpp, y por último recrea el archivo de flag para actualizar su fecha y hora de creación.

Reglas para construir el .urd y el .rdb

Según la gráfica de arriba el .urd depende del .idl y se construye con el idlc, a su vez el .rdb depende del .urd y se genera con el regmerge, las reglas son como sigue:

$(SAMPLE_GEN_OUT)/%.urd : %.idl
        -$(MKDIR) $(subst /,$(PS),$(@D))
        $(IDLC) -I. -I$(IDL_DIR) -O$(SAMPLE_GEN_OUT) $<

$(SAMPLE_GEN_OUT)/%.rdb : $(GENURDFILES)
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$@))
        -$(MKDIR) $(subst /,$(PS),$(@D))
        $(REGMERGE) $@ /UCR $(GENURDFILES)

Este código produce:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
"/usr/lib/openoffice/basis3.2/sdk/bin/idlc" -I. -I../../../../idl -O/root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample Counter.idl
Compiling: Counter.idl
rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter.uno.rdb
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
"/usr/lib/ure/bin/regmerge" /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter.uno.rdb /UCR /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/Counter.urd

Recuerde que $@ es el target, en este caso $(SAMPLE_GEN_OUT)/%.rdb, y aunque no esté aquí $^ es la lista de dependencias. Estos archivos se generarán en el directorio $(OUT_MISC) /root/openoffice.org3.2_sdk/LINUXexample.out/misc, dicho directorio proviene de la especificación en el archivo std.mk.

Generación del .hlp y el .hpp

La regla que le sigue es la regla para construir los archivos sample.hlp y sample.hpp, en el directorio SAMPLE_INC_OUT /root/openoffice.org3.2_sdk/LINUXexample.out/inc/CppComponentSample, se usa un archivo de flags COMP_TYPEFLAG /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/devguide_CppComponent _types.flag, mire arriba Inclusión de stdtarget. Para poder generarlo. Dependen del archivo de flags SDKTYPEFLAG /root/openoffice.org3.2_sdk/LINUXexample.out/misc/oosdk_cpp_types.flag y de COMP_RDB /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/CppComponent/counter.uno.rdb que fue generado en la regla anterior.

$(COMP_TYPEFLAG) : $(COMP_RDB) $(SDKTYPEFLAG)
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$@))
        -$(MKDIR) $(subst /,$(PS),$(@D))
        $(CPPUMAKER) -Gc -BUCR -O$(SAMPLE_INC_OUT) $(TYPESLIST) $(COMP_RDB) -X$(URE_TYPES) -X$(OFFICE_TYPES)
        echo flagged > $@

Esta regla produce las siguientes líneas de ejecución:

rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/devguide_counter_types.flag
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
"/usr/lib/openoffice/basis3.2/sdk/bin/cppumaker" -Gc -BUCR -O/root/openoffice.org3.2_sdk/LINUXexample.out/inc/CppComponentSample  /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter.uno.rdb -X"/usr/lib/ure/share/misc/types.rdb" #-X"/usr/lib/openoffice/basis3.2/program/offapi.rdb"
echo flagged > /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/devguide_counter_types.flag

Compilación de los archivos .o

Esto se hace por medio de la regla:

$(SAMPLE_SLO_OUT)/%.$(OBJ_EXT) : %.cxx $(COMP_TYPEFLAG)
        -$(MKDIR) $(subst /,$(PS),$(@D))
        $(CC) $(CC_FLAGS) $(CC_INCLUDES) -I$(SAMPLE_INC_OUT) $(CC_DEFINES) $(CC_OUTPUT_SWITCH)$(subst /,$(PS),$@) $<

Depenpende claramente de todo los archivos .cxx y de haber generado los archivos .hlp y .hpp de la regla anterior por medio del archivo de flags COMP_TYPEFLAG, esta regla genera las siguientes líneas de código:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/slo/CppComponentSample
gcc -c -O -fpic -I. -I/root/openoffice.org3.2_sdk/LINUXexample.out/inc -I/root/openoffice.org3.2_sdk/LINUXexample.out/inc/examples -I../../../../include -I/root/openoffice.org3.2_sdk/LINUXexample.out/inc/CppComponentSample -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3 -DGXX_INCLUDE_PATH=/usr/include/c++/4.4 -o/root/openoffice.org3.2_sdk/LINUXexample.out/slo/CppComponentSample/counter.o counter.cxx

Regla para el archivo .uno.map

Esta regla para Linux es copiar sólo el archivo ../../../../settings/component.uno.map en /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter.uno.map, para MacOsx, se le adiciona una línea más.

$(COMP_MAPFILE) : $(SLOFILES)
        -$(MKDIR) $(subst /,$(PS),$(@D))
        cat $(PRJ)/settings/component.uno.map > $(COMP_MAPFILE) 
ifeq "$(OS)" "MACOSX"
        nm -gx $(SLOFILES) | $(ADDSYMBOLS) >> $(COMP_MAPFILE)
endif

Esta regla genera:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
cat ../../../../settings/component.uno.map > /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter.uno.map

Generación de las librerías .so

Estas librerías se linkean para Linux y MacOsx con la siguiente regla:

$(SHAREDLIB_OUT)/%.$(SHAREDLIB_EXT) : $(SLOFILES) $(COMP_MAPFILE)
        -$(MKDIR) $(subst /,$(PS),$(@D)) && $(DEL) $(subst \\,\,$(subst /,$(PS),$@))
        $(LINK) $(COMP_LINK_FLAGS) $(LINK_LIBS) -o $@ $(SLOFILES) \
        $(CPPUHELPERLIB) $(CPPULIB) $(SALLIB) $(STLPORTLIB) $(STC++LIB) $(CPPUHELPERDYLIB) $(CPPUDYLIB) $(SALDYLIB)
ifeq "$(OS)" "MACOSX"
        $(INSTALL_NAME_URELIBS)  $@
endif

genera la siguiente ejecución, salvo la línea de las librerías que no están instaladas

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/lib && rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/lib/counter.uno.so
g++ -shared '-Wl,-rpath,$ORIGIN' -Wl,--version-script,../../../../settings/component.uno.map -L"/root/openoffice.org3.2_sdk/LINUXexample.out/lib" -L"/usr/lib/openoffice/basis3.2/sdk/lib" -L"/usr/lib/ure/lib" -o /root/openoffice.org3.2_sdk/LINUXexample.out/lib/counter.uno.so /root/openoffice.org3.2_sdk/LINUXexample.out/slo/CppComponentSample/counter.o \
        -luno_cppuhelpergcc3 -luno_cppu -luno_sal     

Depende de el archivos .o y del archivo .uno.map generados en las dos reglas anteriores.

Reglas para la instalación del componente

Para instalar el componente es importante que no esté corriendo el openoffice. Para permitir esto ponga en YES la variable SDK_AUTO_DEPLOYMENT = YES, esto se configura al correr el setsdkenv_unix que se esplicó en [3], al poner la configuración como sigue:

Automatic deployment of UNO components (YES/NO) [YES]:

Regla para la generación del manifesto.xml

$(SAMPLE_GEN_OUT)/%/manifest.xml :
        -$(MKDIR) $(subst /,$(PS),$(@D))
        @echo $(OSEP)?xml version="$(QM)1.0$(QM)" encoding="$(QM)UTF-8$(QM)"?$(CSEP) > $@
        @echo $(OSEP)!DOCTYPE manifest:manifest PUBLIC "$(QM)-//OpenOffice.org//DTD Manifest 1.0//EN$(QM)" "$(QM)Manifest.dtd$(QM)"$(CSEP) >> $@
        @echo $(OSEP)manifest:manifest xmlns:manifest="$(QM)http://openoffice.org/2001/manifest$(QM)"$(CSEP) >> $@
        @echo $(SQM)  $(SQM)$(OSEP)manifest:file-entry manifest:media-type="$(QM)application/vnd.sun.star.uno-typelibrary;type=RDB$(QM)" >> $@
        @echo $(SQM)                       $(SQM)manifest:full-path="$(QM)$(subst /META-INF,,$(subst $(SAMPLE_GEN_OUT)/,,$(@D))).uno.rdb$(QM)"/$(CSEP) 
>> $@
        @echo $(SQM)  $(SQM)$(OSEP)manifest:file-entry manifest:media-type="$(QM)application/vnd.sun.star.uno-component;type=native;platform=$(UNOPKG_P
LATFORM)$(QM)" >> $@
        @echo $(SQM)                       $(SQM)manifest:full-path="$(QM)$(subst /META-INF,,$(subst $(SAMPLE_GEN_OUT)/,,$(UNOPKG_PLATFORM)/$(@D))).uno
.$(SHAREDLIB_EXT)$(QM)"/$(CSEP) >> $@
        @echo $(OSEP)/manifest:manifest$(CSEP) >> $@

Esta regla produce:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter/META-INF

Y genera el archivo manifesto.xml, este es un archivo xml, que se genera a partir de la salida estandar, usando echo <texto> > <archivo.xml> y echo >> <archivo.xml>. Y contiene:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
  <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"
                       manifest:full-path="counter.uno.rdb"/>
  <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=native;platform=Linux_x86_64"
                       manifest:full-path="Linux_x86_64/counter.uno.so"/>
</manifest:manifest>

Regla para generar el .oxt

$(COMP_PACKAGE) : $(SHAREDLIB_OUT)/$(COMP_IMPL_NAME) $(COMP_RDB) $(COMP_UNOPKG_MANIFEST)
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$@))
        -$(MKDIR) $(subst /,$(PS),$(@D))
        -$(MKDIR) $(subst /,$(PS),$(SAMPLE_GEN_OUT)/$(UNOPKG_PLATFORM))  
        $(COPY) $(subst /,$(PS),$<) $(subst /,$(PS),$(SAMPLE_GEN_OUT)/$(UNOPKG_PLATFORM))
        cd $(subst /,$(PS),$(SAMPLE_GEN_OUT)) && $(SDK_ZIP) ../../bin/$(@F) $(COMP_RDB_NAME) $(UNOPKG_PLATFORM)/$(<F)
        cd $(subst /,$(PS),$(SAMPLE_GEN_OUT)/$(subst .$(UNOOXT_EXT),,$(@F))) && $(SDK_ZIP) -u ../../../bin/$(@F) META-INF/manifest.xml

Este archivo depende del componente CppComponent.uno.so, del CppComponent.uno.rdb, y del manifest.xml, para entender qué es $(@F), $(<F), vea las variables automáticas en [2].

Esta regla produce:

rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/bin/counter.oxt
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/bin
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/Linux_x86_64       
cp /root/openoffice.org3.2_sdk/LINUXexample.out/lib/counter.uno.so /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/Linux_x86_64
cd /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample && "/usr/bin/zip" ../../bin/counter.oxt counter.uno.rdb Linux_x86_64/counter.uno.so
  adding: counter.uno.rdb (deflated 92%)
  adding: Linux_x86_64/counter.uno.so (deflated 68%)
cd /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/counter && "/usr/bin/zip" -u ../../../bin/counter.oxt META-INF/manifest.xml
  adding: META-INF/manifest.xml (deflated 52%)

Ejecución del Extension Manager

Por medio de un archivo de flags, se ejecuta el Extension Manager y se genera el archivo de flags para el archivo CppComponentSample y la regla SimpleComponent.odt.load.

$(COMP_REGISTERFLAG) : $(COMP_PACKAGE)
ifeq "$(SDK_AUTO_DEPLOYMENT)" "YES"
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$@))
        -$(MKDIR) $(subst /,$(PS),$(@D))
        $(DEPLOYTOOL) $(COMP_PACKAGE_URL)
        @echo flagged > $(subst /,$(PS),$@)
else
        @echo --------------------------------------------------------------------------------
        @echo  If you want to install your component automatically, please set the environment
        @echo  variable SDK_AUTO_DEPLOYMENT = YES. But note that auto deployment is only 
        @echo  possible if no office instance is running. 
        @echo --------------------------------------------------------------------------------
endif

Si la variable SDK_AUTO_DEPLOYMENT está en algo diferente a YES, esta regla produce, el siguiente mensaje:

--------------------------------------------------------------------------------
If you want to install your component automatically, please set the environment
variable SDK_AUTO_DEPLOYMENT = YES. But note that auto deployment is only
possible if no office instance is running.
--------------------------------------------------------------------------------

Si la variable SDK_AUTO_DEPLOYMENT está en YES, ejecuta las siguientes instrucciones:

rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/devguide_counter_register_component.flag
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
"/usr/lib/openoffice/program/unopkg" add -f "/root/openoffice.org3.2_sdk/LINUXexample.out/bin/counter.oxt"
getImplementationEnvironnement return gcc3
component_writeInfo called
New key : /com.sun.star.comp.example.cpp.Counter/UNO/SERVICES
--component_writeInfo calls MyCounterImpl::getSupportedServiceNames_Static()
MyCounterImpl::getSupportedServiceNames_Static(  ) called with foo.Counter
----Sub-Key : foo.Counter build
getImplementationEnvironnement return gcc3
getSupportedServiceNames_MyCounterImpl called
getSupportedServiceNames_MyCounterImpl called
getImplementationEnvironnement return gcc3
getSupportedServiceNames_MyCounterImpl called
getSupportedServiceNames_MyCounterImpl called
getImplementationEnvironnement return gcc3
getSupportedServiceNames_MyCounterImpl called
getSupportedServiceNames_MyCounterImpl called

Las últimas líneas aparecen porque adicioné como en el counter que hicimos inicialmente las líneas de printf, pero retirándoloas aparece los siguiente:

rm -f /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample/devguide_counter_register_component.flag
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
"/usr/lib/openoffice/program/unopkg" add -f "/root/openoffice.org3.2_sdk/LINUXexample.out/bin/counter.oxt"

Este ejecuta el comando unopkg add -f CppComponent.oxt [4], claro con en el directorio correspondiente, y genera un archivo de flags devguide_CppComponent_register_component.flag para poder ejecutarlo en secuencia make.

Reglas auxiliares

Compilación del aplicativo TestCppComponent

$(SAMPLE_OBJ_OUT)/$(APP1_NAME).$(OBJ_EXT) : $(APP1_NAME).cxx $(COMP_TYPEFLAG)
        -$(MKDIR) $(subst /,$(PS),$(@D))
        $(CC) $(CC_FLAGS) $(CC_INCLUDES) -I$(SAMPLE_INC_OUT) $(CC_DEFINES) $(CC_OUTPUT_SWITCH)$(subst /,$(PS),$@) $<

Esta regla produce:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/obj/CppComponentSample
gcc -c -O -fpic -I. -I/root/openoffice.org3.2_sdk/LINUXexample.out/inc -I/root/openoffice.org3.2_sdk/LINUXexample.out/inc/examples -I../../../../include -I/root/openoffice.org3.2_sdk/LINUXexample.out/inc/CppComponentSample -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3 -DGXX_INCLUDE_PATH=/usr/include/c++/4.4 -o/root/openoffice.org3.2_sdk/LINUXexample.out/obj/CppComponentSample/TestCppComponent.o TestCppComponent.cxx

Pero genera los siguientes errores:

TestCppComponent.cxx:45:51: error: com/sun/star/frame/XComponentLoader.hpp: No existe el fichero o el directorio
TestCppComponent.cxx:46:36: error: my_module/MyService1.hpp: No existe el fichero o el directorio
TestCppComponent.cxx:47:36: error: my_module/MyService2.hpp: No existe el fichero o el directorio
TestCppComponent.cxx:53: error: ‘frame’ is not a namespace-name
TestCppComponent.cxx:53: error: expected namespace-name before ‘;’ token
make: *** [/root/openoffice.org3.2_sdk/LINUXexample.out/obj/CppComponentSample/TestCppComponent.o] Error 1

Estos errores ocurren porque en el Typelist no están dichas interfaces [6], para eso hay que modificar el Makelist en el Typelist así:

Nota dichas líneas las voy a comentar para poder instalar el componente recien hecho.

TYPELIST=com.sun.star.frame.XComponentLoader \
        com.sun.star.bridge.XUnoUrlResolver
#-Tmy_module.XSomething  \
#       -Tmy_modules.MyService1 \
#       -Tmy_module.MyService2

Modifique el TestCppComponent.cxx las líneas del include de los servicios:

/*#include <my_module/MyService1.hpp>
#include <my_module/MyService2.hpp>*/

Y agrege un int main(){} comentando el resto del las líneas del SAL_IMPLEMENT_MAIN hasta el final del archivo:

int main(){}
/*SAL_IMPLEMENT_MAIN()
{
...
}*/

Las siguientes líneas compilar el archivo _TestCppComponent

$(OUT_BIN)/_$(APP1_NAME)$(EXE_EXT) : $(SAMPLE_OBJ_OUT)/$(APP1_NAME).$(OBJ_EXT)
        -$(MKDIR) $(subst /,$(PS),$(@D))
        -$(MKDIR) $(subst /,$(PS),$(SAMPLE_GEN_OUT))
ifeq "$(OS)" "WIN"
        $(LINK) $(EXE_LINK_FLAGS) /OUT:$@ /MAP:$(SAMPLE_GEN_OUT)/$(basename $(@F)).map \
          $< $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB) $(STLPORTLIB)
else
        $(LINK) $(EXE_LINK_FLAGS) $(LINK_LIBS) -o $@ $< \
          $(CPPUHELPERLIB) $(CPPULIB) $(SALHELPERLIB) $(SALLIB) $(STLPORTLIB) $(STDC++LIB) $(CPPUHELPERDYLIB) $(CPPUDYLIB) $(SALHELPERDYLIB) $(SALDYLIB)
ifeq "$(OS)" "MACOSX"
        $(INSTALL_NAME_URELIBS_BIN)  $@
endif
endif

$(OUT_BIN)/$(APP1_NAME)$(EXE_EXT) : $(OUT_BIN)/_$(APP1_NAME)$(EXE_EXT)
        $(COPY) $(subst /,$(PS),$(BIN_DIR)/unoapploader$(EXE_EXT)) $(subst /,$(PS),$@)
# touch the target to renew the date for correct dependencies.
# Note: no touch under windows! The unoapploader.exe is copied always.
ifneq "$(OS)" "WIN"
        touch $@
endif

Estas líneas producen:

mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/bin
mkdir -p /root/openoffice.org3.2_sdk/LINUXexample.out/misc/CppComponentSample
g++ -Wl,--allow-shlib-undefined -Wl,-export-dynamic -Wl,-z,defs -Wl,--no-whole-archive -L"/root/openoffice.org3.2_sdk/LINUXexample.out/lib" -L"/usr/lib/openoffice/basis3.2/sdk/lib" -L"/usr/lib/ure/lib" -o /root/openoffice.org3.2_sdk/LINUXexample.out/bin/_TestCppComponent /root/openoffice.org3.2_sdk/LINUXexample.out/obj/CppComponentSample/TestCppComponent.o \
        -luno_cppuhelpergcc3 -luno_cppu -luno_salhelpergcc3 -luno_sal      
cp ../../../../bin/unoapploader /root/openoffice.org3.2_sdk/LINUXexample.out/bin/TestCppComponent
touch /root/openoffice.org3.2_sdk/LINUXexample.out/bin/TestCppComponent

Regla para generar el SAMPLE_NAME '''CppComponentSample'''

Por últimoa aperecerá un mensaje para ejecutar el make con .run correspondiente a la siguiente regla:

$(SAMPLE_NAME) : $(COMP_REGISTERFLAG) $(APP1_BINARY)
        @echo --------------------------------------------------------------------------------
        @echo Please use the following command to execute the example!
        @echo -
        @echo $(MAKE) $(APP1_NAME).run
        @echo --------
        @echo The simple C++ component was installed if SDK_AUTO_DEPLOYMENT = YES.
        @echo You can use this component inside your office installation, see the example
        @echo description. You can also load the "$(QM)SimpleComponent.odt$(QM)" document containing
        @echo a StarBasic macro which uses this component.
        @echo -
        @echo $(MAKE) SimpleComponent.odt.load
        @echo --------------------------------------------------------------------------------

Que produce:


Please use the following command to execute the example! - make TestCppComponent.run


The simple C++ component was installed if SDK_AUTO_DEPLOYMENT = YES. You can use this component inside your office installation, see the example description. You can also load the "SimpleComponent.odt" document containing a StarBasic macro which uses this component. - make SimpleComponent.odt.load


En caso de que se ejecute cualquier archivo con

make <archivo>.run

El make ejecuta la siguiente regla:

%.run: $(OUT_BIN)/%$(EXE_EXT)
        $(subst /,$(PS),$(OUT_BIN))$(PS)$(basename $@)
#       cd $(subst /,$(PS),$(OUT_BIN)) && $(basename $@)

De la misma forma si se ejecuta el comando:

make SimpleComponent.odt.load

Se ejecuta la siguiente regla:

SimpleComponent.odt.load : $(COMP_REGISTERFLAG)
        "$(OFFICE_PROGRAM_PATH)$(PS)soffice" $(basename $@)

Regla para limpiar los archivos innecesarios

La regla para limpiar estos archivos es:

.PHONY: clean
clean :
        -$(DELRECURSIVE) $(subst /,$(PS),$(SAMPLE_INC_OUT))
        -$(DELRECURSIVE) $(subst /,$(PS),$(SAMPLE_GEN_OUT))
        -$(DELRECURSIVE) $(subst /,$(PS),$(SAMPLE_SLO_OUT))
        -$(DELRECURSIVE) $(subst /,$(PS),$(SAMPLE_OBJ_OUT))
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$(OUT_BIN)/$(COMP_NAME)*))
        -$(DEL) $(subst \\,\,$(subst /,$(PS),$(OUT_BIN)/*$(APP1_NAME)*))

Esta regla se ejecuta con:

make clean

y borra los contenidos de los directorios que afecta:

rm -rf ../../../../LINUXexample.out/inc/CppComponentSample
rm -rf ../../../../LINUXexample.out/misc/CppComponentSample
rm -rf ../../../../LINUXexample.out/slo/CppComponentSample
rm -rf ../../../../LINUXexample.out/obj/CppComponentSample
rm -f ../../../../LINUXexample.out/bin/counter*
rm -f ../../../../LINUXexample.out/bin/*TestCppComponent*

Par limpiar completamente los archivos creados use la siguiente cadena de comandos:

make clean
rm /usr/lib/openoffice/basis3.2/sdk/LINUXexample.out/misc/CppComponentSample -rdf
rm /usr/lib/openoffice/basis3.2/sdk/LINUXexample.out/misc/oosdk_cpp_types.flag
rm /usr/lib/openoffice/basis3.2/sdk/LINUXexample.out -rdf
rm /root/openoffice.org3.2_sdk/LINUXexample.out -rdf

[1] http://www.gnu.org/software/make/manual/make.html#Phony-Targets

[2] http://www.gnu.org/software/make/manual/make.html#Automatic-Variables

[3] http://wiki.opdevel.com/OpenOffice

[4] http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Extensions/unopkg

[5] http://wiki.services.openoffice.org/wiki/MakeFil

[6] http://wiki.services.openoffice.org/wiki/UNO_automation_with_a_binary_%28executable%29

[7] http://wiki.opdevel.com/OpenOffice

OpTrWiki: OpenOffice/ComponentMakefile (last edited 2010-06-26 18:17:03 by JuanfJaramillo)