667
edits
Changes
→Makefile.in
== Makefile.in ==
The first step in making the build system aware of our component is to generate an input file for autoconf to use during the configure step, which will build our the necessary Makefile automatically.
$ cd mozilla/extensions/firstxpcom
The Makefile.in should contain the following (NOTE: you can read more about what these files actually mean [http://developer.mozilla.org/en/docs/How_Mozilla%27s_build_system_works here]):
DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = firstxpcom
DIRS = public \
src \
$(NULL)
XPI_NAME = firstxpcom
# A Unique ID for your extension INSTALL_EXTENSION_ID = firstxpcom@senecac.on.ca
# Will create a .xpi in /mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/ XPI_PKGNAME = firstxpcom
# install.rdf will tell Firefox how to install our extension and # this says, "copy install.rdf into our extension dir and xpi" DIST_FILES = install.rdf
include $(topsrcdir)/config/rules.mk
Note the '''DIRS ''' variable. It says that the two directories, public and src, will be enteredduring the build. We That means we also need Makefile.in files in each of thosethese.
Next we need a Makefile.in public directory
Here we tell the build system about our component's name and where it's XPIDL file can be found.
Now a Makefile.in for in the srcdirectory:
Now you can re-build your tree (also known as "rebuilding world") by doing:
$ cd mozilla $ make -f client.mk build
BUT...this takes forever for it to actually reach your code, since it has to traverse the entire tree checking for changes. So, you can bypass the rest of the tree and go directly to your component's build.
$ cd $(objdir) $ ../build/autoconf/make-makefile extensions/firstxpcom
Now call make in $(objdir)/extensions/firstxpcom
$ cd $(objdir)/extensions/firstxpcom $ make
This will create the '''public ''' and '''src ''' directories, as well as generate the Makefiles necessary in each. Go into the public directory and call make again, in order to have your .h and .cpp stubs generated:
$ cd $(objdir)/extensions/firstxpcom/public $ make
If all goes well, you'll see a hundred lines or so of output from make, ending in an error (NOTE: make will error out, since we have no source files yet). We can safely ignore most of it, but a few lines are significant at this point:
<code> IFirstXpcom.idl ../../../dist/bin/xpidl.exe -m header -w -I../../../../extensions/firstxpcom/public -I../../../dist/idl -o _xpidlgen/IFirstXpcom /c/temp/proj/ff-trunk/mozilla/obj-fftrunk/extensions/firstxpcom/public/../../../../extensions/firstxpcom/public/IFirstXpcom.idl Here it is processing our IDL file. As a result of this first partially successful run make, exported and generated header files (i.e.,from our IDL) will be placed in dist/include/firstxpcom. Within $(obdir)/dist/include</firstxpcom/IFirstXpcom.h you'll see a block that begins:code>
You'll need to do a search/replace on '''_MYCLASS_ > ''' and change it to the name of your class, in our case, '''FirstXpcom'''.
Now you can try and re-run make for your extension:
$ cd $(objdir)/extensions/firstxpcom $ make
This will produce a host of errors, mostly related to the fact that we don't have proper includes setup set-up and it can't find declarations it needs. You need to add an include for your interface's generated .hfile:
#include "IFirstXpcom.h"
********** TODO ****************
Discuss https://bugzilla.mozilla.org/show_bug.cgi?id=371201 at this point, and problems I had making this work, how luser helped me, and in the end a bug was filed on the build system.
/* Use this macro when declaring classes * DO NOT EDIT. THIS FILE IS GENERATED FROM c:/temp/proj/ff-trunk/mozilla/obj-fftrunk/extensions/firstxpcom/public/../../../../extensions/firstxpcom/public/IFirstXpcom.idl */ #ifndef __gen_IFirstXpcom_h__ #define __gen_IFirstXpcom_h__ #ifndef __gen_nsISupports_h__ #include "nsISupports.h" #endif /* For IDL files that implement this interfacedon't want to include root IDL files. */ #ifndef NS_NO_VTABLE #define NS_DECL_IFIRSTXPCOM \NS_NO_VTABLE NS_IMETHOD GetName(nsAString & aName); \ #endif NS_IMETHOD SetName(const nsAString & aName); \ NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 /* starting interface: IFirstXpcom *_retval); / #define IFIRSTXPCOM_IID_STR "78af1749-014a-47aa-baec-2669670b7601"
class NS_NO_VTABLE IFirstXpcom : public nsISupports { public: NS_DECLARE_STATIC_IID_ACCESSOR(IFIRSTXPCOM_IID) /* attribute AString name; */ NS_IMETHOD GetName(nsAString & aName) = 0; NS_IMETHOD SetName(const nsAString & aName) = 0; /* long add (in long a, in long b); */ NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(IFirstXpcom, IFIRSTXPCOM_IID) /* Use this macro when declaring classes that implement this interface. */ #define NS_DECL_IFIRSTXPCOM \ NS_IMETHOD GetName(nsAString & aName); \ NS_IMETHOD SetName(const nsAString & aName); \ NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval); /* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */ #define NS_FORWARD_SAFE_IFIRSTXPCOMNS_FORWARD_IFIRSTXPCOM(_to) \ NS_IMETHOD GetName(nsAString & aName) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetName(aName); } \ NS_IMETHOD SetName(const nsAString & aName) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetName(aName); } \ NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Add(a, b, _retval); } #if 0 /* Use this macro to declare functions that forward the code below as a template for the implementation class for behavior of this interfaceto another object in a safe way. */ /* Header file */class _MYCLASS_ : public IFirstXpcom{public: NS_DECL_ISUPPORTS NS_DECL_IFIRSTXPCOM _MYCLASS_ #define NS_FORWARD_SAFE_IFIRSTXPCOM(_to);\ private: ~_MYCLASS_ NS_IMETHOD GetName(nsAString & aName); protected: /* additional members */}; /* Implementation file */NS_IMPL_ISUPPORTS1(_MYCLASS_, IFirstXpcom) _MYCLASS_::_MYCLASS_(){ /* member initializers and constructor code */} _MYCLASS_::~_MYCLASS_(){ /* destructor code */} /* attribute AString name; */NS_IMETHODIMP _MYCLASS_:return !_to ? NS_ERROR_NULL_POINTER : _to->GetName(nsAString & aName){ return NS_ERROR_NOT_IMPLEMENTED;}\NS_IMETHODIMP _MYCLASS_:: NS_IMETHOD SetName(const nsAString & aName){ return NS_ERROR_NOT_IMPLEMENTED;} /* long add !_to ? NS_ERROR_NULL_POINTER : _to->SetName(in long a, in long baName); */} \NS_IMETHODIMP _MYCLASS_:: NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval){ return NS_ERROR_NOT_IMPLEMENTED!_to ? NS_ERROR_NULL_POINTER : _to->Add(a, b, _retval);} /* End of implementation class template. */#endif #endif /* __gen_IFirstXpcom_h__ */ ----------end-------------------
#if 0
/* Use the code below as a template for the implementation class for this interface. */
/* Header file */
class _MYCLASS_ : public IFirstXpcom
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IFIRSTXPCOM
_MYCLASS_();
private:
~_MYCLASS_();
protected:
/* additional members */
};
/* Implementation file */
NS_IMPL_ISUPPORTS1(_MYCLASS_, IFirstXpcom)
_MYCLASS_::_MYCLASS_()
{
/* member initializers and constructor code */
}
_MYCLASS_::~_MYCLASS_()
{
/* destructor code */
}
/* attribute AString name; */
NS_IMETHODIMP _MYCLASS_::GetName(nsAString & aName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP _MYCLASS_::SetName(const nsAString & aName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* long add (in long a, in long b); */
NS_IMETHODIMP _MYCLASS_::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* End of implementation class template. */
#endif
#endif /* __gen_IFirstXpcom_h__ */
What things do you notice? What strikes you?
Header guards (or Include Guards, see [http://en.wikipedia.org/wiki/Include_guardInclude Guards]) are a portable technique for ensuring that includes or defines are only done once. Another way of doing this, especially with the Microsoft compiler, is to use
#pragma once
But this is not portable, and therefore Mozilla doesn't use it.
=== Use of macros ===
* NS_DECL_ISUPPORTS* NS_ENSURE_TRUE* NS_IMPL_NSGETMODULE(* see http://developer.mozilla.org/en/docs/Category:XPCOM_Macros for more examples)
NS_DECL_ appended with any interface name in all caps will declare all of the methods of that interface for you. Looking at the code above shows you how this is possible. For example, NS_DECL_NSIFOO will declare all of the methods of nsIFoo , provided that it exists and that nsIFoo.h was generated by the XPIDL compiler. Consider the following real class:
class myClass : public nsISomeClass { public: NS_DECL_ISUPPORTS // declares AddRef, Release, and QueryInterface NS_DECL_NSISOMECLASS // declares all methods of nsISomeClass myClass(); virtual ~myClass() {} };
Next there is NS_IMPL_ISUPPORTS1. This macro implements the nsISupports interface for you, specifically the implementation of AddRef, Release, and QueryInterface for any object.
NS_IMPL_ISUPPORTS1(classname, interface1)
NS_IMPL_ISUPPORTS2(classname, interface1, interface2) NS_IMPL_ISUPPORTSn(classname, interface1, ..., interfacen)
These macros automatically add the nsISupports entry for you, so you ''don't '' need to do something like thisthe following:
NS_IMPL_ISUPPORTS2(classname, interface1, nsISupports)
As an example, consider seamonkey/xpcom/io/nsBinaryStream.cpp (http://lxr.mozilla.org/seamonkey/source/xpcom/io/nsBinaryStream.cpp#62):
62 NS_IMPL_ISUPPORTS3(nsBinaryOutputStream, nsIObjectOutputStream, nsIBinaryOutputStream, nsIOutputStream)
nsAString, nsresult, PRInt32 -- what are these new types?