In this tutorial I’ll show how to build a custom Eclipse distribution with Maven/Tycho. We will create an Eclipse distribution including our own features/plugins and standard Eclipse features, trying to keep the size of the final distribution small.
The code of the example can be found at: https://github.com/LorenzoBettini/customeclipse-example
First of all, we want to mimic the Eclipse SDK product and Eclipse SDK feature; have a look at your Eclipse Installation details
You see that “Eclipse SDK” is the product (org.eclipse.sdk.ide), and “Eclipse Project SDK” is the feature (org.eclipse.sdk.feature.group).
Moreover, we want to deal with a scenario such that
Our custom feature can be installed in an existing Eclipse installation, thus we can release it independently from our custom Eclipse distribution. Our custom Eclipse distribution must be updatable, e.g., when we release a new version of our custom feature.
The project representing our parent pom will be
- customeclipse.example.tycho
The target platform is defined in
- customeclipse.example.targetplatform
For this example we only need the org.eclipse.sdk feature and the native launcher feature
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde version="3.8"?> <target name="luna" sequenceNumber="1"> <locations> <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit"> <unit id="org.eclipse.equinox.executable.feature.group" version="3.6.100.v20140819-1617"/> <unit id="org.eclipse.sdk.feature.group" version="4.4.0.v20140925-0400"/> <repository location="http://download.eclipse.org/releases/luna"/> </location> </locations> </target> |
We created a plugin project and a feature project including such plugin (the plugin is nothing fancy, just an “Hello World Command” created with the Eclipse Plug-in project wizard):
- customeclipse.example.plugin
- customeclipse.example.feature
We also create another project for the p2 repository (Tycho packaging type: eclipse-repository) that distributes our plugin and feature (including the category.xml file)
- customeclipse.example.site
All these projects are then configured with Maven/Tycho pom.xml files.
Then we create another feature that will represent our custom Eclipse distribution
- customeclipse.example.ide.feature
This feature will then specify the features that will be part of our custom Eclipse distribution, i.e., our own feature (customeclipse.example.feature) and all the features taken from the Eclipse update sites that we want to include in our custom distribution.
Finally, we create another site project (Tycho packaging type: eclipse-repository) which is basically the same as customeclipse.example.site, but it also includes the product definition for our custom Eclipse product:
- customeclipse.example.ide.site
NOTE: I’m using two different p2 repository projects because I want to be able to release my feature without releasing the product (see the scenario at the beginning of the post). This will also allow us to experiment with different ways of specifying the features for our custom Eclipse distribution.
Product Configuration
This is our product configuration file customeclipse.example.ide.product in the project customeclipse.example.ide.site and its representation in the Product Configuration Editor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
<?xml version="1.0" encoding="UTF-8"?> <?pde version="3.5"?> <product name="Custom Eclipse SDK" uid="customeclipse.example.ide" id="org.eclipse.sdk.ide" application="org.eclipse.ui.ide.workbench" version="1.0.0.qualifier" useFeatures="true" includeLaunchers="true"> <aboutInfo> <image path="eclipse_lg.gif"/> <text> %productBlurb </text> </aboutInfo> <configIni use="default"> </configIni> <launcherArgs> <vmArgs>-XX:MaxPermSize=256m -Xms512m -Xmx1024m </vmArgs> <vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts </vmArgsMac> </launcherArgs> <windowImages i16="eclipse16.gif" i32="eclipse32.gif" i48="eclipse48.gif" i64="eclipse16.png" i128="eclipse32.png" i256="eclipse48.png"/> <splash location="org.eclipse.platform" startupProgressRect="2,290,448,10" startupMessageRect="7,225,320,20" startupForegroundColor="FFFFFF" /> <launcher> <solaris/> <win useIco="false"> <bmp/> </win> </launcher> <intro introId="org.eclipse.ui.intro.universal"/> <vm> </vm> <plugins> </plugins> <features> <feature id="customeclipse.example.ide.feature"/> </features> <configurations> <plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="4" /> <plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" /> <plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" /> <plugin id="org.eclipse.equinox.event" autoStart="true" startLevel="2" /> <plugin id="org.eclipse.equinox.p2.reconciler.dropins" autoStart="true" startLevel="0" /> <plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" /> <property name="org.eclipse.core.resources/encoding" value="UTF-8" /> <property name="org.eclipse.ui/org.eclipse.ui.edit.text.encoding" value="UTF-8" /> <property name="osgi.instance.area.default" value="@user.home/workspace-customide" /> </configurations> </product> |
Note that we use org.eclipse.sdk.ide and org.eclipse.ui.ide.workbench for launching product extension identifier and application (we don’t have a custom application ourselves).
ATTENTION: Please pay attention to “uid” and “id” in the .product file, which correspond to “ID” and “Product” in the Product definition editor (quite confusing, isn’t it? 😉
This product configuration includes our customeclipse.example.ide.feature; we also inserted in the end the standard start level configuration, and other properties, like the standard workspace location.
The pom in this project will also activate the product materialization and archiving (we also specify the file name of the zip with our own pattern):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>tycho-p2-director-plugin</artifactId> <version>${tycho-version}</version> <executions> <execution> <id>materialize-products</id> <goals> <goal>materialize-products</goal> </goals> </execution> <execution> <id>archive-products</id> <goals> <goal>archive-products</goal> </goals> </execution> </executions> <configuration> <products> <product> <!-- The uid in the .product file, NOT the name of the .product file --> <id>customeclipse.example.ide</id> <archiveFileName>customeclipse-ide-${unqualifiedVersion}-${buildQualifier}</archiveFileName> </product> </products> </configuration> </plugin> |
We chose NOT to include org.eclipse.example.ide.site as a module in our parent pom.xml: we include it only when we enable the profile build-ide: installing and provisioning a product takes some time, so you may not want to do that on every build invocation. In that profile we add the customeclipse.example.ide.site module, this is the relevant part in our parent pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<profile> <id>build-ide</id> <activation> <activeByDefault>false</activeByDefault> </activation> <properties> <target-file-name>luna</target-file-name> </properties> <modules> <module>../customeclipse.example.ide.site</module> </modules> <build> <plugins> <!-- specify all environments when building the IDE --> <plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>target-platform-configuration</artifactId> <version>${tycho-version}</version> <configuration> <target> <artifact> <groupId>customeclipse.example</groupId> <artifactId>customeclipse.example.targetplatform</artifactId> <version>${project.version}</version> <classifier>${target-file-name}</classifier> </artifact> </target> <environments> <environment> <os>win32</os> <ws>win32</ws> <arch>x86_64</arch> </environment> <environment> <os>macosx</os> <ws>cocoa</ws> <arch>x86_64</arch> </environment> <environment> <os>linux</os> <ws>gtk</ws> <arch>x86_64</arch> </environment> </environments> </configuration> </plugin> </plugins> </build> </profile> |
In this profile, we also specify the environments for which we’ll build our custom Eclipse distribution. When this profile is not active, the target-platform-configuration will use only the current environment.
In the rest of the tutorial we’ll examine different ways of defining customeclipse.example.ide.feature. In my opinion, only the last one is the right one; but that depends on what you want to achieve. However, we’ll see the result and drawbacks of all the solutions.
You may want to try the options we detail in the following by cloning the example from https://github.com/LorenzoBettini/customeclipse-example and by modifying the corresponding files.
Include org.eclipse.sdk
The first solution is to simply include the whole org.eclipse.sdk feature in our customeclipse.example.ide.feature:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="UTF-8"?> <feature id="customeclipse.example.ide.feature" label="Custom Eclipse Project SDK" version="1.0.0.qualifier" provider-name="Lorenzo Bettini"> <includes id="customeclipse.example.feature" version="0.0.0"/> <includes id="org.eclipse.sdk" version="0.0.0"/> </feature> |
You can run the maven build specifying the profile build-ide
1 |
maven clean verify -Pbuild-ide |
To get the materialized products (and the corresponding zipped versions).
NOTE: if you enable the tycho-source-feature-plugin in the parent pom to generate also source features, you’ll get this error during the build:
1 2 3 4 5 |
[ERROR] Failed to execute goal org.eclipse.tycho.extras:tycho-source-feature-plugin:0.22.0:source-feature (source-feature) on project customeclipse.example.ide.feature: Could not generate source feature for project MavenProject: customeclipse.example:customeclipse.example.ide.feature:1.0.0-SNAPSHOT @ customeclipse.example.ide.feature/pom.xml [ERROR] Missing sources for features [org.eclipse.sdk_4.4.0.v20140925-0400] |
That’s because it tries to include in customeclipse.example.ide.feature.source the source feature of org.eclipse.sdk, which does not exist (org.eclipse.sdk already includes sources of its included features). You need to tell the tycho plugin to skip the source of org.eclipse.sdk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<plugin> <groupId>org.eclipse.tycho.extras</groupId> <artifactId>tycho-source-feature-plugin</artifactId> <version>${tycho-extras-version}</version> <executions> <execution> <id>source-feature</id> <phase>package</phase> <goals> <goal>source-feature</goal> </goals> <configuration> <excludes> <!-- These are bundles and feature that do not have a corresponding source version; NOT the ones that we do not want source versions --> <feature id="org.eclipse.sdk" /> </excludes> </configuration> </execution> </executions> </plugin> |
The build should succeed.
Let’s copy the installed product directory (choose the one for your OS platform) to another folder; we perform the copy because a subsequent build will wipe out the target directory and we want to do some experiments. Let’s run the product and we see that our custom IDE shows our custom feature menu “Sample Menu” and the corresponding tool bar button:
If we check the installation details we see the layout mimicking the ones of Eclipse SDK (which is included in our product)
Now let’s run the build again with above maven command.
If you have a look at the target directory you see that besides the products, in custom.eclipse.ide.site/target you also have a p2 repository,
we will use the p2 repository to try and update the custom ide that we created in the first maven build (the one we copied to a different directory and that we ran in the previous step). So let’s add this built repository (in my case is /home/bettini/work/eclipse/tycho/custom-eclipse/customeclipse.example.ide.site/target/repository/) in the custom ide’s “Install New Software” dialog.
You see our Example Feature, and if you uncheck Group items by category you also see the Custom Eclipse Project SDK feature (corresponding to customeclipse.example.ide.feature) and Custom Eclipse SDK (corresponding to our product definition uid customeclipse.example.ide).
But wait… only the product is updatable! Why? (You see that’s the only one with the icon for updatable elements; if you try “Check for updates” that’s the only one that’s updatable)
Why can’t I update my “Example Feature” by itself?
If you try to select “Example Feature” in the “Install” dialog to force the update, and press Next…
you’ll get an error, and the proposed solution, i.e., also update the product itself:
And if you have a look at the original error…
…you get an idea of the problem beneath: since we INCLUDED our “customeclipse.example.feature” in our product’s feature “customeclipse.example.ide.feature” the installed product will have a strict version requirement on “customeclipse.example.feature”: it will want exactly the version the original product was built with; long story short: you can’t update that feature, you can only update the whole product.
Before going on, also note in the target directory you have a zip of the p2 repository that has been created: customeclipse.example.ide.site-1.0.0-SNAPSHOT.zip it’s about 200 MB! That’s because the created p2 repository contains ALL the features and bundles INCLUDED in your product (which in our case, it basically means, all features INCLUDED in “customeclipse.example.ide.feature”).
Require org.eclipse.sdk
Let’s try and modify “customeclipse.example.ide.feature” so that it does NOT include the features, but DEPENDS on them (we can also set a version range for required features).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="UTF-8"?> <feature id="customeclipse.example.ide.feature" label="Custom Eclipse Project SDK" version="1.0.0.qualifier" provider-name="Lorenzo Bettini"> <requires> <import feature="customeclipse.example.feature" version="1.0.0.qualifier" match="greaterOrEqual"/> <import feature="org.eclipse.sdk" version="4.4.0.v20140925-0400" match="greaterOrEqual"/> </requires> </feature> |
Let’s build the product.
First of all, note that the p2 repository zip in the target folder of customeclipse.example.ide.site is quite small! Indeed, the repository contains ONLY our features, not all the requirements (in case, you can also force Tycho to include all the requirements), since, as stated above, the required feature will not be part of the repository.
Now let’s do the experiment once again:
- copy the built product for your OS into another directory
- run the product custom ide
- run another maven build
- add the new created p2 repository in the custom ide “Install new software” dialog
Well… the Example Feature does not appear as updatable, but this time, if we select it and press Next, we are simply notified that it is already installed, and that it will be updated
So we can manually update it, but not automatically (“Check for updates” will still propose to update the whole product).
To make a feature updatable in our product we must make it a “Root level feature” (see also http://codeandme.blogspot.com/2014/06/tycho-11-install-root-level-features.html).
At the time of writing the Eclipse product definition editor does not support this feature, so we must edit the .product definition manually and add the line for specifying that customeclipse.example.feature must be a root level feature:
1 2 3 4 |
<features> <feature id="customeclipse.example.ide.feature"/> <feature id="customeclipse.example.feature" installMode="root"/> </features> |
Let’s build again, note that this time the p2 director invocation explicitly installs customeclipse.example.feature
1 2 3 4 |
[INFO] --- tycho-p2-director-plugin:0.22.0:materialize-products (materialize-products) @ customeclipse.example.ide.site --- [INFO] Installing product customeclipse.example.ide for environment ... Installing customeclipse.example.ide 1.0.0.v20150121-1346. Installing customeclipse.example.feature.feature.group 1.0.0.v20150121-1346. |
Let’s do the experiment again; but before trying to update let’s see that the installed software layout is now different: our Example Feature is now a root level feature (it’s also part of our Custom SDK IDE since it’s still required by customeclipse.example.ide.feature but that does not harm, and you may also want to remove that as a requirement in customeclipse.example.ide.feature).
Hey! This time our “Example Feature” is marked as updatable
and also Check for updates proposes “Example Feature” as updatable independently from our product!
What happens if we make also customeclipse.example.ide.feature” a root feature? You may want to try that, and the layout of the installed software will list 3 root elements: our product “Custom Eclipse SDK”, our ide.feature “Custom Eclipse Project SDK” (which is meant to require all the software from other providers, like in this example, the org.eclipse.sdk feature itself) and our “Example Feature”.
This means that also “Custom Eclipse Project SDK” can be updated independently; this might be useful if we plan to release a new version of the ide.feature including (well, depending on) other software not included in Eclipse SDK itself (e.g., Mylyn, Xtext, or something else). At the moment, I wouldn’t see this as a priority so I haven’t set customeclipse.example.ide.feature as a root level feature in the product configuration.
Minimal Distribution
The problem of basing our distribution on org.eclipse.sdk is that the final product will include many features and bundles that you might not want in your custom distribution; e.g., CVS features, not to mention all the sources of the platform and PDE and lots of documentation. Of course, if that’s what we want, then OK. But if we want only the Java Development Tools in our custom distribution (besides our features of course)?
We can tweak the requirements in customeclipse.example.ide.feature and keep them minimal (note that the platform feature is really needed):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="UTF-8"?> <feature id="customeclipse.example.ide.feature" label="Custom Eclipse Project SDK" version="1.0.0.qualifier" provider-name="Lorenzo Bettini"> <requires> <import feature="customeclipse.example.feature" version="1.0.0.qualifier" match="greaterOrEqual"/> <import feature="org.eclipse.jdt" version="3.10.0.v20140925-0400" match="greaterOrEqual"/> <import feature="org.eclipse.platform" version="4.4.0.v20140925-0400" match="greaterOrEqual"/> </requires> </feature> |
Build the product now.
Note also that the installed software has been reduced a lot:
The size of the zipped products dropped down to about 90Mb, instead of about 200Mb as they were before when we were using the whole org.eclipse.sdk feature.
However, by running this product you may notice that we lost some branding
- There’s no Welcome Page
- Eclipse starts with “Resource” Perspective, instead of “Java” Perspective
- Help => About (Note only “About” no more “About Eclipse SDK”) shows:
To recover the typical branding of Eclipse SDK, we have to know that such branding is implemented in the bundle org.eclipse.sdk (the bundle, NOT the homonymous feature).
So, all we have to do is to put that bundle in our feature’s dependencies
1 2 3 4 5 6 |
<requires> <import feature="customeclipse.example.feature" version="1.0.0.qualifier" match="greaterOrEqual"/> <import feature="org.eclipse.jdt" version="3.10.0.v20140925-0400" match="greaterOrEqual"/> <import feature="org.eclipse.platform" version="4.4.0.v20140925-0400" match="greaterOrEqual"/> <import plugin="org.eclipse.sdk"/> </requires> |
Rebuild, and try the product: we have all the branding back! 🙂
I hope you find this blog post useful 🙂
The sources of this example can be found here: https://github.com/LorenzoBettini/customeclipse-example
Thanks Lorenzo, great tutorial! Haven’t tried it but immediately remembered how much pain I had to build my custom Eclipse IDE two years ago (CBI build was at the very beginning).
Andrey, if you happen to try it, please provide feedback 🙂
Thanks Lorenzo,
great post. I’m struggling with including my required component in my eclipse plugin and installing it in Luna (Juno/Kepler works just fine) – https://www.eclipse.org/forums/index.php/t/1063735/
I have a few questions to regarding your example.
* Is there a particular reason that you have the target platform pom file being a “pom” instead of a “eclipse-target-definition”
* What does the “attach-artifact” actually do, because I can’t detect any difference in my result.
I also try to understand how the required mechanism works in detail. If I require a component that has been defined in my target platform, where does that URL ref for the P2 repo get stored in the target P2 repo? I have searched, but did not find anything in my target repo that would identify the P2 update site of the required component (nebula in my case).
Hi Kaj
I’m using pom instead of eclipse-target-definition because that way I can simply switch the .target file by passing the classifier property (see the parent pom); in that directory you could also see an ant file to create a .target file that points to a mirror in the local computer, so that I can easily test a build without waiting for the remote p2 sites (that could be the subject of a future blog post); the attach-artifact is maven related somehow I guess (I’m not a maven expert). I took inspiration from here: http://eclipsedriven.blogspot.it/2011/07/configuring-eclipse-tycho-maven-plugin.html
concerning required features, if I understand your question correctly: no URL will be stored in your p2 update site I’m afraid; you have to tell your users about the URLs of required software… that’s something that has always bugged many users… The workflow would be that your users should first add the URL of the required software in the “Install New Software” location (and press ENTER) so that Eclipse will record that update site, and then they can install your software from your p2 update site (they should select the check box “Contact all update sites…”).
In Mars, they added the possibility to specify references to required software URLs in your category.xml (have a look at the news of Mars milestones). That way, the URLs will be stored in your p2 update site. Unfortunately, Tycho still does not handle this feature; it works only if you export your features directly from Eclipse. Moreover, I think that this works only if you install software in a Mars Eclipse (but I’m not sure).
If you need your p2 update site to be selfcontained, you can instruct Tycho to include all dependencies; that’s also the subject of the next blog post.
Hello
I am new in eclipse rcp development and came here with the hope to gain some knowledge on the concepts. I just want to let you know that this is a great tutorial for some one with significant development experience in eclipse and eclipse-rcp development , though does not help much anybody trying to begin on the domain. Everything is a bit ambiguous your steps are not define you even start from the middle of the story to begin with ! Anyway it’s a waste of time for somebody that has not experience on the domain because he can hardly make any sense out of it.
The tutorial assumes that you’re already familiar with eclipse rcp development
Thnx for the tutorial
Hi,
Thanks a lot for your tutorial. I have a question, though, which you might (or not) be able to answer… I’m in charge of a quite large RCP application (https://github.com/gama-platform/gama) where developers used to use PDE build to produce releases, before we recently moved to Tycho for that. One problem we are facing, however, is that if the features in our product are marked with the property “installMode=”root””, they are not exported by PDE build (i.e. they are not present in the plugins directory of the application, and the application is not functional). And if we remove the property, they are correctly exported again. But of course, we lose in that case the ability to update the features in the resulting release…
Do you have an idea of why it is the case ? And any idea on how we could enable developers to use either PDE build or Tycho while having plugins correctly exported and features marked as updatable ? (keeping PDE build around is for the moment necessary for quick testing of functionalities in the release — and because it is more convenient for first-time developers to just have to click on a button rather than going through the process of Maven/Tycho builds).
Thanks in advance for any answer, even negative 🙂
Cheers
Alexis
Hi Alexis
I have no experience at all with PDE build, so I really don’t know how to handle that with PDE build. Probably, with PDE build, you need to install the “root” features in the product as dependencies. I guess that could be done with p2.inf. But I’m really not sure about that, I’m afraid.
Hello Lorenzo,
great tutorial! I followed your instructions and everything seems to work, except the very last thing: the branding in about dialog and other.
I have “lost” the branding in the product like you said. But I can’t include org.eclipse.sdk in my feature: the plugin is not found. Should I install something? Which feature?
I’m using Eclipse 2018-09 but planning to move to 2021-12.
Thankyou very much.
Gionata
Hi Gionata, glad you enjoyed the tutorial.
When you say that the plugin “org.eclipse.sdk” is not found, where do you get this error?
I mean, during the build or in Eclipse somewhere?
Are you sure you have everything in the target platform (or in your Eclipse installation in case you don’t use a target platform in your development workspace)?
I get the error in the feature dep section of the feature.xml file. And in the maven build:
[ERROR] Cannot resolve project dependencies:
[ERROR] Software being installed: com.test.mas.rcp.ide.feature.feature.group 0.0.1.qualifier
[ERROR] Missing requirement: com.test.mas.rcp.ide.feature.feature.group 0.0.1.qualifier requires ‘org.eclipse.equinox.p2.iu; org.eclipse.sdk 0.0.0’ but it could not be found
p.s. I’m reading your book on Eclipse build automation, a valuable source of information that I’ve been looking for years… 🙂
Thankyou!
In case you need it, this is my target platform:
Is there any tag to instert code in these comments??
My target platform… (the Xml war removed in my previous comment)..
Hi
I don’t think you can paste XML code in comments, or maybe you have to insert it as code, using the editor (if available). In any case, if you use the target platform of my example there should be no problem (start from that target platform and add your additional dependencies).
Please let me know.
P.S. I’m happy you’re enjoying the book as well 🙂
This is what I have in the target platform:
org.eclipse.equinox.sdk.feature.group
org.eclipse.mylyn_feature.feature.group
org.eclipse.platform.sdk
org.eclipse.sdk.ide
is it correct to have plugins and not feature? I can’ find the org.eclipse.sdk.feature.group that is in your target..
Anyway, now I can find the plugin org.eclipse.sdk as a depency for my ide feature.
BUT it’s not working.. no about and no welcome page..
After many trials I’ve found the reason: I’m using a custom product defined by me while you are using “org.eclipse.sdk.ide” as product in the .product file.
If I use the same everything work.
So if I define a custom product there is no branding “inherited” from Eclipse?
Thnkyou very much for your help.
If you use a custom product you’ll have to handle branding (see the example created by the standard Eclipse wizard)
This article is very useful, thank you
But I can’t use Tycho. Can you provide .product build tutorial?
I’m not sure what you mean, but that’s the only approach I’m using…