Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
wiki:creating_extensions [2018/07/08 21:49] – [Submitting] aus9 | wiki:creating_extensions [2024/08/25 13:09] (current) – [Adding Custom Startup Scripts] rhermsen | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ======Creating an Extension ====== | + | ===== Creating an Extension ===== |
This article assumes the user is comfortable at the command line. Using these instructions, | This article assumes the user is comfortable at the command line. Using these instructions, | ||
- | * create temporary files and directories | + | * create temporary files and directories |
- | * output the final files to a temp directory | + | * output the final files to a temp directory |
- | * use make and squash file tools | + | * use make and squash file tools |
- | Required: | + | Required: |
- | * Your source code and all dependencies | + | * Your source code and all dependencies |
- | * compiletc extension | + | * compiletc extension |
- | * squash file tools extension | + | * squash file tools extension |
- | ======Choosing an Extension name====== | + | ===== Choosing an Extension name ===== |
+ | Please take care while choosing extension names. eg: Be aware of those using FAT filesystem (see [[http:// | ||
- | Please take care with choosing extension names. eg Be aware of those using FAT filesystem see http:// | ||
+ | ===== Required info ===== | ||
+ | * The package maintainers (JW in particular) use the forum to post the most recent extension creation guidelines. You need to read the [[http:// | ||
+ | * For information on creating icons, menu entries, setup scripts, .info and .dep files, please see [[iconmenuinfo]]. | ||
+ | * Packaging kernel modules: [[http:// | ||
+ | * Tiny Core v2.4+ uses extensions in .tcz format. Other formats are deprecated. | ||
+ | * Tiny Core v2.7+ only uses the .tcz extension. There are no filename extension variants. If you don't know what that means, be thankful. Just create files ending in tcz. | ||
- | ===== Required info ===== | + | ===== Abbreviated steps ===== |
- | + | The Big Steps: | |
- | * The package maintainers (JW in particular) use the forum to post the most recent extension creation guidelines. You need to read the [[http:// | + | - configure/ |
- | * For information on creating icons, menu entries, setup scripts, .info and .dep files, please see [[iconmenuinfo]]. | + | - separate out docs, locale info, and development files |
- | * Packaging kernel modules: [[http:// | + | - include a copyright/ |
- | * Tiny Core v2.4+ uses extensions in .tcz format. Other formats are deprecated. | + | - squash up everything into your extension(s) |
- | * Tiny Core v2.7+ only uses the .tcz extension. There are no filename extension variants. If you don't know what that means ... be thankful. Just create files ending in tcz. | + | - write & place support files: dep, info, list, and md5 hash |
- | + | - bcrypt/tar it all | |
- | ===== Abbreviated steps ===== | + | - email it to the Tiny Core Team |
- | + | ||
- | The Big Steps: | + | |
- | - configure/ | + | |
- | - separate out docs, locale info, and development files | + | |
- | - include a copyright/ | + | |
- | - squash up everything into your extension(s) | + | |
- | - write & place support files: dep, info, list, and md5 hash | + | |
- | - bcrypt/tar it all | + | |
- | - email it to the Tiny Core Team | + | |
Much can be scripted and the payoff is well worth it. For instance, steps 3-6 can be automated with [[http:// | Much can be scripted and the payoff is well worth it. For instance, steps 3-6 can be automated with [[http:// | ||
+ | < | ||
+ | *.so* -> main extension (after --strip-unneeded)</ | ||
+ | **Note** *.la should not be used in the dev extension anymore. See [[http:// | ||
- | < | + | ===== Installing ===== |
- | *.a *.h *.la *.m4 *.pc -> dev extension (after --strip-debug) | + | Before you begin, please do not have any build depend tczs like compiletc, lib* or *dev files ondemand. All depends for building need to be loaded thru onboot or manually such as |
- | *.so* -> main extension (after --strip-unneeded) | + | < |
- | </ | + | This means you do not not need to adjust your onboot list, but can use the APPS panel to download (only) packages and then install them when you need them. |
- | + | ||
- | ===== Installing ===== | + | |
- | Before you begin, please do **not** have any build depend tczs like compiletc, lib* or *dev files ondemand. All depends for building need to be loaded thru onboot or manually such as | + | |
- | + | ||
- | < | + | |
- | tce-load -i package | + | |
- | </ | + | |
- | + | ||
- | This means you do not not need to adjust your onboot list, but can use the APPS panel to download (only) packages and then install them when you need them | + | |
Use the compiletc extension when compiling your source - it includes the most common tools, all set up for tc (gcc, make, etc). If you are getting strange make errors, try the coreutils extension. Tar errors? Get the tar extension. And so on. | Use the compiletc extension when compiling your source - it includes the most common tools, all set up for tc (gcc, make, etc). If you are getting strange make errors, try the coreutils extension. Tar errors? Get the tar extension. And so on. | ||
- | + | Please note that the standard install prefix for TC is /usr/local | |
- | Please note that the standard install prefix for TC is **/usr/local** | + | |
Suggested compiler flags on x86 (for compatibility): | Suggested compiler flags on x86 (for compatibility): | ||
- | + | <code bash> | |
- | <code bash> | + | |
- | export CFLAGS=" | + | |
export CXXFLAGS=" | export CXXFLAGS=" | ||
- | export LDFLAGS=" | + | export LDFLAGS=" |
- | </ | + | It is OK to use lower architectures in -march and -mtune than the recommended(-march=i386, |
- | It is OK to use lower architectures in -march and -mtune than the recommended(-march=i386 | + | it is not OK to use higher architectures in -march and not recommended to use higher architectures in -mtune (eg. -march=i586). |
+ | If you get an error about -Wl you can omit it. You might be able to specify a different -O value to LDFLAGS and you might be able to use " | ||
+ | but that may only work for " | ||
- | Suggested compiler flags on x86_64 (for compatibility; | + | Suggested compiler flags on x86_64 (for compatibility; |
- | <code bash> | + | <code bash> |
- | export CFLAGS=" | + | |
export CXXFLAGS=" | export CXXFLAGS=" | ||
- | export LDFLAGS=" | + | export LDFLAGS=" |
- | </ | + | |
+ | Again, //-pipe// isn't necessary. If you get an error about " | ||
- | Suggested compiler flags on RPi (discussed in [[http:// | + | Suggested compiler flags on RPi (discussed in this forum thread): |
- | <code bash> | + | <code bash> |
- | export CFLAGS=" | + | |
export CXXFLAGS=" | export CXXFLAGS=" | ||
- | export LDFLAGS=" | + | export LDFLAGS=" |
- | </ | + | |
+ | Again, //-pipe// isn't necessary. If you get an error about " | ||
If you wish to try to get a lower sized C++ app, you can try adding " | If you wish to try to get a lower sized C++ app, you can try adding " | ||
- | |||
For apps that do not use threads (pthread_cancel), | For apps that do not use threads (pthread_cancel), | ||
- | + | For apps that need speed (math library or so), you can use " | |
- | For apps that need speed (math library or so), you can use " | + | It gives smaller binaries than " |
Flags Not-allowed (good performance, | Flags Not-allowed (good performance, | ||
- | <code bash>-march=native -mtune=native</ | + | -march=native -mtune=native |
- | On x86_64, | + | On x86_64, Juanito has suggested that additional flags may help reduce size, but this may break some builds: |
- | < | + | |
CC=" | CC=" | ||
CXX=" | CXX=" | ||
- | </ | ||
- | |||
- | Please refer to [[http:// | ||
+ | Please refer to http:// | ||
Setting pkg-config paths via " | Setting pkg-config paths via " | ||
Example steps to configure and compile a package_name.tar.bz2: | Example steps to configure and compile a package_name.tar.bz2: | ||
- | + | <code bash>tar xjvf package_name.tar.bz2 | |
- | <code bash> | + | |
- | tar xjvf package_name.tar.bz2 | + | |
cd package_name | cd package_name | ||
./configure --prefix=/ | ./configure --prefix=/ | ||
- | make -j3 | + | make -j3</ |
- | </ | + | |
- | Note: " | + | Note: " |
+ | unless you are on a system that supports hyperthreading (which means that the each of the physical processors acts like 2 virtual processors | ||
+ | [because the processor does multitasking and so can run 2 processes "at once" | ||
+ | If your system uses hyperthreading, | ||
Create/ | Create/ | ||
- | + | <code bash> | |
- | <code bash> | + | |
- | touch /tmp/mark | + | |
- | </ | + | |
Install the application: | Install the application: | ||
- | <code bash> | ||
make DESTDIR=/ | make DESTDIR=/ | ||
- | </ | + | |
- | + | ||
- | (see below, "When DESTDIR Fails" if needed.) | + | |
- | + | ||
- | Note: some packages support "make install-strip", | + | |
- | <code bash> | + | Note: some packages support "make install-strip", |
- | find . | xargs file | grep " | + | <code bash> |
- | </ | + | |
Run these on your package directory tree before you tar it up. | Run these on your package directory tree before you tar it up. | ||
- | ===== All extension creators please note ===== | + | ==== All extension creators please note ==== |
+ | If you don't need a startup script, then skip the next section. The TC system will create empty tce.installed/ | ||
- | If you don't need a startup script, then skip the next section. The TC system will create empty tce.installed/ | + | gutmensch provides the following set of rules: |
- | + | ||
- | == gutmensch provides the following set of rules: | + | |
* Tiny Core special settings, e.g. root:staff for / | * Tiny Core special settings, e.g. root:staff for / | ||
* Shared object lib files (end in .so or .so*) are classified as executables | * Shared object lib files (end in .so or .so*) are classified as executables | ||
Line 138: | Line 110: | ||
* All files root:root, 644 for files, 755 for executables, | * All files root:root, 644 for files, 755 for executables, | ||
* Special settings varying on the software, | * Special settings varying on the software, | ||
- | | + | |
- | * ----special user like postfix or mysql, etc. within the extension or setup with the tce.installed/ | + | * special user like postfix or mysql, etc. within the extension or setup with the tce.installed/ |
* [/ | * [/ | ||
- | | + | |
- | Most of the time(but not always) this is done automatically by the install script. | + | |
- | Optional: | + | Most of the time(but not always) this is done automatically by the install script. |
- | * If app/service can be run as a normal user (not as root!), make sure your init, start or extensions scripts | + | |
- | * ---are able to handle | + | |
- | * ---installing the extension. Or reconfigure | + | |
+ | ==== Optional ==== | ||
+ | * If app/service can be run as a normal user (not as root!), make sure your init, start or extensions scripts | ||
+ | * are able to handle this. For example, query the $TCUSER variable and set the permissions accordingly when | ||
+ | * installing the extension. Or reconfigure the software so that it defaults to user writable directories like $HOME, /tmp, etc. | ||
- | == @cups example: | + | @cups example: |
- | | + | Unordered List ItemSince the service is run as root either way, the init script should also fail when not run as root, which is the easiest solution. |
- | | + | Checkout the checkroot() helper function in / |
- | reference | + | |
- | + | ||
- | ===== Adding Custom Startup Scripts ===== | + | |
- | + | ||
- | If your software needs a startup script then create the folder for it | + | |
- | + | ||
- | <code bash> | + | |
- | mkdir -p / | + | |
- | </ | + | |
- | + | ||
- | Next, create script as / | + | |
- | + | ||
- | A good pattern to follow would be to first rename / | + | |
+ | ==== Adding Custom Startup Scripts ==== | ||
+ | If your software needs a startup script then create the folder for it | ||
+ | <code bash> | ||
+ | Next, create script as **/ | ||
+ | A good pattern to follow would be to first rename **/ | ||
e.g.: | e.g.: | ||
- | < | + | < |
- | cd / | + | Warning: If you don't do this now, these configuration files would be read-only. Please read iconmenuinfo wiki page for more information on creating wbar icons, menu entries, setup scripts, .info and .dep files. |
- | </ | + | Warning: Please make sure that your script does NOT depend on the existence of files located at / |
- | **Warning**: | + | Next, follow |
+ | <code bash> | ||
+ | sudo chmod -R 775 /tmp/ | ||
- | **Warning**: | + | Watch out for persistence. If your startup |
- | Next, follow these commands to make script executable and with correct permissions. | + | Extra steps may also be needed see [[iconmenuinfo|link]] |
- | <code bash> | ||
- | sudo chown -R root:staff / | ||
- | sudo chmod -R 775 / | ||
- | </ | ||
- | Watch out for persistence--If your startup script is creating | + | ===== License ===== |
+ | Please check the license condition. Although we can strip a number of documents from the main tcz and have a separate doc.tcz, this is not always possible. eg if you see a file called COPYING and it has a section like this: | ||
+ | < | ||
+ | Please create and copy the relevant file, eg: | ||
+ | <code bash> | ||
+ | cp -f COPYING / | ||
- | ===== Extra steps may also be needed see link ===== | + | ===== Creating a .tcz ===== |
+ | If the program supports DESTDIR (most do) the files will be installed in / | ||
+ | <code bash>cd /tmp | ||
+ | mksquashfs package program_name.tcz | ||
+ | cd / | ||
- | [[wiki:iconmenuinfo]] | + | Next create the list of files in the extension, it will be submitted with the extension: |
+ | <code bash> | ||
- | ===== License ===== | + | As a final step, remove the packed files from / |
+ | <code bash>rm -rf usr</ | ||
- | Please check the **license** condition. Although we can strip a number | + | ===== When DESTDIR Fails ===== |
+ | Just about all applications support | ||
+ | One possible solution | ||
+ | As above, set the ./configure installation prefix as normal. Then be sure to create | ||
+ | <code bash> | ||
+ | make | ||
+ | touch /tmp/mark #in case DESTDIR fails | ||
+ | make install DESTDIR=/ | ||
+ | find /usr/local -newer /tmp/mark -not -type d > /tmp/list | ||
+ | tar -T /tmp/list -czvf / | ||
- | < | + | For TC newer than 2.4, you will need to unzip the tar file, and then use mksquashfs to create your extension: |
- | The above copyright notice and this permission notice (including | + | < |
- | </ | + | cd /tmp/pkg |
+ | tar -xf / | ||
+ | cd /tmp | ||
+ | mksquashfs pkg/ someapp.tcz</ | ||
- | Please create and copy the relevant file, eg: | + | Be careful using touch/find -newer method. There are files just copied by installer from the source package, like configuration files, header files, scripts, doc files, images, etc. with original date, therefore they are not detected. Check installer messages! |
- | < | + | ===== Testing ===== |
- | mkdir -p / | + | Test out your new extension(s) by manually loading them after booting TC with the cheatcodes: |
- | cp -f COPYING / | + | < |
- | </ | + | |
- | ===== Creating a .tcz ===== | + | Load your extension, and check: |
+ | * all dependencies loaded? | ||
+ | * menu item works? wbar/ | ||
+ | * program actually runs? | ||
- | If the program supports DESTDIR (most do) the files will be installed | + | It is easy to leave out a required dependency from your .dep file. Do use base norestore, and check the dependencies |
+ | If you are planning on submitting your extension for inclusion in the repository, you should run the extension | ||
- | <code bash> | + | ===== Separation ===== |
- | cd /tmp | + | Smaller extensions reduce ' |
- | mksquashfs package program_name.tcz | + | * move translations and other locale data into a locale extension (myprogram-locale.tcz) |
- | cd / | + | * move documentation and help files into a doc extension (myprogram-doc.tcz) |
- | </ | + | * rather than including docs in your extension, use the info file to list official online docs. |
- | + | ||
- | Next create the list of files in the extension, it will be submitted with the extension: | + | |
- | + | ||
- | <code bash> | + | |
- | find usr -not -type d > program_name.tcz.list | + | |
- | </ | + | |
- | + | ||
- | As a final step, remove the packed files from / | + | |
- | + | ||
- | <code bash> | + | |
- | rm -rf usr | + | |
- | </ | + | |
- | + | ||
- | ===== When DESTDIR Fails ===== | + | |
- | + | ||
- | Just about all applications support the use of DESTDIR on the make line (as above). There are those that don't, however. If your application does not support DESTDIR, it will likely install into subdirectories of root, rather than tmp. | + | |
- | + | ||
- | [[http:// | + | |
- | + | ||
- | As above, set the ./configure installation prefix as normal. Then be sure to create a time stamp after make, but do it just before make install. Use find to list all the newly installed files, and then gather those files up using tar. | + | |
- | + | ||
- | <code bash> | + | |
- | ./configure --prefix=/ | + | |
- | make | + | |
- | touch /tmp/mark #in case DESTDIR fails | + | |
- | make install DESTDIR=/ | + | |
- | find /usr/local -newer /tmp/mark -not -type d > /tmp/list | + | |
- | tar -T /tmp/list -czvf / | + | |
- | </ | + | |
- | + | ||
- | For TC past 2.4, you will need to unzip the tar file, and then use mksquashfs to create your extension: | + | |
- | + | ||
- | <code bash> | + | |
- | mkdir /tmp/pkg | + | |
- | cd /tmp/pkg | + | |
- | tar -xf / | + | |
- | cd /tmp | + | |
- | mksquashfs pkg/ someapp.tcz | + | |
- | </ | + | |
- | + | ||
- | Be careful using touch/find -newer method. There are files just copied by installer from the source package, like configuration files, header files, scripts, doc files, images, etc. with original date, therefore they are not detected. Check installer messages! | + | |
- | + | ||
- | ===== Testing ===== | + | |
- | + | ||
- | Test out your new extension(s) by manually loading them after booting TC with the cheatcodes: | + | |
- | + | ||
- | ^base norestore^ | + | |
- | + | ||
- | Load your extension, and check: | + | |
- | - all dependencies loaded? | + | |
- | - menu item works? wbar/ | + | |
- | - program actually runs? | + | |
- | + | ||
- | It is easy to leave out a required dependency from your .dep file. Do use base norestore, and check the dependencies in particular. | + | |
- | + | ||
- | If you are planning on submitting your extension for inclusion in the repository, | + | |
- | ===== | + | |
- | + | ||
- | Smaller extensions reduce ' | + | |
- | * move translations and other locale data into a locale extension (myprogram-locale.tcz) | + | |
- | * move documentation and help files into a doc extension (myprogram-doc.tcz) | + | |
- | * rather than including docs in your extension, use the info file to list official online docs. | + | |
* move headers and static libraries to a dev extension(myprogram-dev.tcz) | * move headers and static libraries to a dev extension(myprogram-dev.tcz) | ||
- | ===== Required Files ===== | + | ===== Required Files ===== |
- | + | Submissions must include: | |
- | Submissions must include: | + | * the extension file (.tcz) |
- | * the extension file (.tcz) | + | * a list of its contents (.tcz.list) |
- | * a list of its contents (.tcz.list) | + | * an md5 sum (.tcz.md5.txt) |
- | * an md5 sum (.tcz.md5.txt) | + | * an info file describing its contents (.tcz.info) - this content is standardized. Visit the repository for examples(The link is to the 8.x repository. If you have a different version, follow the link, and then replace 8.x with whatever version you have[but only the major release eg. 7.x 9.x, not the minor release eg. 8.0, 7.2]). Also see the example below. |
- | * an info file describing its contents (.tcz.info) - this content is standardized. | + | * a dependency list, if necessary (.tcz.dep) |
- | * a dependency list, if necessary (.tcz.dep) | + | * If the source is under the GPL license, include the source as well. |
- | * If the source is under the GPL license, include the source as well. | + | |
* a .tcz.zsync (autogenerated by submitqc) | * a .tcz.zsync (autogenerated by submitqc) | ||
- | It is not required, but certainly recommended, | + | It is not required, but certainly recommended, |
+ | < | ||
+ | Xorg-7.4-dev | ||
+ | Xlibs_support | ||
- | < | + | Notes: |
- | Required extensions to build: | + | 256-color patch applied |
- | Xorg-7.4-dev | + | |
- | Xlibs_support | + | |
- | Notes: | + | Additional configure options: |
- | 256-color patch applied | + | |
+ | * -with-codesets=none | ||
+ | * -disable-afterimage | ||
+ | * -disable-xterm-scroll | ||
+ | * -disable-next-scroll | ||
+ | * -disable-perl</ | ||
- | Additional configure options: | + | This is just an example, and the format can be however you desire. Again, this is not required, but is a helpful practice, as it will help if you update the extension for a new release. |
- | * -enable-xft | + | |
- | * -with-codesets=none | + | |
- | * -disable-afterimage | + | |
- | * -disable-xterm-scroll | + | |
- | * -disable-next-scroll | + | |
- | * -disable-perl | + | |
- | </ | + | |
- | This is just an example, and the format can be however you desire. Again, this is not required, but is a helpful practice, as it will help if you update the extension for a new release. | + | ===== .tcz.info example ===== |
- | + | < | |
- | ===== .tcz.info example===== | + | Description: |
- | + | Version: | |
- | < | + | Author: |
- | Title: | + | Original-site: |
- | Description: | + | Copying-policy: |
- | Version: | + | Size: 100K (of the package) |
- | Author: | + | Extension_by: |
- | Original-site: | + | Tags: tag1 tag2 tag3 ... |
- | Copying-policy: | + | Comments: |
- | Size: 100K (of the package) | + | for those who will be use this package. |
- | Extension_by: | + | ---- |
- | Tags: tag1 tag2 tag3 ... | + | Compiled for TC 4.x |
- | Comments: | + | ---- |
- | for those who will be use this package. | + | |
- | ---- | + | |
- | Compiled for TC 4.x | + | |
- | ---- | + | |
PPI Compatible | PPI Compatible | ||
Change-log: | Change-log: | ||
- | 2012/01/01 Short change description | + | 2012/01/01 Short change description |
- | Current: | + | Current: |
- | </ | + | |
- | If the package contains a program, the best choice for its name is the bin name (this will ensure that program start directly if you load package ondemand[but you need to make an executable shell script usr/local/tcz.installed/< | + | If the package contains a program, the best choice for its name is the bin name (this will ensure that program start directly if you load package ondemand [but you need to make an executable shell script usr/local/tce.installed/< |
+ | In field " | ||
- | In field " | + | ===== DAEMONS ===== |
+ | Please show //full pathways// to start daemons in your info file. TC does not condone starting daemons in your tce.install script. | ||
+ | < | ||
- | **DAEMONS** | + | ===== .tcz.dep example ===== |
+ | If submitting a package called fruit.tcz your depend should be a simple list of main dependencies, | ||
+ | Right example: <file dep fruit.tcz.dep> | ||
+ | apple.tcz | ||
+ | banana.tcz</ | ||
- | Please show full pathways to start daemons in your info file. TC does not condone starting daemons in your tce.install script. | + | Wrong example: <file dep fruit.tcz.dep> |
- | + | ||
- | eg | + | |
- | $ sudo / | + | |
- | + | ||
- | ===== .tcz.dep example ===== | + | |
- | + | ||
- | If submitting a package called fruit.tcz your depend should be a simple list of main dependencies, | + | |
- | + | ||
- | Right example: | + | |
- | + | ||
- | <code> | + | |
apple.tcz | apple.tcz | ||
- | banana.tcz | + | chemicals.tcz |
- | </code> | + | banana.tcz</file> |
+ | If package has no dependencies, | ||
- | Wrong example: | + | ===== Submitting ===== |
+ | Have you run the extension audit script (// | ||
+ | If so, create a gzip archive. For example, if all the required files are in one directory, the command would look like this: | ||
+ | <code bash>tar zcf extension.tar.gz *</ | ||
+ | Or, alternatively, | ||
+ | <code bash>tar -cf extension.tar *.tcz* | ||
+ | gzip -9 extension.tar</ | ||
+ | Our email provider sometimes blocks emails with .tar or .tar.gz attachments, | ||
+ | <code bash> | ||
+ | Encryption key: tinycore</ | ||
- | < | + | Send the resulting extension.tar.gz.bfe file to **tcesubmit @ gmail ... com** (without spaces or extra periods.) |
- | apple.tcz | + | |
- | chemicals.tcz | + | |
- | banana.tcz | + | |
- | </ | + | |
- | If package has **no dependencies** do not submit any file but in email please alert tcz checker that there are no dependencies. You can also create an empty .tcz.dep file if your extension has no dependencies. | + | For piCore (Raspberry Pi) extensions send it to **picoresubmit @ gmail ... com** (without spaces or extra periods.) |
- | ===== Submitting ===== | + | For more details, read the submission guidelines thread. |
- | Have you run the extension audit script(submitqcx[where x is the major release of tinycore that you have] or submitqc) | + | Gmail currently limits attachments |
- | <code bash> | ||
- | tar zcf extension.tar.gz * | ||
- | </ | ||
- | Or, alternatively, | ||
- | |||
- | <code bash> | ||
- | tar -cf extension.tar *.tcz* | ||
- | gzip -9 extension.tar | ||
- | </ | ||
- | |||
- | Send the resulting extension.tar.gz file to **tcesubmit _at_ gmail _dot_ com**. | ||
- | |||
- | For piCore (Raspberry Pi) extensions send it to **picoresubmit _at_ gmail _dot_ com**. | ||
- | |||
- | Files part of an extension package are Gmail neutral and accepted for delivery, no need to encrypt. | ||
- | |||
- | Gmail currently limits attachments to 25 Mb per email. |