mirror of
https://github.com/google/pebble.git
synced 2025-03-26 05:09:05 +00:00
227 lines
7 KiB
Markdown
227 lines
7 KiB
Markdown
|
---
|
||
|
# Copyright 2025 Google LLC
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
|
||
|
title: Tips and Tricks - Platform-specific C File Set
|
||
|
author: chrislewis
|
||
|
tags:
|
||
|
- Beautiful Code
|
||
|
---
|
||
|
|
||
|
In
|
||
|
[the last Tips and Tricks blog post](/blog/2015/05/13/tips-and-tricks-transparent-images/)
|
||
|
we looked at drawing transparent images on both the Aplite and Basalt platforms.
|
||
|
|
||
|
This time around, we will look at a `wscript` modification that can allow you to
|
||
|
build a Pebble project when you have two completely separate sets of C source
|
||
|
files; one set for Aplite, and another for Basalt.
|
||
|
|
||
|
Note: This technique can be applied only to local SDK projects, where access to
|
||
|
`wscript` is available. This means that it cannot be used in CloudPebble
|
||
|
projects.
|
||
|
|
||
|
|
||
|
|
||
|
> Update 05/20/15: There was an error in the JS code sample given at the end of
|
||
|
> this post, which has now been corrected.
|
||
|
|
||
|
## The Preprocessor Approach
|
||
|
|
||
|
In the [3.0 Migration Guide](/sdk/migration-guide/#backwards-compatibility) we
|
||
|
recommend using preprocessor directives such as `PBL_PLATFORM_APLITE` and
|
||
|
`PBL_PLATFORM_BASALT` to mark code to be compiled only on that particular
|
||
|
platform. This helps avoid the need to maintain two separate projects for one
|
||
|
app, which is especially convenient when migrating a 2.x app to the Basalt
|
||
|
platform.
|
||
|
|
||
|
```c
|
||
|
#ifdef PBL_PLATFORM_APLITE
|
||
|
// Aligns under the status bar
|
||
|
layer_set_frame(s_layer, GRect(0, 0, 144, 68));
|
||
|
#elif PBL_PLATFORM_BASALT
|
||
|
// Preserve alignment to status bar on Aplite
|
||
|
layer_set_frame(s_layer, GRect(0, STATUS_BAR_LAYER_HEIGHT, 144, 68));
|
||
|
#endif
|
||
|
```
|
||
|
|
||
|
This is a good solution for small blocks of conditional code, but some
|
||
|
developers may find that complicated conditional code can soon become more
|
||
|
`#ifdef...#elif...#endif` than actual code itself!
|
||
|
|
||
|
|
||
|
## The Modified Wscript Approach
|
||
|
|
||
|
In these situations you may find it preferable to use a different approach.
|
||
|
Instead of modifying your app code to use preprocessor statements whenever a
|
||
|
platform-specific value is needed, you can modify your project's `wscript` file
|
||
|
to limit each compilation pass to a certain folder of source files.
|
||
|
|
||
|
By default, you will probably have a project with this file structure:
|
||
|
|
||
|
```text
|
||
|
my_project
|
||
|
resources
|
||
|
images
|
||
|
banner~bw.png
|
||
|
banner~color.png
|
||
|
src
|
||
|
main.c
|
||
|
util.h
|
||
|
util.c
|
||
|
appinfo.json
|
||
|
wscript
|
||
|
```
|
||
|
|
||
|
In this scenario, the `wscript` dictates that *any* `.c` files found in `src`
|
||
|
will be compiled for both platforms.
|
||
|
|
||
|
To use a different set of source files for each platform during compilation,
|
||
|
modify the lines with the `**` wildcard (within the `for` loop) to point to a
|
||
|
folder within `src` where the platform- specific files are then located:
|
||
|
|
||
|
```python
|
||
|
for p in ctx.env.TARGET_PLATFORMS:
|
||
|
ctx.set_env(ctx.all_envs[p])
|
||
|
ctx.set_group(ctx.env.PLATFORM_NAME)
|
||
|
app_elf='{}/pebble-app.elf'.format(ctx.env.BUILD_DIR)
|
||
|
|
||
|
# MODIFY THIS LINE!
|
||
|
# E.g.: When 'p' == 'aplite', look in 'src/aplite/'
|
||
|
ctx.pbl_program(source=ctx.path.ant_glob('src/{}/**/*.c'.format(p)), target=app_elf)
|
||
|
|
||
|
if build_worker:
|
||
|
worker_elf='{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR)
|
||
|
binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf})
|
||
|
|
||
|
# MODIFY THIS LINE!
|
||
|
# Also modify this line to look for platform-specific C files in `worker_src`
|
||
|
ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/{}/**/*.c'.format(p)), target=worker_elf)
|
||
|
|
||
|
else:
|
||
|
binaries.append({'platform': p, 'app_elf': app_elf})
|
||
|
```
|
||
|
|
||
|
With this newly modified `wscript`, we must re-organise our `src` folder to
|
||
|
match the new search pattern. This allows us to maintain two separate sets of
|
||
|
source files, each free of any excessive `#ifdef` pollution.
|
||
|
|
||
|
```text
|
||
|
my_project
|
||
|
resources
|
||
|
images
|
||
|
banner~bw.png
|
||
|
banner~color.png
|
||
|
src
|
||
|
aplite
|
||
|
main.c
|
||
|
util.h
|
||
|
util.c
|
||
|
basalt
|
||
|
main.c
|
||
|
util.h
|
||
|
util.c
|
||
|
appinfo.json
|
||
|
wscript
|
||
|
```
|
||
|
|
||
|
|
||
|
## Sharing Files Between Platforms
|
||
|
|
||
|
Using the modified wscript approach as shown above still requires any files that
|
||
|
are used on both platforms to be included twice: in the respective folder. You
|
||
|
may wish to reduce this clutter by moving any platform-agnostic files that both
|
||
|
platforms use to a `common` folder inside `src`.
|
||
|
|
||
|
You project might now look like this:
|
||
|
|
||
|
```text
|
||
|
my_project
|
||
|
resources
|
||
|
images
|
||
|
banner~bw.png
|
||
|
banner~color.png
|
||
|
src
|
||
|
aplite
|
||
|
main.c
|
||
|
basalt
|
||
|
main.c
|
||
|
common
|
||
|
util.h
|
||
|
util.c
|
||
|
appinfo.json
|
||
|
wscript
|
||
|
```
|
||
|
|
||
|
To tell the SDK to look in this extra folder during compilation of each
|
||
|
platform, further modify the two lines calling `ctx.pbl_program()` to include
|
||
|
the `common` folder in the array of paths passed to
|
||
|
[`ant_glob()`](https://waf.io/book/#_general_usage). This is shown in the code
|
||
|
snipped below, with unchanged lines ommitted for brevity:
|
||
|
|
||
|
```python
|
||
|
# Additionally modified to include the 'common' folder
|
||
|
ctx.pbl_program(source=ctx.path.ant_glob(['src/{}/**/*.c'.format(p), 'src/common/**/*.c']), target=app_elf)
|
||
|
|
||
|
/* Other code */
|
||
|
|
||
|
if build_worker:
|
||
|
|
||
|
# Also modify this line to look for common files in '/worker_src/common/'
|
||
|
ctx.pbl_worker(source=ctx.path.ant_glob(['worker_src/{}/**/*.c'.format(p), 'worker_src/common/**/*.c']), target=worker_elf)
|
||
|
|
||
|
else:
|
||
|
|
||
|
/* Other code */
|
||
|
|
||
|
```
|
||
|
|
||
|
|
||
|
## Important Notes
|
||
|
|
||
|
While this new `wscript` allows us to keep our source files for each platform
|
||
|
separated entirely, there are a couple of important limitations to take into
|
||
|
account when using this method (without any further modification):
|
||
|
|
||
|
* There can still be only *one* JavaScript file, in `src/js/pebble-js-app.js`.
|
||
|
You can simulate two JS files using a platform check:
|
||
|
|
||
|
```js
|
||
|
Pebble.addEventListener('ready', function() {
|
||
|
if(Pebble.getActiveWatchInfo && Pebble.getActiveWatchInfo().platform === 'basalt') {
|
||
|
// This is the Basalt platform
|
||
|
console.log('PebbleKit JS ready on Basalt!');
|
||
|
} else {
|
||
|
// This is the Aplite platform
|
||
|
console.log('PebbleKit JS ready on Aplite!');
|
||
|
}
|
||
|
});
|
||
|
```
|
||
|
|
||
|
* Each binary can be bundled with only the app resources required for that
|
||
|
specific platform. To learn how to package app resources with only a certain
|
||
|
platform, read the
|
||
|
[*Platform-specific Resources*](/guides/app-resources/platform-specific/)
|
||
|
guide.
|
||
|
|
||
|
|
||
|
## Conclusion
|
||
|
|
||
|
With this modification to a Pebble project's `wscript`, developers now have two
|
||
|
options when it comes to diverging their app code for Aplite- and Basalt-
|
||
|
specific features **without** the need to maintain two completely separate
|
||
|
projects.
|
||
|
|
||
|
You can see a simple example project that ses all these techniques over at
|
||
|
[`pebble-examples/multi-platform-wscript`]({{site.links.examples_org}}/multi-platform-wscript).
|