Compare commits

...

505 Commits

Author SHA1 Message Date
Miku AuahDark 4c65fff4f8 Remove some legacy options after Gradle migration. 2026-07-25 15:31:40 +08:00
Miku AuahDark fe15119efc Update Gradle and AGP to 9.5 and 9.3.1. 2026-07-25 13:43:26 +08:00
Miku AuahDark ceae396832 Update LOVE to love2d/love@792690b. 2026-07-25 13:12:42 +08:00
Miku AuahDark 5d8800f138 Update megasource to love2d/megasource@5118c13. 2026-07-25 13:06:00 +08:00
Sasha Szpakowski 3fb8ead63d update megasource submodule. 2026-06-30 19:58:24 -03:00
Sasha Szpakowski dd6a211cdc Update LOVE submodule. 2026-06-30 19:33:00 -03:00
Miku AuahDark 007d258cb4 Add CMake minimum policy version to build.gradle
If user is compiling with CMake 4, ensure it doesn't fail.

Issue #300.
2026-02-16 09:01:46 +08:00
Miku AuahDark b375d142fd Update LOVE submodule. 2026-01-08 11:02:13 +08:00
Miku AuahDark 871ceb314d Update AGP to 8.13.2. 2026-01-08 09:45:31 +08:00
Miku AuahDark 4290c0b614 Update submodules. 2025-11-07 18:44:16 +08:00
Miku AuahDark 39bdc40087 Update LOVE submodule. 2025-06-30 15:54:30 +08:00
Miku AuahDark 9bdd400b00 Disable precompiled headers across the whole project.
This cause some intermittent build errors.
2025-06-30 13:36:04 +08:00
Miku AuahDark 12430bf8a7 Update LOVE submodule. 2025-01-30 19:16:43 +08:00
Miku AuahDark bb2e250575 Update Megasource. 2025-01-30 12:20:01 +08:00
Miku AuahDark d0f7ff7085 Update LOVE submodule. 2025-01-30 12:10:51 +08:00
Miku AuahDark 85ac733fa4 Use ordinary content:// protocol instead of love2d://. 2025-01-16 17:20:35 +08:00
Miku AuahDark 3ad966dbe7 Update LOVE submodule. 2024-12-31 14:46:22 +08:00
Miku AuahDark fa88c64ceb Update submodules. 2024-12-28 11:05:12 +08:00
Miku AuahDark 9b340ae150 Update build.gradle dependencies. 2024-12-28 11:04:11 +08:00
Miku AuahDark b0420d94ca Update submodules. 2024-12-15 12:19:42 +08:00
Miku AuahDark 18d3e8e7cb Change git submodule branch. 2024-11-04 00:57:54 +08:00
Miku AuahDark dcd27223bf Fix game loading through game selector. 2024-10-13 14:11:40 +08:00
Miku AuahDark f585f05839 Update to SDL3 and target Android 15.
Currently game selection (the "LOVE Loader") equivalent is currently broken, but it will be addressed in future cleanup.
2024-10-13 12:35:42 +08:00
Miku AuahDark e8e3eb3d1a Update Megasource. 2024-10-13 12:34:46 +08:00
Miku AuahDark 44b0650f14 Update LOVE submodule. 2024-10-13 10:58:21 +08:00
Miku AuahDark d99f8ce8a5 Update Megasource and LOVE submodule. 2024-10-12 18:50:09 +08:00
Miku AuahDark 5ba547b0cc Update AGP to 8.7.0 and Gradle to 8.9. 2024-10-12 13:04:59 +08:00
Miku AuahDark ba5dad82ba Update NDK and Gradle lib dependencies. 2024-10-12 12:10:16 +08:00
Miku AuahDark d442728e01 Update LOVE submodule. 2024-06-23 19:34:56 +08:00
Miku AuahDark b09380d98b Remove Java function GameActivity.openURLFromLOVE()
SDL_OpenURL() is now used instead.
2024-06-21 10:46:35 +08:00
Miku AuahDark b128cb6067 Update LOVE submodule. 2024-06-21 10:46:18 +08:00
Miku AuahDark 0a81d4e4ea Bump minimum OpenGLES version from 2.0 to 3.0. 2024-06-20 16:29:54 +08:00
Miku AuahDark 9bcd419d92 Update LOVE submodule. 2024-06-20 16:29:00 +08:00
Miku AuahDark 46583c9fce Update Megasource and LOVE submodule. 2024-06-18 11:52:42 +08:00
Miku AuahDark cf9a5311c7 Add Vulkan 1.1 feature manifest. 2024-04-27 12:48:06 +08:00
Miku AuahDark 30a2dafd69 Update LOVE submodule. 2024-04-27 12:43:08 +08:00
Miku AuahDark 7a5c5eb507 Update Megasource and LOVE. 2024-04-24 17:01:07 +08:00
Miku AuahDark 50192f4e4a Additionally load libliblove.so before loading liblove.so after CMake modernization.
https://github.com/love2d/love/pull/2036#pullrequestreview-1967673996
2024-03-31 12:44:13 +08:00
Miku AuahDark 7efdfefe74 Update megasource and love. 2024-03-31 12:43:59 +08:00
Miku AuahDark ce70a64606 Ensure app/src/embed/assets directory is available when cloning the repository. 2024-03-20 11:29:30 +08:00
Miku AuahDark abfd0a7021 Update LOVE submodule.
Fixed `love.graphics.newVideo` failing on Adreno GPUs.
2024-03-18 10:50:04 +08:00
Miku AuahDark 28f7c4a8db Don't set the intent to null, only set the intent data to null.
Cherry-picked from d1f74df686. Closes #268.
2024-03-18 10:49:39 +08:00
Miku AuahDark c73f7fec23 Change the GRADLE_OPTS to alleviate out of memory errors when compiling. 2024-03-16 11:04:53 +08:00
Miku AuahDark 7fd649271a Workaround Java out of memory error. 2024-02-23 13:24:22 +08:00
Miku AuahDark 8b72016703 Fix debug symbol artifact. 2024-02-23 11:44:47 +08:00
Miku AuahDark aab23aded7 Update LOVE and Megasource submodule. 2024-02-23 11:32:39 +08:00
Miku AuahDark 590f733790 Drop support for 32-bit x86 Android.
32-bit x86 Android is declining rapidly and it's possible that future Android NDK will drop this architecture (android/ndk#1772).

Also related issue: love2d/love#1889.
2024-02-23 11:28:39 +08:00
Miku AuahDark 9da3e56c43 Update actions/checkout and actions/upload-artifact to v4. 2024-02-16 10:24:58 +08:00
Miku AuahDark 1a4915b48a Separate debug and release APK build to reduce CI build times. 2024-02-16 10:23:55 +08:00
Miku AuahDark 6e3b44e1cc Update LOVE submodule. 2024-02-13 13:24:05 +08:00
Miku AuahDark 288949e493 Merge remote-tracking branch 'upstream/main' into 12.x 2024-02-13 12:56:05 +08:00
Miku AuahDark 860c109861 Update coypright year. 2024-02-13 10:18:48 +08:00
Miku AuahDark e74a9ef791 Update LOVE 11.x submodule. 2024-02-13 10:18:17 +08:00
Miku AuahDark 46e7d9da0e Update copyright year. 2024-01-27 00:54:45 +08:00
Miku AuahDark fe8df53097 Update fastlane changelog. 2024-01-27 00:44:07 +08:00
Miku AuahDark 10f65a4302 Merge branch 'ClockGen-fastlane' into 12.x-testmerge 2024-01-27 00:26:38 +08:00
Miku AuahDark 4394603ed7 Update Megasource and LOVE submodule. 2024-01-27 00:24:31 +08:00
Miku AuahDark 7163a2480a Bump minimum Android version and Android NDK version.
* Minimum Android version is now Android 6.
* NDK 26.1.10909125 is now used.
2024-01-26 23:57:47 +08:00
Miku AuahDark a712164440 Minor reformat and fix. 2024-01-26 23:18:54 +08:00
Miku AuahDark fc6053974f Merge tag '11.5a' into 12.x-testmerge 2024-01-26 18:23:45 +08:00
fruitsnack 71fcddfbe5 Added initial fastlane structure 2024-01-19 11:50:50 +03:00
Miku AuahDark 55feb38fa1 Release 11.5 hotfix 1. 2023-12-29 13:51:37 +08:00
Miku AuahDark 6811eca7d2 Artifact unstripped .so files. 2023-12-29 13:32:16 +08:00
Miku AuahDark d1f74df686 Don't set the intent to null, only set the intent data to null.
Issue #260.
2023-12-25 12:23:18 +08:00
Miku AuahDark c3ed3b454b Sanitize destination filename from content URI.
Fixes #257.
2023-12-23 13:08:00 +08:00
Miku AuahDark 8a3d635cdb LOVE Loader: Add missing FLAG_GRANT_READ_URI_PERMISSION flag. 2023-12-23 12:58:55 +08:00
Miku AuahDark a81931be2c Merge pull request #259 from marclurr/fix-embedding
Fix embedding
2023-12-10 17:57:26 +08:00
Mark 7a0068535b Remove unreachable code 2023-12-09 14:52:26 +00:00
Mark 034a6d6361 initialise needToCopyGameInArchive inside onCreate based on the value
of embed
2023-12-09 12:29:23 +00:00
Miku AuahDark 7a32a370f9 Release 11.5. 2023-12-03 20:46:00 +08:00
Miku AuahDark 8687928a33 Update LOVE submodule. 2023-11-27 12:52:04 +08:00
Miku AuahDark 6d67b15e79 SDL: Disable building Android audio subsystems. 2023-11-25 22:38:28 +08:00
Miku AuahDark ecb5076b3d Update LOVE submodule. 2023-11-25 22:32:44 +08:00
Miku AuahDark 3b80a5a766 Update SDL to 2.28.5. 2023-11-25 22:31:57 +08:00
Miku AuahDark 69cfcd25fb Rebuild LuaJIT for ARMv7 and x86.
Previous build was compiled for Android Lollipop. It must be compiled for Jelly Bean instead.
2023-11-25 22:07:01 +08:00
Miku AuahDark 8bbe71a6bb Add <LuaJIT>/android/<arch> to exported include directories. 2023-11-25 21:49:56 +08:00
Miku AuahDark d9ea1f60a5 Rebuild LuaJIT after 044d5b5. 2023-11-25 21:43:50 +08:00
Miku AuahDark a3b1903250 Use LuaJIT build script from Megasource's 12.x branch. 2023-11-25 21:43:06 +08:00
Miku AuahDark 044d5b5e34 Update LuaJIT to LuaJIT/LuaJIT@43d0a19. 2023-11-25 21:41:59 +08:00
Miku AuahDark abd98a1378 Replace Python script with Unix Shell and Powershell script.
Fixes #246.
2023-11-25 18:04:19 +08:00
Miku AuahDark 86dbfffcfc Restore old behavior of launching LOVE from launcher after ae465f8.
The old behavior is to re-start no-game screen when launching LOVE from app launcher for non-embed builds.
2023-11-15 12:33:41 +08:00
Miku AuahDark b2686d98e5 Update LOVE submodule. 2023-11-15 12:26:52 +08:00
Miku AuahDark 11d99352dc Fixed minor issue with LOVE Loader launcher. 2023-11-15 12:25:48 +08:00
Miku AuahDark f2970f47b1 Potentially fix unexpected "love.filedropped" event when launching .love files.
Issue #254
2023-11-15 11:47:07 +08:00
Miku AuahDark bd7032b56f Update LOVE submodule. 2023-09-28 16:57:26 +08:00
Miku AuahDark 65693ca2ff Fix build failures. 2023-09-28 16:06:20 +08:00
Miku AuahDark 90dd5df090 Add requiresNonNull to LoveDocumentsProvider. 2023-09-28 13:50:15 +08:00
Miku AuahDark 26a45e4372 Workaround Harfbuzz compile error. 2023-09-28 13:46:25 +08:00
Miku AuahDark f73a91c0be Provide option to easily modify app name and version.
Chery-picked from #243.
2023-09-28 13:44:18 +08:00
Miku AuahDark fefb7dfc8d Add null-checking when scanning games. 2023-09-28 13:03:38 +08:00
Miku AuahDark 74f3c935c8 Update dependencies in build.gradle. 2023-09-28 12:18:13 +08:00
Miku AuahDark f9ee72ff77 Update Gradle and AGP to 8.1. 2023-09-28 12:14:12 +08:00
Miku AuahDark 8ef01fed73 Update submodules. 2023-09-28 12:03:50 +08:00
Miku AuahDark 8a882cabc0 Add notice about AGP bug for 3rd-party modules. 2023-09-27 12:48:53 +08:00
Miku AuahDark f7bc09eac0 Update Gradle to 8.1. 2023-09-26 15:59:30 +08:00
Miku AuahDark 8b77791aeb Apply LOVE 11.x-specific patch to SDL2. 2023-09-26 15:49:26 +08:00
Miku AuahDark eac9c7dc6a Update SDL to 2.28.3. 2023-09-26 15:48:40 +08:00
Miku AuahDark d257a3b987 Update compile SDK version and NDK version.
* Target API level 34.

* Update NDK to r25b. This will be the last NDK update to LOVE 11.x as future NDK dropped support for Android KitKat and earlier.
2023-09-26 14:25:00 +08:00
Miku AuahDark af732a0f47 Update LOVE submodule to love2d/love@2deb627. 2023-09-26 13:44:01 +08:00
Miku AuahDark 9b9cc15813 Recompile LuaJIT for Android with debug information. 2023-06-01 15:38:14 +08:00
Miku AuahDark eeb47f70c0 Update LOVE Submodule. 2023-06-01 15:38:13 +08:00
Miku AuahDark 729c355674 Minor fix from LuaJIT upstream.
LuaJIT/LuaJIT@224129a8e6
2023-06-01 15:38:13 +08:00
Miku AuahDark 81ff3acca7 Merge pull request #249 from MikuAuahDark/selector
Provide App To Select *.love File to Open
2023-04-19 14:25:26 +08:00
Miku AuahDark 0b106828b2 Initial "Loader" launcher. 2023-04-18 13:20:56 +08:00
Miku AuahDark 5187166c3d Update LuaJIT to LuaJIT/LuaJIT@1c27912705. 2023-04-18 10:25:19 +08:00
Miku AuahDark c8ebfc3427 Update copyright to 2023. 2023-04-18 10:05:14 +08:00
Miku AuahDark bda684ae1c Simplify isNativeLibsExtracted() 2023-04-18 09:50:11 +08:00
Miku AuahDark 7ee3735d1a Apply LOVE 11.x-specific patch to SDL2. 2023-04-18 09:39:33 +08:00
Miku AuahDark 55853d5850 Update SDL to 2.26.5. 2023-04-18 09:37:23 +08:00
Miku AuahDark f9eca86935 Minor dependency and readme update. 2023-04-17 21:09:38 +08:00
Miku AuahDark 5d34bf94f3 Update version. 2023-04-16 15:42:13 +08:00
Miku AuahDark acb97d6f87 Update LOVE Submodule. 2023-04-16 15:40:58 +08:00
Miku AuahDark a1868f713d Perform minor changes. 2023-04-16 15:39:44 +08:00
Miku AuahDark 569df256e3 Upgrade to AGP 8.0 2023-04-16 14:53:12 +08:00
Miku AuahDark 349c1e3dda Apply recommended changes by Android Studio. 2023-04-16 14:42:12 +08:00
Miku AuahDark 75fd79b37a Update Android Gradle Plugin. 2023-04-16 14:26:24 +08:00
Miku AuahDark 874a0b12a9 Add more information about transitive dependency issue in Android CMake. 2023-04-06 11:06:43 +08:00
Miku AuahDark e503a91773 Update LOVE submodule. 2023-04-06 11:06:33 +08:00
Miku AuahDark 6a56449748 Update GitHub Actions script. 2023-03-21 11:06:52 +08:00
Miku AuahDark a04d54d5b1 Update README to reflect new requirements. 2023-03-21 11:06:35 +08:00
Miku AuahDark 990471d5d8 Update LOVE submodule. 2023-03-21 11:02:29 +08:00
Miku AuahDark 8a27486c63 Add "love" target to workaround transitive dependency issue (again).
Fixes #247
2023-03-21 10:50:42 +08:00
Miku AuahDark 0025095419 Update gradle and AGP 2023-03-21 10:50:25 +08:00
Miku AuahDark 3c11fdf70d Update copyright year and license. 2023-02-26 10:07:59 +08:00
Miku AuahDark 17122a871f Increase versionCode of the app. 2023-02-26 09:55:30 +08:00
Miku AuahDark 52fa8f3d10 Re-add "OpenAL" target to workaround transitive dependencies.
Fixes #245
2023-02-26 09:53:49 +08:00
Miku AuahDark 43ad1287d7 Update LOVE and Megasource submodule. 2023-02-26 09:29:16 +08:00
Miku AuahDark 187e408d0b Update GitHub Actions dependencies. 2023-02-12 14:03:45 +08:00
Miku AuahDark eddaf2d70a Addendum to #243 and #244
* Revert configurable activity name. Always use "org.love2d.android.GameActivity"

* Delete unnecessary AndroidManifext.xml for embed variant.

* Workaround non-UTF-8 app.name in gradle.properties. See gradle.properties for more information.
2023-02-12 13:22:29 +08:00
flamendless a0740420e8 Fix the previous PR's error (#244)
* Abstract configurable values to gradle.properties

* Remove gms in AndroidManifest

* Fix AndroidManifest
2023-02-06 20:50:46 +08:00
flamendless 69dcd4b63b Abstract configurable values to gradle.properties (#243)
* Abstract configurable values to gradle.properties

* Remove gms in AndroidManifest
2023-02-03 20:57:42 +08:00
Miku AuahDark a46d4211e6 Update LOVE submodule. 2023-01-01 15:18:26 +08:00
Miku AuahDark d72a5e4f1e Compile OpenAL-soft with hidden visibility by default. 2023-01-01 14:16:36 +08:00
Miku AuahDark 588c20f839 Update LOVE submodule. 2022-12-10 09:09:23 +08:00
Miku AuahDark d55d3ce715 Implement 3rd-party modules support for new CMake build system.
Existing 3rd-party module with Android.mk will be converted to CMake, with caveats
of course. Read lua-modules-readme.txt for more info!

Fixes #241.
2022-11-19 18:55:54 +08:00
Miku AuahDark bd57c5e88f Update LOVE submodule 2022-11-19 18:55:39 +08:00
Miku AuahDark b8c353e1e7 Update Megasource 2022-11-19 18:37:22 +08:00
Miku AuahDark 1593566648 Update gradle, dependencies, SDK, and NDK versions. 2022-11-19 14:19:29 +08:00
Miku AuahDark ca0fe2c4ca Update README with new SDK and NDK version requirements. 2022-10-31 00:00:10 +08:00
Miku AuahDark feb20972b5 Update Gradle to 7.5.1 and AGP to 7.3.1 2022-10-30 23:52:48 +08:00
Miku AuahDark 63d53f3584 Android 13 build compatibility. 2022-10-30 23:47:32 +08:00
Miku AuahDark bed7d5c826 Add assert include file. 2022-10-30 22:19:22 +08:00
Miku AuahDark 542560bb2d Update LOVE submodule. 2022-10-30 22:03:33 +08:00
Miku AuahDark 8df7b76060 Update megasource (again) 2022-08-25 20:15:57 +08:00
Miku AuahDark efbf3f5500 Update Megasource submodule. 2022-06-18 22:50:43 +08:00
Miku AuahDark 3eb0f48c07 Only enable documentsprovider on non-fused build for now. 2022-06-18 22:18:51 +08:00
Miku AuahDark 255de8435f Merge branch 'vxdp' into 12.x 2022-06-18 21:57:20 +08:00
Miku AuahDark 2994a6fdc8 Update LOVE submodule. 2022-06-18 21:54:10 +08:00
Mylah Dee 0a4dffbc6e Add A DocumentProvider for access to LOVES external files 2022-06-04 13:31:33 -05:00
Miku AuahDark bef1f21705 Update submodules. 2022-06-04 14:55:29 +08:00
Miku AuahDark 6a48bbb7c3 Revert "Manually extract Oboe AAR for now."
This reverts commit 190938943f.
2022-06-04 14:04:27 +08:00
Miku AuahDark 190938943f Manually extract Oboe AAR for now.
This is not ideal, but looks like there's issue when using prebuilt, causing CI build failure. Reported at google/oboe#1554
2022-06-01 22:41:32 +08:00
Miku AuahDark 50f5e72807 Only launch LOVE if user actually select file in the file picker. 2022-05-29 02:06:07 +08:00
Miku AuahDark 21a4c8eadc Impelement "Share to LOVE" support.
This allows you to share either .love game to launch as game (for the
non-fused APKs and instance of LOVE isn't running) or any file that
gets passed as love.filedropped.

Caveat: Ensure the intended game is running before sending files to LOVE app.
Otherwise, LOVE will attempt to open it as *.love file, which is may not what
you want.
2022-05-29 02:01:58 +08:00
Miku AuahDark 760f8c3860 Add "Open .love File" menu option. 2022-05-28 19:56:48 +08:00
Miku AuahDark 4e8723bec1 Use prebuilt Oboe from prefab. 2022-05-28 19:37:28 +08:00
Miku AuahDark 93cd20d522 Stop further initialization if library loading failed. 2022-05-28 15:48:21 +08:00
Miku AuahDark 2639b8fb63 Convert JNI-called functions to object methods. 2022-05-28 13:52:44 +08:00
Miku AuahDark 72cb021a49 Cleanup unnecessary Java file. 2022-05-28 11:54:21 +08:00
Miku AuahDark b1bca062c9 Reoder handleIntent() call. 2022-05-22 23:11:42 +08:00
Miku AuahDark 6adcd4a8d3 Implement click event to game list. 2022-05-22 23:00:05 +08:00
Miku AuahDark b1724276ac Implement argument passing for external games. 2022-05-22 22:49:01 +08:00
Miku AuahDark 96acf0a891 Handle directory creation failure gracefully. 2022-05-22 17:19:52 +08:00
Miku AuahDark 4cd476b9cc Update megasource submodule. 2022-05-22 13:54:09 +08:00
Miku AuahDark a20adda235 Use Kitware-provided CMake.
Our build system requires CMake 3.22 but Ubuntu 20.04 doesn't provide that.
2022-05-22 13:33:34 +08:00
Miku AuahDark cee0ca9661 Implement game selector.
Item selection is currently not implemented.
2022-05-22 13:18:40 +08:00
Miku AuahDark b1f1062854 Update library versions. 2022-05-22 13:18:26 +08:00
Miku AuahDark 5dd2ac6c3a Use libc++_shared when compiling Megasource and LOVE. 2022-05-16 00:28:13 +08:00
Miku AuahDark 9e15879b4b Initial handling of swipe refresh gesture. 2022-05-15 23:59:17 +08:00
Miku AuahDark 1f90ef5646 Use FLAG_ACTIVITY_NEW_TASK when opening our site. 2022-05-15 23:44:56 +08:00
Miku AuahDark 3379e4c1e9 Game folder dialog. 2022-05-15 23:40:49 +08:00
Miku AuahDark 3a51afb798 Move hardcoded menu strings. 2022-05-15 22:45:27 +08:00
Miku AuahDark d5ba173cbb Allow launching no-game screen.
Not working yet, GameActivity crashes.
2022-05-15 22:38:40 +08:00
Miku AuahDark 7914d60eae Add swipe refresh. 2022-05-15 22:28:28 +08:00
Miku AuahDark 4a1b2ae325 Update GitHub Actions workflow. 2022-05-15 22:16:14 +08:00
Miku AuahDark 4848d7f712 Implement options menu. 2022-05-15 00:34:28 +08:00
Miku AuahDark 39da32d7c5 Add no games text. 2022-05-15 00:14:02 +08:00
Miku AuahDark df8125b601 Use Theme.AppCompat.DayNight. 2022-05-14 23:20:03 +08:00
Miku AuahDark d107d36bbd Add about activity.
Can't be seen yet.
2022-05-14 23:07:00 +08:00
Miku AuahDark d7c8736e9a Update submodules. 2022-05-14 20:42:27 +08:00
Miku AuahDark ef7bb80a47 Rename android:tint to app:tint 2022-05-14 14:44:19 +08:00
Miku AuahDark fcd0731535 Update submodules (again) 2022-03-22 15:05:07 +08:00
Miku AuahDark 78bf758489 Update submodules. 2022-03-05 15:28:49 +08:00
Miku AuahDark 24778126d6 Fix inappropriate fd usage. 2022-03-05 11:43:06 +08:00
Miku AuahDark adfe737120 Update megasource submodule. 2022-02-07 01:25:48 +08:00
Miku AuahDark d4da2103a4 Initial step of integrating with CMake and Megasource 2022-02-07 01:23:15 +08:00
Miku AuahDark 9faca13054 Game list layout. 2022-02-06 23:42:35 +08:00
Miku AuahDark 2a461594a7 Initial work of the game selector. 2022-02-06 21:39:00 +08:00
Miku AuahDark a63feccedd Update NDK requirements. 2022-02-06 11:36:25 +08:00
Miku AuahDark 90e7e60955 Rewrite GameActivity.java 2022-02-05 23:23:59 +08:00
Miku AuahDark 10622388b5 Initial 12.0 refactor.
There are no guarantees this commit will compile.
2022-02-05 16:02:16 +08:00
Miku AuahDark 8e61af7669 Update LOVE submodule. 2022-01-20 20:51:55 +08:00
Miku AuahDark 612a0d0d0c AssetManager: Use directory name without trailing slash when calling AssetManager.list()
It seems that earlier version of Android (probably Android 8) returns empty files if the
passed path in AssetManager.list() contains trailing slash.
2022-01-18 14:27:04 +08:00
Miku AuahDark 2cd3d319d0 Update README.md 2022-01-12 12:14:24 +08:00
Miku AuahDark b367b3733d Release 11.4 2022-01-05 00:48:12 +08:00
Miku AuahDark efaf0f7aa4 Update copyright year to 2022. 2022-01-01 10:44:50 +08:00
Miku AuahDark 8164f11ecb Update submodule. 2021-12-31 10:32:41 +08:00
Miku AuahDark 7ec4135598 LuaJIT: Update to LuaJIT/LuaJIT@a91d0d9d3b 2021-12-31 01:56:38 +08:00
Miku AuahDark 8ad534d227 SDL: Apply libsdl-org/SDL@2363ddc330 2021-12-30 15:19:02 +08:00
Miku AuahDark ba88c4107f SDL: Apply libsdl-org/SDL@a1e992b110 2021-12-30 15:17:07 +08:00
Miku AuahDark 645bae0831 Fixed /sdcard/Android/data/org.love2d.android/files/games/lovegame lookup.
See #194 for more information.
2021-12-28 14:48:34 +08:00
Miku AuahDark 9076e124fe Update LOVE submodule. 2021-12-12 10:06:50 +08:00
Miku AuahDark fd966a7298 Update target SDK to Android 12
We can't update NDK yet because it drops supports for Android Jelly Bean.
2021-12-05 14:26:58 +08:00
Miku AuahDark 17f92a71aa Update gradle library dependencies.
* AGP to 7.0.3
* AndroidX AppCompat to 1.4.0
2021-12-05 14:08:25 +08:00
Miku AuahDark 91ba32e893 Fix gradle wrapper inconsistencies. 2021-12-05 14:04:43 +08:00
Miku AuahDark 2f5394098c Increase minimum SDK version to API 16.
Don't think anyone uses ICS nowadays?
2021-12-05 13:54:00 +08:00
Miku AuahDark 17ec687714 Apply love-specific SDL2 patches to fix black screen. 2021-12-05 13:49:46 +08:00
Miku AuahDark cd0747806d Change how "embed" flag is passed. 2021-12-05 13:49:23 +08:00
Miku AuahDark b17ba72668 Remove hidapi from getLibraries.
libsdl-org/SDL@5b646cd19e
2021-12-05 13:12:35 +08:00
Miku AuahDark 06e4082dfb Apply love-specific SDL2 patches.
Hopefully this will be the last time.
2021-12-05 13:12:01 +08:00
Miku AuahDark 4001bdab19 Update SDL to 2.0.18 2021-12-05 12:52:45 +08:00
Miku AuahDark cd2280386e Update GitHub Actions steps to reflect newly refactored flavor. 2021-12-05 12:46:31 +08:00
Miku AuahDark b6cb0d037e Minor cleanup to GameActivity. 2021-12-05 12:03:23 +08:00
Miku AuahDark c9831be4a4 Refactor AndroidManifest.
Playstore flavor is now removed. Instead, another "record" flavor added:
* `embedNoRecord` - Embed version without recording support.
* `embedRecord` - Embed version with recording support.
* `normalNoRecord` - Normal version without recording support.
* `normalRecord` - Normal version with recording support.
2021-12-05 11:44:47 +08:00
Miku AuahDark a3fc057064 Revert "Implement partial "Share to LOVE" support." 2021-12-05 10:08:17 +08:00
Miku AuahDark a3ea2d5ca0 Update LuaJIT to LuaJIT/LuaJIT@b4b2dce9fc 2021-11-13 14:42:25 +08:00
Miku AuahDark c802045cb2 Update LOVE submodule. 2021-11-05 15:31:54 +08:00
Miku AuahDark 25de1b5de3 Remove redundant GameActivity.getAssetManager() 2021-11-05 13:59:46 +08:00
Miku AuahDark ab850bfc5d Implement GameActivity.buildFileLookup 2021-11-05 13:58:02 +08:00
Miku AuahDark 80078b3046 Update LOVE submodule. 2021-11-02 17:58:57 +08:00
Miku AuahDark ba0f568f15 Improve GameActivity.getCRequirePath() 2021-11-02 17:42:56 +08:00
Miku AuahDark 444a61b945 Add GameActivity.getCRequirePath()
Used by love.filesystem C loader later.
2021-11-01 20:32:10 +08:00
Miku AuahDark 52a80a4e54 Forgot to add .gitignore 2021-11-01 17:53:11 +08:00
Miku AuahDark 383fe4aec6 Initial modular 3rd-party C libs system. 2021-11-01 17:50:36 +08:00
Miku AuahDark b3d9ceb314 Do not obfuscate SDL Java wrappers.
Fixes #217
2021-10-13 19:19:31 +08:00
Miku AuahDark 61ed34b4c7 Reorder GitHub Actions checkout step. 2021-10-11 20:14:10 +08:00
Miku AuahDark 56ab3cef77 Try to silence some Play Console warnings.
Issue #215
2021-10-11 20:07:16 +08:00
Miku AuahDark ae0d89458a Add x86_64 abiFilters for debug.
This workaround problems on debugging/running from Android Studio. See #208
2021-08-21 14:37:25 +08:00
Miku AuahDark ab03301730 Update Gradle build system.
Highlights:
* At least JDK 11 and/or Android Studio 2020.3.1 is now required.
* Update AGP to 7.0 and Gradle to 7.2.
* Replace jcenter() repository with mavenCentral()

Known Issue:
* Currently NDK 22 can't be used to compile yet as GLSLang has compile errors.
2021-08-20 09:41:36 +08:00
Miku AuahDark 89c9fc0a70 Update love2d/love@1e69a8c485
to trigger new workflow run.
2021-08-07 14:08:27 +08:00
Miku AuahDark f507d58891 Use lld linker when linking everything. 2021-05-09 16:35:44 +08:00
Miku AuahDark 552376fc7a Remove x86-specific compile options for Theora
Turns out they're unsupported.
2021-05-09 16:31:18 +08:00
Miku AuahDark 1ff59f59e5 Recompile LuaJIT binaries with -fPIC and lld linker and rewrite build_instructions.bat 2021-05-09 16:30:18 +08:00
Miku AuahDark df01c4568b Update LOVE to love2d/love@e9c58c8192 2021-05-08 22:43:16 +08:00
Miku AuahDark 5862a884bd Update to LOVE to love2d/love@22455276f6 2021-02-06 23:03:47 +08:00
Miku AuahDark d023500320 Only copy game archive if it's requested. 2021-02-06 22:09:47 +08:00
Miku AuahDark 0480f4bac7 Add getAssetManager() method.
This method will be called from C++ side.
2021-02-06 19:30:08 +08:00
Miku AuahDark 59153900ad Update Android Gradle plugin to 4.1.1 2021-02-06 19:08:06 +08:00
Miku AuahDark 0008f9b49e Fix compile error. 2021-02-06 18:54:19 +08:00
Miku AuahDark c315ddff8b Fixed crash when plugging physical keyboard or joystick. 2021-01-21 17:03:43 +08:00
Miku AuahDark 7da70d9786 SDL: Apply https://hg.libsdl.org/SDL/rev/a8e6474302ea
Issue #198
2021-01-14 14:55:03 +08:00
Miku AuahDark ac3ce6af68 Reapply e1f6ce34f0
https://github.com/love2d/love-android/issues/200#issuecomment-757976093
2021-01-12 13:57:04 +08:00
Miku AuahDark 05150585bf Update LÖVE to love2d/love@4ebe64afe1
Issue #200
2021-01-09 23:47:42 +08:00
Miku AuahDark 5b51e05895 Add missing Android.mk for LuaJIT 2021-01-09 11:42:05 +08:00
Miku AuahDark e94fe1a70d Add missing x86-64 LuaJIT static library. 2021-01-05 10:14:58 +08:00
Miku AuahDark d59818bf69 Update LuaJIT to LuaJIT/LuaJIT@1e66d0f9e6 2021-01-05 10:13:12 +08:00
Miku AuahDark f56e03b47c Upload normal debug APK as artifacts too. 2020-12-25 23:10:36 +08:00
Miku AuahDark cf608eda1d Update submodule to love2d/love@9c4db00e94 2020-12-25 23:10:00 +08:00
Miku AuahDark aaae1f4392 Look in /sdcard/lovegame too in Android 9 and earlier for backward compatibility.
See #194 for further explanation about this change.
2020-12-25 23:06:41 +08:00
Miku AuahDark 71c07360a5 Update LOVE submodule love2d/love@57a2a88a09 2020-12-24 23:00:03 +08:00
Miku AuahDark 596cffc9dc Rename openURL -> openURLFromLOVE
It's probably a good idea to remove this function in 12.0 and replace
it by calls to SDL_OpenURL() in LOVE C++ code instead.
2020-12-24 22:48:58 +08:00
Miku AuahDark 0fe970a575 Apply the current love-specific patches. 2020-12-24 22:48:29 +08:00
Miku AuahDark 7ff727cc2d Update SDL to 2.0.14 2020-12-24 20:55:12 +08:00
Miku AuahDark c97bc90527 Rename "Alc" to "alc"
This caught me off-guard.
2020-12-24 20:33:33 +08:00
Miku AuahDark b96fd660f9 Pass sample rate and frames/buffer to opensl_latency.cpp to be used with Oboe later. 2020-12-24 20:08:47 +08:00
Miku AuahDark 321fd15d99 Add low latency audio feature in manifest.
... but make it optional
2020-12-24 15:18:57 +08:00
Miku AuahDark dfe836d39c Update OpenAL-soft to 1.21.0
This allows OpenAL-soft to use Oboe backend which uses AAudio in Android 8
or OpenSLES in earlier Android version. This switch is necessary for
Android 11 compatibility as OpenSLES is now deprecated in Android 11.

Plus, we also have low latency audio for free.
2020-12-24 15:01:23 +08:00
Miku AuahDark 96f7387ac5 Upload each APK as separate artifacts. 2020-12-23 22:19:05 +08:00
Miku AuahDark 1c0565b56e Update readme. 2020-12-23 21:44:40 +08:00
Miku AuahDark 9c94f41470 Ensure app/src/main/assets directory exist. 2020-12-23 21:24:19 +08:00
Miku AuahDark 5b9fbeacb5 Update GitHub actions workflow. 2020-12-19 20:45:06 +08:00
Miku AuahDark 0e41ef20b3 Android 11.0 compatibility (#195)
* Update dependencies and target SDK
* Update Gradle to 6.6.1
* Update target API level to 30
* Update AGP to 4.0.1
* Update Android Build Dependencies (androidx.appcompat:appcompat:1.2.0, androidx.multidex:multidex:2.0.1)
* Update readme
* Move /sdcard/lovegame directory. (closes #194)
* Potentially fixes black screen when reopening LOVE from app drawer (fixes #190)
* Downloader cleanup.
* Merge SDL AndroidManifest.xml to LOVE
* Implement partial "Share to LOVE" support.
* Enable resizeableActivity
2020-10-10 01:33:06 +08:00
Miku AuahDark 6c754106ea Revert "Increase target API level to 29 (Android 10.0)"
This reverts commit f0abf9b537.

See #194
2020-10-06 20:47:56 +08:00
Miku AuahDark f0abf9b537 Increase target API level to 29 (Android 10.0) 2020-06-27 19:49:55 +08:00
Miku AuahDark 31d7affd91 Remove setImmersiveMode code as it conflicts with SDL's immersive mode code.
Fixes #191
2020-06-22 12:57:38 +08:00
Miku AuahDark 20329a65a6 Do not use ID 1 for request code
As it's reserved by SDL for its Android_JNI_RequestPermission
2020-05-05 11:26:25 +08:00
Miku AuahDark 8a964146c1 Update SDL to 2.0.12 2020-05-05 10:31:43 +08:00
Miku AuahDark b1740eb4b6 Add license.txt and license notice to each Java files. 2020-02-01 00:37:34 +08:00
Miku AuahDark cb56ef28fb Update and cleanup readme. 2020-02-01 00:01:27 +08:00
Miku AuahDark ba299eeafb Fix embed flavor not starting up. 2020-01-31 23:20:49 +08:00
Miku AuahDark 3370e38eea Testing the Actions. 2020-01-31 22:12:12 +08:00
Miku AuahDark 7999e17a76 Exclude "Download" service/activity from embed flavor. 2020-01-31 21:34:21 +08:00
Miku AuahDark 5a80990790 Perform handleIntent conditional whetever it's embed build or not. 2020-01-31 14:58:53 +08:00
Miku AuahDark 62684832a6 Generate 3 different flavors: normal, playstore, embed. 2020-01-31 14:46:34 +08:00
Miku AuahDark 01c8018c36 Merge commit 'e721960f7e52fcadd7e0f4bda977b879adb12433'
Add 11.3 changelog.
2020-01-29 22:51:03 +08:00
Miku AuahDark 1fe71865f6 Update readme. 2020-01-29 22:42:52 +08:00
Miku AuahDark fa276ea4d8 Detect LOVE submodule first before building. 2019-11-24 17:36:32 +08:00
Miku AuahDark e721960f7e Update README 2019-11-17 11:50:36 +08:00
Martin Felis 18c9b3c401 Disable microphone for PlayStore build. 2019-10-29 22:59:28 +01:00
Miku AuahDark face22cff4 Release 11.3 2019-10-27 23:19:47 +08:00
Miku AuahDark 8b93b1eea2 Remove problematic dimens.xml when compiling. 2019-10-20 12:07:24 +08:00
Miku AuahDark 29821438ad Update APK manifest to 11.3 2019-10-10 23:23:28 +08:00
Miku AuahDark a199d54b50 Merge branch '11.x_submodule' into 0.11.x 2019-10-10 23:09:15 +08:00
Miku AuahDark 61ef9802a3 Really fix Martin's SDL hack. 2019-10-10 23:00:46 +08:00
Miku AuahDark ee81c4262d Unstable changes: Update SDL to 2.0.10
Bug: Martin's hack of restarting SDL no longer works in this SDL version
so more matches to LOVE central repository will be come soon.
2019-10-10 22:26:54 +08:00
Miku AuahDark 4be53bca65 Make LOVE as submodule 2019-10-08 15:13:08 +08:00
Alex Szpakowski c89ac83e37 Fix some readme syntax issues 2019-09-29 12:28:04 -03:00
Alex Szpakowski 29e49d9048 Merge pull request #1 from MikuAuahDark/micsupport
Recording support for Android (Java side)
2019-09-29 09:21:37 -03:00
Miku AuahDark 8c701dd3a4 Add microphone permission to AndroidManifest.xml 2019-09-29 15:25:01 +08:00
Miku AuahDark 59a5fcb875 Fixed mic permission requested 3 times and dialog not showing. 2019-09-29 15:24:35 +08:00
Miku AuahDark 05e193ddbd Add function to retrieve and request mic permission. 2019-09-29 12:46:17 +08:00
Miku AuahDark 0380160775 Update README file. 2019-09-24 15:10:56 +08:00
Miku AuahDark 376ae96cb1 Merged in AuahDark/love-android-sdl2/java-fix (pull request #22)
Various fixes related to manifest and Java code.
2019-08-10 12:36:55 +00:00
Miku AuahDark 8186794a03 Remove SDL_android_main.c from LOVE Android.mk
A notice from SDL_android_main.c:
"As of SDL 2.0.6 this file is no longer necessary."
2019-08-10 16:27:41 +08:00
Miku AuahDark 54b29fca4f Update APK version to 11.2 2019-08-10 16:25:40 +08:00
Miku AuahDark 45507c5282 Fix download manager crashing in newer devices.
Request storage permission in Mashmallow until Pie. Also added support of
HTTPS URL.
2019-08-10 16:10:16 +08:00
Miku AuahDark f18cf70c15 Minor changes to GameActivity.
Nothing that may cause something break. Mainly reordering & line optmization
changes.
2019-08-10 16:01:52 +08:00
Miku AuahDark 5df17ba075 Modify AndroidManifest.xml again(?)
Moved WRITE_EXTERNAL_STORAGE maxSdkVersion to 28. Although t.externalstorage=true
needs WRITE_EXTERNAL_STORAGE for Android Jelly Bean and earlier, it's needed
for the game downloader to store files in Downloads folder. However the permission
to do it is unnecessary since Android Q (API 29).
See https://developer.android.com/reference/android/app/DownloadManager.Request#setDestinationInExternalPublicDir(java.lang.String,%2520java.lang.String)

Use per-activity theme instead of per-application theme. We need different
theme for the GameActivity and the DownloadActivity.
2019-08-10 15:59:26 +08:00
Miku AuahDark 5090a072b2 Minor manifest change and some GameActivity changes.
Fixed storage permission request and do not hardcode "game.love" as the cache output
file.
2019-07-26 13:01:25 +08:00
Miku AuahDark 117bba5ff2 Minor changes.
Remove vibrate permission string, use Manifest.permission.VIBRATE instead!

Fix code style.

Set gamePath to empty when it fails to detect any game.love
2019-07-20 21:33:52 +08:00
Miku AuahDark 78e88a7473 Override getMainSharedObject()
This theoretically allows LOVE libs not to be extracted in Marshmallow
and later by utilizing extractNativeLibs=false. However this is left to
users (developer) to decide whetever to use this or not.
2019-07-20 20:49:25 +08:00
Miku AuahDark 2529265eed Modify AndroidManifest.xml again.
The first change is to change the launch mode from singleTop to singleTask.
This hopefully fixes issue with love.filesystem initialization issue.

The second change is to change the accepted mime type to application/octet-stream.
2019-07-20 19:58:51 +08:00
Miku AuahDark a2c79d95e0 Flip the storage permission check. 2019-07-20 10:03:32 +08:00
Miku AuahDark f761e43904 Fix *.love file association in Nougat and later.
Note that the file association is rather hacky but I can't find any method
which is compatible in Nougat and later as file:// URI is banned there.
2019-07-10 12:10:36 +08:00
Miku AuahDark cd6463b4e4 Implement content:// URI 2019-07-10 10:14:10 +08:00
Miku AuahDark 9298bed843 Fix embedded game.love loading if there's no external storage permission given.
Mainly affect Android M and later devices.
2019-07-10 09:16:06 +08:00
Miku AuahDark 94d31aefc1 Only request storage permission on JB and older.
The permission to read local, application external directory is granted
implicitly in KitKat and later versions.
2019-07-10 09:00:13 +08:00
Miku AuahDark 8d71234114 Merged in AuahDark/love-android-sdl2/clean-include (pull request #21)
Clean external dependency include paths from LOVE Android.mk
2019-07-06 04:16:00 +00:00
Miku AuahDark 799956e002 Fix theoretical Theora x86-64 build. 2019-07-04 13:32:07 +08:00
Miku AuahDark f8d0890519 Cleanup ogg-family (vorbis, theora) includes.
This means only SDL remains that has paths hardcoded.
2019-07-04 12:53:44 +08:00
Miku AuahDark c065fe9e56 Update Theora codec
Add x86(-64)-optimized assembly. Unfortunately ARM-optimized assembly
can't be used. Please report this to Theora maintainers :(
2019-07-04 11:49:13 +08:00
Miku AuahDark 77c7570f55 Fix Mpg123 export include. 2019-07-04 10:38:44 +08:00
Miku AuahDark 6d5d8c4540 OpenAL-soft: link with Android log library.
It seems that in ARM64, liblog is added implicitly, but for other arch,
it must be added explicitly.

See https://github.com/MikuAuahDark/livesim3-love-android/issues/5
2019-07-04 10:24:30 +08:00
Miku AuahDark 456273ebf0 Clean include paths of external dependency
This way, LOVE Android.mk doesn't have to be modified in case new libraries
added or in case old libraries gets updated and their name is different.
2019-07-04 10:11:34 +08:00
Miku AuahDark 7c48033960 Merged in AuahDark/love-android-sdl2/als-1.19.1 (pull request #19)
Update OpenAL-soft to 1.19.1
2019-07-03 20:39:29 +00:00
Miku AuahDark b8beb8a1f4 Merged in AuahDark/love-android-sdl2/ft-2.8.1 (pull request #20)
Update FreeType to 2.8.1
2019-07-03 20:38:39 +00:00
Miku AuahDark c1399fc44a Remove version number from folder 2019-07-03 22:07:04 +08:00
Miku AuahDark 077c1a350b Remove version number from folder 2019-07-03 21:59:56 +08:00
Miku AuahDark 40ec52368b Use LOCAL_EXPORT_C_INCLUDES to manage include paths.
Better than hardcoding the include path in LOVE Android.mk
2019-07-02 21:21:19 +08:00
Miku AuahDark 605ddefd0e Update FreeType to 2.8.1 2019-07-02 20:57:08 +08:00
Tae Hanazono 2a23cbd16d Clean LOVE Android.mk and rename/fix detection variables. 2019-07-02 11:15:16 +08:00
Tae Hanazono 0ebc4d9271 Update OpenAL-soft to 1.19.1 2019-07-02 10:16:25 +08:00
Tae Hanazono 07149c0ba8 Fix log2f conflict. 2019-07-01 23:05:08 +08:00
Miku AuahDark 288f005d86 Merged in AuahDark/love-android-sdl2/love11-arm64 (pull request #15)
Add ARM64 ABI support
2019-07-01 13:28:00 +00:00
Miku AuahDark 49ad4632b6 Merged in AuahDark/love-android-sdl2/love113-safearea (pull request #17)
Implement `love.window.getSafeArea` for Android (Java changes)
2019-07-01 13:21:52 +00:00
Tae Hanazono 6eafa708f9 Fix setImmersiveMode using unsupported flags in some older devices. 2019-02-09 18:53:42 +08:00
Tae Hanazono 53d24a1b5f Added method to retrieve safe area insets. 2019-02-08 23:56:23 +08:00
Tae Hanazono 3b7407ab34 Fix onResume using unsupported flags in some older devices. 2019-02-08 20:20:37 +08:00
Tae Hanazono e203f7ae4c Modify LOVE build.gradle
Again, two changes. First change is to add "arm64-v8a" to NDK abiFilters.
This is needed to really generate ARM64 binaries inside the APK.

The second change is to exclude libSDL2.so from the resulting APK. Since
LOVE statically links with SDL2, then there's no reason to have libSDL2.so
lying around inside the APK. It's also save the APK size a little bit.
2018-12-14 23:40:10 +08:00
Tae Hanazono 1349f27bd8 Modify OpenAL-soft Android.mk
The comment is self-explanatory.
2018-12-14 23:36:31 +08:00
Tae Hanazono 9a11b88572 Modify LOVE Android.mk
There are two changes in here. First change is to tell Android build
system to use NEON instruction support. Slime already wrote a
NEON-optimized matrix multiplication function which is already in love main
source code (see link below for related commit)
https://bitbucket.org/rude/love/commits/e61734b33581a485743ea79b87d02f8aeb77693e

The problem is that not all ARMv7 devices do support NEON instruction, but
I don't even think if such device exist in 2018 (or even in 2019). ARM64
guarantee NEON instruction support, so it's all good for ARM64.

The second change is to define "HAVE_SOCKLEN_T=1" only when building ARM64.
This is needed because LuaSocket (or enet, I don't remember exactly)
redefines socklen_t and this cause compiler error.
2018-12-14 23:25:32 +08:00
Tae Hanazono f88e0ba4b9 Start ARM64 support: build LuaJIT for arm64-v8a
I don't use the buildandroid.sh for this because it forces the host
compiler to 32-bit (-m32), but we do really need 64-bit host compiler to
build LuaJIT for ARM64 (also I'm in Windows).

So, I used Android NDK standalone toolchain then invoke make like this:
make CROSS=aarch64-linux-android- TARGET_SYS=Linux TARGET_CFLAGS="-D__ANDROID_API__=21" amalg

Then the resulting libluajit.a is copied to android/arm64-v8a/libluajit.a
2018-12-14 23:14:11 +08:00
Martin Felis 2fd01541c2 Updated buildscript for LuaJIT 2018-12-13 09:06:40 +01:00
Martin Felis fc85623f10 Fixed build settings (thanks to Tae Hanazono!) 2018-12-10 22:46:42 +01:00
Martin Felis 692ce8bb51 Updated build system to use compileSdkVersion 28. 2018-12-07 22:39:06 +01:00
Martin Felis 0394a380c4 Added missing file from LÖVE main 2018-12-07 19:58:06 +01:00
Martin Felis 0000c326a8 Updated LÖVE code to tag 11.2 (changeset 55dc225ee2) 2018-12-07 18:34:41 +01:00
Martin Felis 34e88d43ae merged 2018-12-07 17:57:07 +01:00
Martin Felis 94c8a99ddc Properly ask and check for permissions on android >= 23.
On the first run it will ask for permission and block the LÖVE thread until
it has been granted. Thanks to Tae Hanzano for the initial draft.
2018-12-07 17:32:01 +01:00
Martin Felis 1ea86d3305 Properly using SDL 2.0.9 paths and android 26 compatibility layers. 2018-12-07 17:24:32 +01:00
Martin Felis 696fae730c Merge branch 'sdl2_2.0.9_fix' into 0.11.x 2018-12-07 17:03:21 +01:00
Martin Felis a19404a902 Re-applied patch to restart native thread. Also 2018-11-18 23:55:14 +01:00
Martin Felis e2c44417d1 Renamed SDL2 directory (already contains 2.0.9 sources) 2018-11-18 22:29:36 +01:00
Martin Felis e23fb2c8ea Renamed SDL2 directory (already contains 2.0.9 sources) 2018-11-18 22:23:51 +01:00
Martin Felis 4de76a9c52 preparing update of SDL to 2.0.9 2018-11-18 22:21:57 +01:00
Martin Felis 973f9eef89 Updated buildToolsVersion to 28.0.3 and Android Gradle Plugin to 3.2.1 2018-11-18 12:29:55 +01:00
Martin Felis 0ac43aa717 Updated love sources to changeset 0ab246b5045d and updated android version 2018-04-15 21:22:56 +02:00
Martin Felis c186a70b14 Updated love sources to changeset 0ab246b5045d and updated android version 2018-04-15 21:22:56 +02:00
Martin Felis 7fbf155d82 Setting target SDK to 22 to mark app as legacy app which gets storage permissions without having to write request code 2018-04-15 11:05:23 +02:00
Martin Felis 7ad34c64f4 Setting target SDK to 22 to mark app as legacy app which gets storage permissions without having to write request code 2018-04-15 11:05:23 +02:00
Martin Felis 3df1807c6f Fix for #159 2018-04-08 21:03:05 +02:00
Martin Felis 29a493a54b Fix for #159 2018-04-08 21:03:05 +02:00
Martin Felis c979f65152 New version: 11.0. Also bumped minSdkVersion to 14 to be in sync with used SDL2 version 2018-04-01 22:52:58 +02:00
Martin Felis 75306e8e63 New version: 11.0. Also bumped minSdkVersion to 14 to be in sync with used SDL2 version 2018-04-01 22:52:58 +02:00
Martin Felis 1dba069683 Updated LÖVE to 11.0 tag (6504209dc45b) 2018-04-01 22:45:58 +02:00
Martin Felis ec8b710a93 Updated LÖVE to 11.0 tag (6504209dc45b) 2018-04-01 22:45:58 +02:00
Martin Felis 408778fb8f Minor adjustments for 0.11.0-alpha1 2018-03-31 19:48:40 +02:00
Martin Felis 45ae52f55e Minor adjustments for 0.11.0-alpha1 2018-03-31 19:48:40 +02:00
Martin Felis f8241c1b65 Updated LÖVE to changeset c303c1f52ea6 2018-03-30 21:42:03 +02:00
Martin Felis 91295b7506 Updated LÖVE to changeset c303c1f52ea6 2018-03-30 21:42:03 +02:00
Martin Felis 4d8f4f70ce Initial works to support 0.11.x, disabled armeabi builds, using now clang and libc++ instead of gnustl 2018-02-02 21:10:33 +01:00
Martin Felis ebd4a0ad4f Initial works to support 0.11.x, disabled armeabi builds, using now clang and libc++ instead of gnustl 2018-02-02 21:10:33 +01:00
Martin Felis f40577c9cb Upgraded OpenAL-Soft to 0.18.2 2018-02-01 15:53:05 +01:00
Martin Felis ac443d7e2f Upgraded OpenAL-Soft to 0.18.2 2018-02-01 15:53:05 +01:00
Martin Felis fd60978b7b Merge branch 'master' into 0.10.x 2018-01-24 10:17:36 +01:00
Martin Felis 8c7772cfa4 Merge branch 'master' into 0.10.x 2018-01-24 10:17:36 +01:00
Martin Felis 6ed3ba3810 Adjusted SDLActivity.java to allow restarting of the native thread 2018-01-23 21:27:41 +01:00
Martin Felis 21ff4b2188 Adjusted SDLActivity.java to allow restarting of the native thread 2018-01-23 21:27:41 +01:00
Martin Felis ba269a5062 Copied SDL2 2.0.7+ (changeset b359333bdc52) and adjusted gradle to use the new directory layout of the SDL2 android project 2018-01-23 21:22:56 +01:00
Martin Felis 4ffea15ffc Copied SDL2 2.0.7+ (changeset b359333bdc52) and adjusted gradle to use the new directory layout of the SDL2 android project 2018-01-23 21:22:56 +01:00
Martin Felis 74d83c0c13 Cleaned up formatting of Java code 2018-01-23 15:28:20 +01:00
Martin Felis 906a7cc00b Cleaned up formatting of Java code 2018-01-23 15:28:20 +01:00
Martin Felis f12ab60594 merge 2018-01-23 15:22:57 +01:00
Martin Felis 5f4aeb2d71 merge 2018-01-23 15:22:57 +01:00
Martin Felis fb34e99d9a merge 2018-01-22 22:57:29 +01:00
Martin Felis d62a4df5ac merge 2018-01-22 22:57:29 +01:00
Martin Felis ad5db40a9d Merge branch 'setSource_mount_order' 2018-01-22 22:52:36 +01:00
Martin Felis 406d0c04e2 Merge branch 'setSource_mount_order' 2018-01-22 22:52:36 +01:00
Martin Felis a00675c4cc Cleaned up logic of loading games on the Java side of the App 2018-01-22 22:52:16 +01:00
Martin Felis 0afdf271a2 Cleaned up logic of loading games on the Java side of the App 2018-01-22 22:52:16 +01:00
Martin Felis 7ebcf9494e Merge https://bitbucket.org/cigumo/love-android-sdl2/branch/master into setSource_mount_order 2018-01-22 13:28:18 +01:00
Martin Felis cff1a295a6 Merge https://bitbucket.org/cigumo/love-android-sdl2/branch/master into setSource_mount_order 2018-01-22 13:28:18 +01:00
Tiago Shibata 234bc83aa2 Merged in tiagokcshibata/love-android-sdl2 (pull request #8)
Add GameActivity.hasBackgroundMusic

Approved-by: Tiago Shibata <tiago.shibata@tapps.com.br>
Approved-by: Bart van Strien <bart.bes+projects@gmail.com>
2018-01-22 12:18:17 +00:00
Tiago Shibata 84dc89e264 Merged in tiagokcshibata/love-android-sdl2 (pull request #8)
Add GameActivity.hasBackgroundMusic

Approved-by: Tiago Shibata <tiago.shibata@tapps.com.br>
Approved-by: Bart van Strien <bart.bes+projects@gmail.com>
2018-01-22 12:18:17 +00:00
Martin Felis a22628bc1b Updgraded SDL2 to version 2.0.7 2017-12-26 22:04:21 +01:00
Martin Felis 487f00201e Updgraded SDL2 to version 2.0.7 2017-12-26 22:04:21 +01:00
Martin Felis 1fe6d7b640 Removed physfs, updated LÖVE to changeset 7bb02207faa6 2017-12-26 16:42:40 +01:00
Martin Felis 204945586e Removed physfs, updated LÖVE to changeset 7bb02207faa6 2017-12-26 16:42:40 +01:00
Martin Felis 004ccf4f9c Upgraded physfs to 3.0.1 2017-12-26 14:20:42 +01:00
Martin Felis f68cf2fcc4 Upgraded physfs to 3.0.1 2017-12-26 14:20:42 +01:00
Martin Felis f6c360c809 Updated gradle scripts so that it uses newer gradle version 2017-12-26 13:37:35 +01:00
Martin Felis 391429367d Updated gradle scripts so that it uses newer gradle version 2017-12-26 13:37:35 +01:00
cigumo baa595bd51 Changes Filesystem::setSource mount order on Android
Simplifies the way setSource is handled on Android. It tries to mount
first and if that fails it will copy to memory and mount.

The /sdcard/lovegame fallback is moved to GameActivity.java.

Also a flag is added (mustCacheArchive) that will copy the game.love
file to the cache dir, so it can be mounted directly and not loaded to
memory, which does not work for large .love files.

The Filesystem.cpp change was also submitted to rude/love repo in this
push request: https://bitbucket.org/rude/love/pull-requests/99
2017-11-16 19:53:41 -03:00
cigumo 957330d722 Changes Filesystem::setSource mount order on Android
Simplifies the way setSource is handled on Android. It tries to mount
first and if that fails it will copy to memory and mount.

The /sdcard/lovegame fallback is moved to GameActivity.java.

Also a flag is added (mustCacheArchive) that will copy the game.love
file to the cache dir, so it can be mounted directly and not loaded to
memory, which does not work for large .love files.

The Filesystem.cpp change was also submitted to rude/love repo in this
push request: https://bitbucket.org/rude/love/pull-requests/99
2017-11-16 19:53:41 -03:00
Tiago Koji Castro Shibata ecaf3f7f45 Add GameActivity.getMusicStreamVolume 2017-07-10 16:09:28 -03:00
Tiago Koji Castro Shibata b3db9d4839 Add GameActivity.getMusicStreamVolume 2017-07-10 16:09:28 -03:00
Martin Felis a1aca69aa4 Slight adjustments on how to build with the new gradle build system 2017-05-11 23:04:55 +02:00
Martin Felis 646de828b9 Slight adjustments on how to build with the new gradle build system 2017-05-11 23:04:55 +02:00
Martin Felis 0ffa7f7db7 Merge branch 'master' of ssh://bitbucket.org/MartinFelis/love-android-sdl2 2017-05-11 22:52:40 +02:00
Martin Felis 7d7e1cb1f9 Merge branch 'master' of ssh://bitbucket.org/MartinFelis/love-android-sdl2 2017-05-11 22:52:40 +02:00
Henrique Gemignani ee59b69e01 Merged in henriquegemignani_/love-android-sdl2/gradle (pull request #7)
Change buildsystem to Gradle / Android Studio
2017-05-11 20:51:48 +00:00
Henrique Gemignani 0ac0e39287 Merged in henriquegemignani_/love-android-sdl2/gradle (pull request #7)
Change buildsystem to Gradle / Android Studio
2017-05-11 20:51:48 +00:00
Henrique Gemignani Passos Lima 49d7b402a7 Use 'org.love2d.android' package name for the library. 2017-02-19 16:14:34 -03:00
Henrique Gemignani Passos Lima 529b897fed Use 'org.love2d.android' package name for the library. 2017-02-19 16:14:34 -03:00
Henrique Gemignani Passos Lima 7ef92ea876 Readme changes. 2017-02-19 16:08:49 -03:00
Henrique Gemignani Passos Lima 40b2aa6e6a Readme changes. 2017-02-19 16:08:49 -03:00
Henrique Gemignani Passos Lima 7c8b022dcb Make gradlew work. 2017-02-19 16:05:14 -03:00
Henrique Gemignani Passos Lima dbdefdd86a Make gradlew work. 2017-02-19 16:05:14 -03:00
Henrique Gemignani Passos Lima c931228238 Update gitignore with x86 luajit 2017-02-19 15:56:46 -03:00
Henrique Gemignani Passos Lima 15474cab41 Update gitignore with x86 luajit 2017-02-19 15:56:46 -03:00
Henrique Gemignani Passos Lima 2a0c579ebf Fix build on windows. 2017-02-19 15:56:10 -03:00
Henrique Gemignani Passos Lima af039516c0 Fix build on windows. 2017-02-19 15:56:10 -03:00
Henrique Gemignani Passos Lima cc457787f4 Fix build.gradle and add gradle/Android Studio entries to gitignore 2017-02-19 10:48:35 -03:00
Henrique Gemignani Passos Lima 76230b01f9 Fix build.gradle and add gradle/Android Studio entries to gitignore 2017-02-19 10:48:35 -03:00
Henrique Gemignani Passos Lima 3c922b0ae8 Move the java code. 2017-02-19 10:41:46 -03:00
Henrique Gemignani Passos Lima ab888ac39f Move the java code. 2017-02-19 10:41:46 -03:00
Henrique Gemignani Passos Lima fdb360a557 Move JNI folder. 2017-02-19 13:39:42 +00:00
Henrique Gemignani Passos Lima d32e6ada77 Move JNI folder. 2017-02-19 13:39:42 +00:00
Henrique Gemignani Passos Lima 46d624851b Fix JNI gitignore. 2017-02-19 10:38:07 -03:00
Henrique Gemignani Passos Lima 00cfe30282 Adding love libproject. 2017-02-19 10:32:44 -03:00
Henrique Gemignani Passos Lima 0cf41c2792 Removing more old files. 2017-02-19 10:28:28 -03:00
Henrique Gemignani Passos Lima 803786eee9 Initial files for gradle build. 2017-02-19 10:27:00 -03:00
Martin Felis c025e5eab4 Imported official LÖVE 0.10.2 release version 2016-11-01 20:21:18 +01:00
Martin Felis 35cd9f1900 Preparation for 0.10.2 release 2016-10-30 21:27:26 +01:00
Martin Felis 70f63954ed Applied LÖVE related patches to SDL2 2016-10-30 21:26:13 +01:00
Martin Felis f87d73671f updated SDLActivity to version from SDL2 2.0.5 2016-10-30 21:10:10 +01:00
Martin Felis 967840db16 Updated LÖVE codebase to 6d245a253bab 2016-10-30 19:08:36 +01:00
Martin Felis 6dedec28a2 Updated SDL to version 2.0.5 2016-10-22 22:10:28 +02:00
Martin Felis 2358b45c27 Merge commit '42093cf' 2016-08-30 23:11:50 +02:00
Martin Felis 08b116c09f Fixed linking errors due to using newer toolchain (4.9) 2016-08-30 23:08:04 +02:00
Martin Felis e9a3b2ac59 Merged in orangeudav/love-android-sdl2/orangeudav/update-to-actual-version-of-ndk-at-2016-1470408661381 (pull request #6)
Update to actual version of NDK at 2016
2016-08-25 06:53:49 +02:00
orangeudav 7345a01f56 Update to actual version of NDK at 2016 2016-08-05 14:51:10 +00:00
Martin Felis 42093cfbe9 Updated changes.txt from the 0.10.1 release 2016-02-14 16:18:59 +01:00
Martin Felis 8244228004 OpenGL ES fix and proper sizes for the icons 2016-02-14 14:14:31 +01:00
Martin Felis 7459285690 New release 0.10.1 2016-02-14 00:30:25 +01:00
Martin Felis 7aaeb1485e LuaJIT build script also builds for x86 and added the binary. First step to optional support of x86 android devices 2016-01-20 22:53:06 +01:00
Martin Felis 5e410bca8e Updated to latest LÖVE code (29f0bad6be9d), which adds the externalstorage config flag to conf.lua. Note: one cannot switch between internal and external storage after running the app! 2016-01-17 14:12:09 +01:00
Martin Felis 19e0b12363 Only enable vibration if we have the proper permissions (fixes #122) 2016-01-17 13:45:47 +01:00
Martin Felis 24387a8450 Updated SDL2 to the 2.0.4 release version 2016-01-17 13:22:47 +01:00
Martin Felis 962c894908 Release cleanup 2015-12-22 16:02:02 +01:00
Martin Felis 26a6c423f9 Updated to latest LÖVE code 2f5d329b07d7 (android: disable JIT by default as it may cause performance problems) 2015-12-22 10:06:57 +01:00
Martin Felis 08d51fbf28 Updated LÖVE source to changeset da332813bc05 2015-12-20 22:52:22 +01:00
Martin Felis eac5db7e10 Updated README.md for 0.10.0-alpha2 2015-12-09 23:52:09 +01:00
Martin Felis 28d2d92645 Updated LuaJIT to latest 2.1 version 2015-12-09 22:51:28 +01:00
Martin Felis 66685a2ade Updated LÖVE source to revision cff5bc8604bd 2015-12-09 22:19:41 +01:00
Martin Felis 8f5ee4a05e added building of the theora library 2015-12-09 12:41:20 +01:00
fysx 686e1d5f3e Update LÖVE to changeset 7cb21c8bdd64 (pre 0.10.0) 2015-12-01 23:07:34 +01:00
fysx 7e877716d6 Updated SDL2 to changeset 69a5f3a540af (dev version of 2.0.4) 2015-12-01 22:29:54 +01:00
fysx ec5f068b19 Updated OpenAL to version 1.16.0 2015-11-29 15:27:32 +01:00
fysx 8308a524bc Updated libogg to 1.3.2 and libvorbis to 1.3.5 2015-11-28 22:14:03 +01:00
fysx 4439a193d6 Fixed issue #115 (compatibility with Android 2.3 devices) 2015-11-28 21:58:50 +01:00
fysx 9cbddc2f5e Updated to latest love-android code (b615972822cb) 2015-08-13 17:21:53 +02:00
fysx f3dd769e98 Using latest love-android branch (9a508a54700d) 2015-08-13 11:12:17 +02:00
fysx c91dbb6957 Forcing use of GCC 4.8 to prevent compiling issues 2015-07-15 11:10:46 +02:00
fysx 198c2d28de new version: 0.10.0-alpha. Warning: this uses the not yet released 0.10.0 API of LÖVE. 0.9.2 games likely don't work! 2015-07-03 19:40:31 +02:00
fysx 357a7237a4 Using latest android branch of LÖVE (6d14516b05c9) that now syncs with default (woooo!) 2015-07-03 19:09:18 +02:00
fysx 1924bbdeeb updated changelog for 0.9.2a 2015-04-10 16:01:39 +02:00
fysx d783f5afa1 Preparing 0.9.2a release 2015-04-10 15:59:27 +02:00
fysx 7eb7db1a85 Imported latest love-android code 8e93b946d920 that fixes ParticleSystem:clone 2015-04-10 15:45:46 +02:00
fysx 8af8dffad4 fixed README markup 2015-04-10 11:55:14 +02:00
fysx a0efc89a7d preparing release 0.9.2 2015-04-10 11:43:31 +02:00
fysx c30e788393 properly detect whether we are in "fullscreen" (i.e. immersive) on Android 2015-02-19 00:15:31 +01:00
fysx 168357e1ad fixed #104: loading of multiple .love files 2015-02-18 10:33:54 +01:00
fysx d6f1d8bd70 imported changes from love-0.9.2 2015-02-16 00:37:14 +01:00
fysx 3cfecd46d9 added Download section to README.md 2015-02-15 23:21:53 +01:00
fysx f31760c445 made love.window.setFullscreen() work 2015-02-02 22:42:08 +01:00
fysx d0f866e4b0 fixed build for latest love-android version 2015-01-22 20:57:57 +01:00
fysx 542c029666 updated to latest love-android (changeset 7b5f223900b) 2015-01-22 10:48:45 +01:00
fysx 31cd05551e renamed setBorderless to setImmersive and linked it to the fullscreen mode 2015-01-20 22:11:56 +01:00
fysx 42f6beaa7e Allowing enabling and disabling of immersive mode via borderless setting and love.window.setMode() 2015-01-20 16:01:43 +01:00
fysx 36216c16be fixed immersive mode when resuming 2015-01-20 14:36:57 +01:00
fysx 013df025d0 fix for #91 and #98: printing of non-number and non-string values 2015-01-16 22:13:33 +01:00
fysx 535a8256ee Using immersive mode by default 2015-01-16 20:41:03 +01:00
fysx b732d6cc12 replaced tabs with spaces 2015-01-16 20:40:23 +01:00
fysx 54215b7ce4 refactored loading of games on android 2015-01-16 20:00:51 +01:00
fysx fd9e9758a9 Using latest changeset 593639000823 of love-android 2015-01-16 12:31:11 +01:00
fysx f46115e794 ignoring *.orig files from mercurial merges 2015-01-16 12:30:43 +01:00
fysx 29a3e4b566 fixed APP_PLATFORM warning 2015-01-13 20:57:00 +01:00
fysx 02dc18a587 fixed compilation with Android NDK r10 2015-01-11 22:23:12 +01:00
fysx a034220b10 tried to list dependent softwares and licenses 2014-11-12 10:37:43 +01:00
fysx 72b2fcd4eb Added loading of games by opening the main.lua file 2014-10-22 11:54:04 +02:00
fysx b20f7e7302 Stop the vibrator when the app is paused (e.g. when device is switched off or app goes in background) 2014-10-22 11:26:52 +02:00
fysx 6b1fae429b not calling exit(retval) when main ends 2014-10-21 12:21:02 +02:00
fysx 4ec2e26985 updated to latest SDL2 (f9244b2a151) 2014-10-21 12:20:26 +02:00
fysx 8df94d2a8a Properly pausing OpenAL device using the extension alcDevicePauseSOFT (fixes #83) 2014-09-09 10:29:56 +02:00
fysx 70eef137ae updated OpenAL-Soft to version 1.16.0 2014-09-08 21:17:12 +02:00
fysx 4f11bd0e7b fixed #82: was using wrong argument to query module instance 2014-08-31 14:14:15 +02:00
fysx 5048f3ff8c properly increased android:versionCode 2014-08-28 15:28:57 +02:00
fysx 66f600b5ab New version: 0.9.1b 2014-08-28 11:52:30 +02:00
fysx 659b312121 fixed mousepress event coordinates 2014-08-28 11:44:32 +02:00
fysx b875fffedb updated from latest love-android (228a26ab99bb) 2014-08-28 10:55:10 +02:00
fysx 45b1fc2509 fixed compilation and removed some unneeded files 2014-08-27 23:33:50 +02:00
fysx c6ac06c366 actual update to latest mobile-common 2014-08-27 23:23:26 +02:00
fysx abb819335b updated to latest mobile-common (0cf55b7da58e), removed libtiff, libpng, libmng, devil, jasper, jpeg-8d, added libturbo-jpeg 2014-08-27 23:19:11 +02:00
Martin Felis aba2f47b31 removed printing redirect tag from [LOVE2D] to [LOVE] 2014-08-18 19:04:40 +02:00
Martin Felis ea459a43da removed random text 2014-08-18 19:03:55 +02:00
Martin Felis 6110de0fa8 implemented love.system.vibrate(seconds) 2014-08-18 18:47:13 +02:00
Martin Felis 8f20cb7cc5 added print redirect to SDL_Log (fixes #40) 2014-08-18 16:23:39 +02:00
Martin Felis b25af54383 Merged in PabloMayobre/love-android-sdl2/PabloMayobre/same-as-4c481f993306-use-app_process-as-1405185954174 (pull request #3)
Same as  4c481f9933. Use 'app_process' as executable name (should fix #71 and #23)

Thanks!!
2014-07-12 21:47:41 +02:00
Pablo Mayobre c27f19c141 Same as 4c481f9933. Use 'app_process' as executable name (should fix #71 and #23) 2014-07-12 17:25:58 +00:00
fysx d1ad6cc5a3 fixed README markdown syntax 2014-07-01 17:08:55 +02:00
fysx afe33f06d2 Updated Readme for tag 0.9.1a 2014-07-01 17:06:27 +02:00
fysx 70cb26bb2a bumped version to 0.9.1a 2014-05-25 16:34:53 +02:00
fysx 8cb7bac09f using latest SDL_androidgl.c that removes some calls to eglWaitXXX() calls 2014-05-25 16:30:27 +02:00
fysx 49265f0596 using latest love-android @ changeset 8659be0e75a3 2014-05-25 16:27:34 +02:00
5036 changed files with 4878 additions and 2204665 deletions
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/love_android_sdl2/jni/love/src/scripts&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/lua"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="auto.lua boot.lua graphics.lua"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}/jni/love/src/scripts"/>
</launchConfiguration>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/love_android_sdl2/jni&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${env_var:ANDROID_NDK}/ndk-build"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-j 4"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>
</launchConfiguration>
+67
View File
@@ -0,0 +1,67 @@
name: build
on: [push, pull_request]
jobs:
build-android:
runs-on: ubuntu-latest
strategy:
matrix:
build_type: [Debug, Release]
env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs='-Xmx4G'"
steps:
- name: Prepare Environment
run: sudo apt-get update && curl -Lo kitware-archive.sh https://apt.kitware.com/kitware-archive.sh && sudo bash ./kitware-archive.sh
- name: Install Dependencies
run: sudo apt-get install ninja-build cmake
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Setup Java 17
uses: actions/setup-java@v4
with:
distribution: adopt-hotspot
java-version: 17
cache: gradle
- name: Build Normal Flavor
run: bash ./gradlew assembleNormalRecord${{ matrix.build_type }}
- name: Build Release-specific Binaries
if: ${{ matrix.build_type == 'Release' }}
run: bash ./gradlew bundleNormalNoRecordRelease bundleEmbedRecordRelease bundleEmbedNoRecordRelease
- name: Artifact (Normal debug APK)
if: ${{ matrix.build_type == 'Debug' }}
uses: actions/upload-artifact@v4
with:
name: love-android-debug.apk
path: app/build/outputs/apk/normalRecord/debug/app-normal-record-debug.apk
- name: Artifact (Normal unsigned APK)
if: ${{ matrix.build_type == 'Release' }}
uses: actions/upload-artifact@v4
with:
name: love-android.apk
path: app/build/outputs/apk/normalRecord/release/app-normal-record-release-unsigned.apk
- name: Artifact (Normal AAB w/o recording)
if: ${{ matrix.build_type == 'Release' }}
uses: actions/upload-artifact@v4
with:
name: love-android-ps.aab
path: app/build/outputs/bundle/normalNoRecordRelease/app-normal-noRecord-release.aab
- name: Artifact (Embed AAB)
if: ${{ matrix.build_type == 'Release' }}
uses: actions/upload-artifact@v4
with:
name: love-android-embed-record.aab
path: app/build/outputs/bundle/embedRecordRelease/app-embed-record-release.aab
- name: Artifact (Embed AAB w/o recording)
if: ${{ matrix.build_type == 'Release' }}
uses: actions/upload-artifact@v4
with:
name: love-android-embed.aab
path: app/build/outputs/bundle/embedNoRecordRelease/app-embed-noRecord-release.aab
- name: Artifact (Debug symbols)
uses: actions/upload-artifact@v4
with:
name: love-android-unstripped-debugsyms-${{ matrix.build_type }}
path: app/build/intermediates/cxx
+29 -26
View File
@@ -1,31 +1,34 @@
assets/
bin/
gen/
libs/
obj/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
.*.swp
.*~
*~
*.o
*.so
*.a
# Log/OS Files
*.log
!jni/LuaJIT-2.0.1/android/armeabi/libluajit.a
!jni/LuaJIT-2.0.1/android/armeabi-v7a/libluajit.a
# Android Studio generated files and folders
captures/
.externalNativeBuild/
.cxx/
*.apk
output.json
jni/LuaJIT-2.0.1/buildandroid.sh
jni/LuaJIT-2.0.1/src/host/buildvm
jni/LuaJIT-2.0.1/src/host/buildvm_arch.h
jni/LuaJIT-2.0.1/src/host/minilua
jni/LuaJIT-2.0.1/src/jit/vmdef.lua
jni/LuaJIT-2.0.1/src/libluajit.a
jni/LuaJIT-2.0.1/src/lj_bcdef.h
jni/LuaJIT-2.0.1/src/lj_ffdef.h
jni/LuaJIT-2.0.1/src/lj_folddef.h
jni/LuaJIT-2.0.1/src/lj_libdef.h
jni/LuaJIT-2.0.1/src/lj_recdef.h
jni/LuaJIT-2.0.1/src/lj_vm.s
jni/LuaJIT-2.0.1/src/luajit
# IntelliJ
*.iml
.idea/
# Keystore files
*.jks
*.keystore
# Google Services (e.g. APIs or Firebase)
google-services.json
# Android Profiling
*.hprof
# love-android specific
app/src/main/assets/
app/src/embed/assets/
+8
View File
@@ -0,0 +1,8 @@
[submodule "app/src/main/cpp/love"]
path = app/src/main/cpp/love
url = https://github.com/love2d/love
branch = main
[submodule "app/src/main/cpp/megasource"]
path = app/src/main/cpp/megasource
url = https://github.com/love2d/megasource
branch = main
-53
View File
@@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>love_android_sdl2</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/[Löve] Generate Internal Scripts.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/ndk-build.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
-4
View File
@@ -1,4 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.source=1.6
-69
View File
@@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.love2d.android"
android:versionCode="12"
android:versionName="0.9.1"
android:installLocation="auto" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Allow writing to external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="LÖVE for Android"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<service android:name=".DownloadService" />
<activity
android:name="GameActivity"
android:configChanges="orientation|screenSize"
android:label="LÖVE for Android"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="tv.ouya.intent.category.GAME"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="application/x-love-game" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.love" />
<data android:host="*" />
</intent-filter>
</activity>
<activity
android:name="DownloadActivity"
android:noHistory="true" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="*"
android:pathPrefix="*"
android:mimeType="*/*"
android:pathPattern=".*\\.love" />
<data android:scheme="https"
android:host="*"
android:pathPrefix="*"
android:mimeType="*/*"
android:pathPattern=".*\\.love" />
</intent-filter>
</activity>
</application>
<!-- Android 2.3.3 -->
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="18" />
<!-- OpenGL ES 2.0 -->
<uses-feature android:glEsVersion="0x00020000" />
</manifest>
+163 -19
View File
@@ -1,37 +1,185 @@
Android Port of LÖVE, the awesome 2D game engine LÖVE (http://love2d.org)
Copyright (c) 2013-2014 Martin Felis <martin@fysx.org>
Android Port of LÖVE, an awesome 2D game engine for Lua (http://love2d.org)
Copyright (c) 2006-2024 LOVE Development Team
![Build Status](https://github.com/love2d/love-android/workflows/build/badge.svg)
Download:
---------
You can download pre-built Android packages from https://github.com/love2d/love/releases/latest that allow
you to run .love files by opening them using a file manager of your choice.
Important:
----------
If you want to build from source, make sure to clone the submodules too. Often errors include missing
liblove.so and "Missing LÖVE" error when building. A proper way to clone this repository is:
```
git clone --recurse-submodules https://github.com/love2d/love-android
```
Add `-b <branch/tag name>` and `--depth 1` if needed.
If you already cloned the repository but forgot to initialize the submodules, execute:
```
git submodule sync --recursive
git submodule update --init --force --recursive
```
In the repository directory. For the last command, add `--depth 1` if needed.
Instructions:
-------------
For detailed instructions please refer to the [wiki](wiki).
Detailed instructions can be viewed at https://github.com/love2d/love-android/wiki
Quick Start:
------------
Install the Android NDK and the Android SDK with SDK API 12 and run
Before you start, install JDK 17 (not later not earlier). If you intend to build from Android Studio, skip this step as
Android Studio bundles its own JDK 17.
ndk-build
Install CMake version 3.21 or later in your system. Install Android SDK with SDK API 34 (34.x.y) and Android NDK
26.1.10909125, set the environment variable `ANDROID_HOME` to your Android SDK as necessary then run.
and after that
```
$ ./gradlew assembleNormalRecord
```
ant debug
in the root folder of this project. This should give you an .apk file in the `app/build/outputs/apk/normalRecord`
subdirectory that you can then sign and install on your phone. The `normalRecord` .apk variant is what you normally have
when downloading APK from https://love2d.org.
in the root folder of this project or load the project using Eclipse and
compile/run it using Eclipse.
If you want to put your game inside the APK, you can either:
This should give you a .apk file in the bin/ subdirectory that you can then
install on your phone.
1. Put all your games in `app/src/embed/assets` such that your `main.lua` path is `app/src/embed/assets/main.lua`; or
2. Put your zipped \*.love in `app/src/embed/assets` with name `game.love`
And change the application id, application version string and codes, application display name, and the icons (see
[Game Packaging Wiki](https://github.com/love2d/love-android/wiki/Game-Packaging). Afterwards,
run either `gradlew assembleEmbedNoRecordRelease` (or `gradlew assembleEmbedRecordRelease` if your game uses microphone) to
generate APK which you can install or `gradlew bundleEmbedNoRecordRelease` (or `gradlew bundleEmbedRecordRelease`) to generate
AAB which you can upload to Play Store.
Alternatively, you can install Android Studio **2022.3.1** or later. After opening it for the first time, open its SDK Manager
and on the tab "SDK Tools", tick "Show Package Details" then select NDK (Side By Side) version 26.1.10909125. After that, open
the repository root.
Notice: Previously, the embed + APKTool method is preferred, but recent announcements by Google and recent changes in Android render that method obsolete.
Bugs:
-----
Bugs and feature requests should be reported to the [issue
tracker](issues).
Bugs and/or feature requests should be reported to the issue tracker at:
* https://github.com/love2d/love-android/issues - LÖVE-Android-specific issues
* https://github.com/love2d/love/issues - for LÖVE in general
Note: If in doubt, fill an issue report to https://github.com/love2d/love/issues. We'll transfer the issue to this repository as needed.
Changelog:
----------
11.5:
* Contains all relevant changes for desktop LÖVE [11.5](https://love2d.org/wiki/11.5).
* Fixed audio in Android still playing in the background in certain cases. ([love2d/love#1828](https://github.com/love2d/love/issues/1828))
11.4:
* Contains all relevant changes for desktop LÖVE [11.4](https://love2d.org/wiki/11.4).
* Changed how LOVE looks for game due to Android restrictions.
* Fixed "pointer too large" and "bad lightuserdata" issue when compiling LOVE with recent Android SDK and running LOVE on Android 11 and later.
* For Developers: Added experimental support for 3rd-party Lua modules. Please refer to `love/src/jni/lua-modules` for more information.
* For Packaging: Added experimental fusing method. [See the FAQ for details](https://github.com/love2d/love-android/wiki/FAQ---Frequently-Asked-Questions#whats-experimental-fusing-method).
11.3:
* Contains all relevant changes for desktop LÖVE [11.3](https://love2d.org/wiki/11.3).
* Added support for microphone recording on Android. **This is disabled in Play Store builds**.
* Added t.audio.mic (`false` by default). On Android, setting it to true requests microphone recording permission from the user.
* Fixed performance regression on Android devices with Adreno GPU.
* Fixed video playback support on Android devices with Adreno GPU.
11.2:
* Contains all relevant changes for desktop LÖVE [11.2](https://love2d.org/wiki/11.2).
* Added support for ARM64 devices to comply with Play Store requirements.
* Fixed `love.system.openURL` crashing in some cases.
* Changed target SDK to 28 so it comply with Play Store requirements.
0.10.2:
* Contains all relevant changes for desktop LÖVE [0.10.2](https://love2d.org/wiki/0.10.2).
* Upgrade of SDL2 to 2.0.5 (fixes an issue with the accelerometer)
0.10.1:
* Contains all relevant changes for desktop LÖVE [0.10.1](https://love2d.org/wiki/0.10.1).
* Added a new love.conf flag t.externalstorage, which determines whether files are saved in internal or external storage on Android devices.
* Fixed audio on Android to pause when the app is inactive, and resume when the app becomes active again.
* Fixed a driver bug on some Android devices which caused all objects to show up as black.
* Fixed love.graphics.clear(colortable) causing crashes on OpenGL ES 2 systems when a Canvas is active.
* New icons
0.10.0:
* first official release!
* Disabled JIT by default as it can cause performance problems. To enable JIT call jit.on()
0.10.0-alpha2:
* Update to the next love API 0.10.0 (not yet officially released)
* Added building of libtheora
* Updated LuaJIT from 2.0.1 to 2.1
* Fixed a compatibility issue with Android 2.3 devices
* Updated libogg from 1.3.2. to 1.3.5
* Updated OpenAL to 1.17.0
* Updated SDL2 to a dev version of 2.0.4
0.9.2a:
* Added bugfix for ParticleSystem:clone
0.9.2:
* updated API to match that of LÖVE 0.9.2
* love.window.setFullscreen can be used to switch between regular and immersive mode without status and navbar
* added loading of games by opening a main.lua file
* quitting LÖVE now conforms to the Android application lifecycle
* stop vibrator when app is paused
* fixed battery drain by properly pausing OpenAL device
* fixed printing of non-number and non-string values
* fixed compilation of Android NDK r10
* fixed compilation warnings concerning ```APP_PLATFORM```
* old instance is shut down when opening a new game (note: it may crash when opening games at a high frequency, e.g. more than 2 per second)
* updated OpenAL-Soft to version 1.16.0
* updated to newer SDL version (f9244b2a151)
0.9.1b:
* added love.system.vibrate(seconds)
* print statements are now redirected to logcat. Output is prefixed with "[LOVE] "
* removed DevIL, libpng, libjpeg, libmng, and libtiff
* pngs are loaded using lodepng and jpegs using libturbo-jpeg
* repeatedly fixed a bug which caused Release builds to crash
* update to latest mobile-common branch
0.9.1a:
* using latest SDL\_androidgl.c (fixes some random performance issues)
* using latest love-android @ changeset 8659be0e75a3 (adds support for
compressed textures)
0.9.1:
* uses 0.9.1 API
* fixed crash on Moto G (and possibly other devices). This was a nasty bug that would just show a blue screen without an error message. The bug was resolved using the help of headchant
* fixed loading of jpegs (it probably hasn't worked up to now)
* fixed issues with looping over active touches. This fix was sponsored by slime!
beta2:
* fixed bug with canvases
@@ -76,9 +224,5 @@ alpha7:
License:
--------
This project contains code from multiple projects using various licenses.
Please look into the folders of jni/<projectname>/ for the respective
licenses.
As for the other code and build system files, these are published under the
zlib license (same as LÖVE).
This project contains code from multiple projects using various licenses. Please look at LOVE
[license.txt](https://github.com/love2d/love/blob/master/license.txt) for the respective licenses.
-17
View File
@@ -1,17 +0,0 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
+184
View File
@@ -0,0 +1,184 @@
import java.nio.charset.StandardCharsets
plugins {
id 'com.android.application'
}
android {
namespace "org.love2d.android"
ndkVersion '27.3.13750724'
defaultConfig {
applicationId project.properties["app.application_id"]
versionCode project.properties["app.version_code"].toInteger()
versionName project.properties["app.version_name"]
minSdk 23
compileSdk = 35
targetSdk 35
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=1", "-DCMAKE_POLICY_VERSION_MINIMUM=3.5", "-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON", "-DCMAKE_BUILD_TYPE=RelWithDebInfo"
// https://issuetracker.google.com/issues/274493986
// Transitive shared library that's added through `add_dependencies` is not taken into
// account. This result in liboboe.so and libluajit.so not get included into the final
// APK. "love" target depends on LuaJIT, and "OpenAL" target depends on oboe::oboe
// (which provides liboboe.so). So, add "OpenAL" and "love" target.
targets "love_android", "OpenAL", "love"
}
}
ndk {
//noinspection ChromeOsAbiSupport
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
debugSymbolLevel 'full'
}
def getAppName = {
def nameArray = project.properties["app.name_byte_array"]
def name = project.properties["app.name"]
if (name != null && nameArray != null) {
throw new Exception("Only define either `app.name` or `app.name_byte_array` in gradle.properties, but not both!")
}
if (name == null) {
def nameArraySplit = nameArray.split(",")
def nameBytes = new byte[nameArraySplit.length]
def count = 0
for (String s: nameArraySplit) {
nameBytes[count++] = (byte) Integer.parseInt(s)
}
return new String(nameBytes, StandardCharsets.UTF_8)
}
return name
}
manifestPlaceholders = [
NAME:getAppName(),
ORIENTATION:project.properties["app.orientation"],
]
}
def retrieveAll3pModules = { ->
def modules = []
fileTree("src/main/cpp/lua-modules/").visit { FileVisitDetails details ->
if (details.isDirectory()) {
if (file(details.file.path + "/Android.mk").exists() ||
file(details.file.path + "/CMakeLists.mk").exists()) {
def logger = project.getLogger()
logger.lifecycle("3rd-party module: " + details.file.path)
def javainfo = file(details.file.path + "/java.txt")
if (javainfo.exists()) {
def fstream = new FileInputStream(javainfo)
def infile = new BufferedReader(new InputStreamReader(fstream))
def javapath = infile.readLine().replace("\\", "/")
def mpath = null
if (javapath[0] != '/') {
mpath = details.file.path + "/" + javapath
} else {
mpath = details.file.path + javapath
}
modules << mpath
logger.lifecycle("Registered path " + mpath)
infile.close()
}
}
}
}
return modules
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
prefab true
}
flavorDimensions = ['mode', 'recording']
productFlavors {
normal {
dimension 'mode'
}
embed {
dimension 'mode'
}
record {
dimension 'recording'
}
noRecord {
dimension 'recording'
}
}
sourceSets {
main {
java {
srcDir 'src/main/cpp/megasource/libs/SDL3/android-project/app/src/main/java'
srcDir 'src/main/java'
srcDir 'src/main/cpp/love/src/libraries/luahttps/src/android/java'
srcDirs += retrieveAll3pModules()
}
}
normal {
java {
srcDir 'src/normal/java'
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
// '+' notation apparently has been supported long time ago
// https://issuetracker.google.com/issues/110693527#comment22
// We require CMake 3.21 because r23 has important fixes
// that's only fixed if CMake 3.21 is used.
// https://github.com/android/ndk/issues/463
version '3.21.0+'
}
}
packagingOptions {
jniLibs {
excludes += [
'lib/armeabi-v7a/libOpenSLES.so',
'lib/arm64-v8a/libOpenSLES.so',
'lib/x86/libOpenSLES.so',
'lib/x86_64/libOpenSLES.so'
]
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation 'androidx.navigation:navigation-fragment:2.8.5'
implementation 'androidx.navigation:navigation-ui:2.8.5'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'com.google.oboe:oboe:1.9.3'
}
// We don't even use Kotlin. Why we have to care about it?
configurations.implementation {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
+24
View File
@@ -0,0 +1,24 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class org.love2d.android.GameActivity { *; }
-keep class org.libsdl.app.** { *; }
+65
View File
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- OpenGL ES 3.0 -->
<uses-feature android:glEsVersion="0x00030000" />
<!-- Vulkan 1.1 -->
<uses-feature android:name="android.hardware.vulkan.version" android:version="0x401000" android:required="false" tools:targetApi="n" />
<!-- Touchscreen support -->
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<!-- Game controller support -->
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
<uses-feature android:name="android.hardware.gamepad" android:required="false" />
<uses-feature android:name="android.hardware.usb.host" android:required="false" />
<!-- External mouse input events -->
<uses-feature android:name="android.hardware.type.pc" android:required="false" />
<!-- Low latency audio -->
<uses-feature android:name="android.hardware.audio.low_latency" android:required="false" />
<uses-feature android:name="android.hardware.audio.pro" android:required="false" />
<application
android:allowBackup="true"
android:icon="@drawable/love"
android:label="${NAME}">
<!-- You don't have to change the activity class unless you have special needs! !-->
<activity
android:name="org.love2d.android.GameActivity"
android:exported="true"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation"
android:launchMode="singleInstance"
android:screenOrientation="${ORIENTATION}">
<!-- Allow app activity re-created -->
<meta-data android:name="SDL_ENV.SDL_ANDROID_ALLOW_RECREATE_ACTIVITY" android:value="1" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="tv.ouya.intent.category.GAME" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</activity>
<activity
android:name=".IntentReceiverActivity"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:taskAffinity=""
android:excludeFromRecents="true"
android:relinquishTaskIdentity="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.OPENABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
</manifest>
+79
View File
@@ -0,0 +1,79 @@
#
# Copyright (c) 2006-2024 LOVE Development Team
#
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
#
cmake_minimum_required(VERSION 3.21)
project(love-android LANGUAGES C CXX)
add_custom_target(love_android)
set(LOVE_ANDROID 1)
# Include Megasource and LOVE
set(MEGA_LOVE "${CMAKE_CURRENT_SOURCE_DIR}/love")
add_subdirectory(megasource)
add_dependencies(love_android love OpenAL)
find_package(Python 3.9 COMPONENTS Interpreter)
if(NOT Python_Interpreter_FOUND)
message(WARNING "No Python detected, Android.mk won't be converted to CMakeLists.txt!")
endif()
# List lua-modules
file(GLOB MODULE_LIST
LIST_DIRECTORIES TRUE
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
CONFIGURE_DEPENDS
"lua-modules/*"
)
foreach(dir ${MODULE_LIST})
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
set(has_run_cmake 0)
# Load either CMakeLists.txt or convert Android.mk to CMakeLists.txt
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir}/CMakeLists.txt")
add_subdirectory(${dir})
set(has_run_cmake 1)
elseif(Python_Interpreter_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir}/Android.mk")
get_filename_component(item_sanitized0 "${dir}" NAME)
string(REGEX REPLACE "[^\\w-]" "-" item_sanitized1 "${item_sanitized0}")
string(REGEX REPLACE "-+" "-" item "${item_sanitized0}")
message(STATUS "Converting ${dir} Android.mk to CMakeLists.txt")
execute_process(RESULT_VARIABLE status
COMMAND "${Python_EXECUTABLE}" amkparse.py convert "${item}" "${dir}/Android.mk"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_FILE "${dir}/CMakeLists.txt"
)
if("${status}" STREQUAL "0")
add_subdirectory(${dir})
set(has_run_cmake 1)
else()
message(FATAL_ERROR "amkparse.py returned ${status}")
endif()
endif()
# If CMake has been run, retrieve targets and add it as dependency
if(has_run_cmake)
get_property(defined_build_targets DIRECTORY "${dir}" PROPERTY BUILDSYSTEM_TARGETS)
get_property(defined_import_targets DIRECTORY "${dir}" PROPERTY IMPORTED_TARGETS)
add_dependencies(love_android ${defined_build_targets} ${defined_import_targets})
endif()
endif()
endforeach()
+483
View File
@@ -0,0 +1,483 @@
# Copyright (c) 2006-2024 LOVE Development Team
#
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
#
import io
import json
import os
import re
import sys
P_COMMENTS = re.compile(r"(?<!\\)#.+")
P_CONTINUATION = re.compile(r"\s*\\\r?\n\s*")
P_EMPTY_LINE = re.compile(r"\s*[\r?\n]+\s*")
P_VAR_ASSIGN = re.compile(r"([a-zA-Z_]\w*)\s*:?:?=\"?\s*(.*)\"?")
P_MULTI_WHITESPACE = re.compile(r"\s+")
P_CLEAN_VARS = re.compile(r"include\s*\$[\(\{]CLEAR_VARS[\)\}]\s*", re.MULTILINE)
P_VARIABLE_REF = re.compile(r"\$[\(\{]([a-zA-Z_]\w*)[\)\}]")
P_BUILD_TYPES = {
"executable": re.compile(r"include\s*\$[\(\{]BUILD_EXECUTABLE[\)\}]\s*", re.MULTILINE),
"shared": re.compile(r"include\s*\$[\(\{]BUILD_SHARED_LIBRARY[\)\}]\s*", re.MULTILINE),
"static": re.compile(r"include\s*\$[\(\{]BUILD_STATIC_LIBRARY[\)\}]\s*", re.MULTILINE),
"prebuilt_shared": re.compile(r"include\s*\$[\(\{]PREBUILT_SHARED_LIBRARY[\)\}]\s*", re.MULTILINE),
"prebuilt_static": re.compile(r"include\s*\$[\(\{]PREBUILT_STATIC_LIBRARY[\)\}]\s*", re.MULTILINE),
}
substitute_love_with_luajit = True
def transform_makefile(mk: str):
# Remove comments
mk = re.sub(P_COMMENTS, "", mk)
# Remove multiline declaration
mk = re.sub(P_CONTINUATION, " ", mk)
# Remove multiple newlines
mk = re.sub(P_EMPTY_LINE, "\n", mk)
mk = re.sub(P_EMPTY_LINE, "\n", mk)
# Simplify assignment
mk = re.sub(P_VAR_ASSIGN, r"\1=\2", mk)
return mk
def list_if_needed(data):
if isinstance(data, str):
return [data]
return data
def str_if_needed(data):
if isinstance(data, list):
return " ".join(data)
return data
def expand_value(value: str, variables: dict[str, str]):
def do_replace(x: re.Match[str]):
v = x.group(1)
return str_if_needed(variables.get(v, f"$({v})"))
return re.sub(P_VARIABLE_REF, do_replace, value)
def extract_variables(mk: str, variables: dict[str, str] = None):
result = {}
for match in re.finditer(P_VAR_ASSIGN, mk):
value = match.group(2).strip()
# Try convert to boolean
if value == "true" or value == "false":
value = value == "true"
# Is it array of strings?
elif value.find(" ") >= 0:
if variables:
# Expand first
value = expand_value(value, variables)
value = re.sub(P_MULTI_WHITESPACE, " ", value).split(" ")
else:
try:
# Try int conversion
value = int(value)
except ValueError:
try:
# Try float conversion
value = float(value)
except ValueError:
# Fallback default (str)
if variables:
value = expand_value(value, variables)
result[match.group(1)] = value
return result
def separate_makefiles(mk: str):
# Normalize "include $(CLEAR_VARS)"
result = re.sub(P_CLEAN_VARS, "include $(CLEAN_VARS)", mk).split("include $(CLEAN_VARS)")
# Transform makefile
result = map(transform_makefile, result)
# Remove "LOCAL_PATH"
def test_filt(x):
return x.find("LOCAL_PATH=") == -1
result = filter(test_filt, result)
return list(result)
def extract_variables_with_expand(mk: str, target_vars: dict[str, str]):
variables = extract_variables(mk, target_vars)
variables = extract_variables(mk, variables | target_vars)
return variables
def determine_build_type(mk: str):
for name, pattern in P_BUILD_TYPES.items():
if re.search(pattern, mk):
return name
return "unknown"
class CFlagsData:
def __init__(self, cflags: str):
# Variable setup
self.standard = None
self.include_paths = []
self.features = set()
self.defines = set()
self.other = []
# Parse
for flag in cflags.split():
if flag.startswith("-std="):
# std
value = flag[5:].replace("gnu++", "c++")
if value == "c99":
self.standard = 99
elif value == "c++11" or value == "c++0x" or value == "c11":
self.standard = 11
elif value == "c++14":
self.standard = 14
elif value == "c++17" or value == "c17":
self.standard = 17
elif value == "c++2a" or value == "c++20":
self.standard = 20
else:
print(f"Unknown -std: {value}", file=sys.stderr)
elif flag.startswith("-I"):
# Include paths
self.include_paths.append(flag[2:])
elif flag.startswith("-f"):
# Features
self.features.add(flag[2:])
elif flag.startswith("-D"):
# Defines
self.defines.add(flag[2:])
else:
self.other.append(flag)
@property
def unknowns(self):
return " ".join(self.others)
class LDFlagsData:
def __init__(self, ldflags: str):
# Variable setup
self.libraries = set()
self.library_paths = []
self.other = []
# Parse
for flag in ldflags.split():
if flag.startswith("-fuse-ld="):
# linker, ignore
pass
elif flag.startswith("-l"):
# Native, built-in libraries
self.libraries.add(flag[2:])
elif flag.startswith("-L"):
# Library paths
self.library_paths.append(flag[2:])
else:
self.other.append(flag)
@property
def unknowns(self):
return " ".join(self.others)
def filter_libraries(name: str):
if len(name) < 2:
return name
if name[0] == "-":
if name[1] == "l":
return name[2:]
else:
if name.startswith("lib"):
return name[3:]
return name
return ""
def get_default_output_file(name: str):
return name if name.startswith("lib") else ("lib" + name)
class SerializedMakefile:
def __init__(self, mk: str, compatsubst: bool = True):
variables = extract_variables_with_expand(mk, target_vars)
build_type = determine_build_type(mk)
# Essential
self.name = variables["LOCAL_MODULE"]
if self.name.startswith("lib"):
self.name = self.name[3:]
self.output = variables.get("LOCAL_MODULE_FILENAME", get_default_output_file(self.name))
self.type = build_type
self.sources = list_if_needed(variables["LOCAL_SRC_FILES"])
self.include = list_if_needed(variables.get("LOCAL_C_INCLUDES", []))
self.export_include = list_if_needed(variables.get("LOCAL_EXPORT_C_INCLUDES", []))
self.allow_undefined = str_if_needed(variables.get("LOCAL_ALLOW_UNDEFINED_SYMBOLS", "")).lower() == "true"
self.force_arm_code = str_if_needed(variables.get("LOCAL_ARM_MODE", "")) == "arm"
# CFlags
cflags = CFlagsData(str_if_needed(variables.get("LOCAL_CFLAGS", "")))
export_cflags = CFlagsData(str_if_needed(variables.get("LOCAL_EXPORT_CFLAGS", "")))
cppflags = CFlagsData(str_if_needed(variables.get("LOCAL_CPPFLAGS", "")))
export_cppflags = CFlagsData(str_if_needed(variables.get("LOCAL_EXPORT_CPPFLAGS", "")))
self.include.extend(cflags.include_paths)
self.include.extend(cppflags.include_paths)
self.export_include.extend(export_cflags.include_paths)
self.export_include.extend(export_cppflags.include_paths)
# C flags
self.c_standard = cflags.standard
self.c_compile_features = list(cflags.features)
self.c_compile_flags = cflags.other
self.export_c_standard = export_cflags.standard
self.export_c_compile_features = list(export_cflags.features)
self.export_c_compile_flags = export_cflags.other
# C++ flags
self.cpp_standard = cppflags.standard
self.cpp_compile_features = list(cppflags.features)
self.cpp_compile_flags = cppflags.other
self.export_cpp_standard = export_cppflags.standard
self.export_cpp_compile_features = list(export_cppflags.features)
self.export_cpp_compile_flags = export_cppflags.other
# Linker flags/libraries
link_libraries = set()
link_libraries.update(
filter_libraries(name) for name in list_if_needed(variables.get("LOCAL_SHARED_LIBRARIES", []))
)
link_libraries.update(
filter_libraries(name) for name in list_if_needed(variables.get("LOCAL_STATIC_LIBRARIES", []))
)
self.link_library_path = []
self.link_library_options = []
if build_type.find("static") == -1:
ldflags = LDFlagsData(str_if_needed(variables.get("LOCAL_LDFLAGS", "")))
ldlibs = list_if_needed(variables.get("LOCAL_LDLIBS", []))
link_libraries.update(filter_libraries(name) for name in ldlibs)
link_libraries.update(filter_libraries(name) for name in ldflags.libraries)
self.link_library_path.extend(ldflags.library_paths)
self.link_library_options.extend(ldflags.other)
self.link_libraries = list(filter(None, link_libraries))
export_ldflags = LDFlagsData(str_if_needed(variables.get("LOCAL_EXPORT_LDFLAGS", "")))
export_link_libraries = set()
export_link_libraries.update(
filter_libraries(name) for name in list_if_needed(variables.get("LOCAL_LDLIBS", []))
)
export_link_libraries.update(filter_libraries(name) for name in export_ldflags.libraries)
self.export_link_library_path = export_ldflags.library_paths
self.export_link_library_options = export_ldflags.other
self.export_link_libraries = list(filter(None, export_link_libraries))
if compatsubst:
self.link_libraries = list(map(lambda x: "luajit" if x == "love" else x, self.link_libraries))
self.export_link_libraries = list(map(lambda x: "luajit" if x == "love" else x, self.export_link_libraries))
def __iter__(self):
yield "name", self.name,
yield "output", self.output,
yield "type", self.type,
yield "allowUndefined", self.allow_undefined
yield "forceARMCode", self.force_arm_code
yield "sources", self.sources
yield "include", self.include
yield "exportInclude", self.export_include
yield "cStandard", self.c_standard
yield "cCompileFeatures", self.c_compile_features
yield "cCompileFlags", self.c_compile_flags
yield "cppStandard", self.cpp_standard
yield "cppCompileFeatures", self.cpp_compile_features
yield "cppCompileFlags", self.cpp_compile_flags
yield "exportCStandard", self.export_c_standard
yield "exportCCompileFeatures", self.export_c_compile_features
yield "exportCCompileFlags", self.export_c_compile_flags
yield "exportCppStandard", self.export_cpp_standard
yield "exportCppCompileFeatures", self.export_cpp_compile_features
yield "exportCppCompileFlags", self.export_cpp_compile_flags
yield "linkLibraries", self.link_libraries
yield "linkLibraryPath", self.link_library_path
yield "linkLibraryOptions", self.link_library_options
yield "exportLinkLibraries", self.export_link_libraries
yield "exportLinkLibraryPath", self.export_link_library_path
yield "exportLinkLibraryOptions", self.export_link_library_options
def convert_to_serialized(mk: list[str], target_vars: dict[str, str]):
result = [] # type: list[SerializedMakefile]
for mks in mk:
result.append(SerializedMakefile(mks, substitute_love_with_luajit))
return result
def convert_to_json(mk: list[str], target_vars: dict[str, str]):
return json.dumps([dict(x) for x in convert_to_serialized(mk, target_vars)])
def write_cmake(stream: io.StringIO, funcname: str, target: str, kind: str = None, props: list[str] = None):
stream.write(funcname)
stream.write("(")
stream.write(target)
if kind:
stream.write(" ")
stream.write(kind)
if props:
stream.write("\n")
for prop in props:
stream.write("\t")
stream.write(prop)
stream.write("\n")
stream.write(")\n")
def convert_to_cmake(mk: list[str], target_vars: dict[str, str], project: str):
serialized_mk = convert_to_serialized(mk, target_vars)
result = io.StringIO()
result.write("# Generated by amkparse.py\n")
result.write("# Modify if needed then remove this comment.\n")
result.write("cmake_minimum_required(VERSION 3.22)\n\n")
result.write(f"project({project} LANGUAGES C CXX)\n\n")
for s in serialized_mk:
result.write(f"#\n# {s.name}\n#\n")
if s.type.startswith("prebuilt"):
# Prebuilt needs either .so or .a
kind = "SHARED" if s.type.find("shared") != -1 else "STATIC"
write_cmake(result, "add_library", s.name, f"IMPORTED {kind}")
write_cmake(result, "set_target_properties", s.name, "PROPERTIES", [f'IMPORTED_LOCATION "{s.sources[0]}"'])
if len(s.export_include) > 0:
write_cmake(result, "target_include_directories", s.name, "INTERFACE", s.export_include)
else:
# add_library/add_executable
if s.type == "executable":
write_cmake(result, "add_executable", s.name, None, s.sources)
else:
kind = "SHARED" if s.type.find("shared") != -1 else "STATIC"
write_cmake(result, "add_library", s.name, kind, s.sources)
# set_target_properties
c_standard = s.export_c_standard or s.c_standard
cpp_standard = s.export_cpp_standard or s.cpp_standard
target_props = [f"OUTPUT_NAME {s.output}", 'PREFIX ""']
if c_standard:
target_props.append(f"C_STANDARD {c_standard}")
if cpp_standard:
target_props.append(f"CXX_STANDARD {cpp_standard}")
write_cmake(result, "set_target_properties", s.name, "PROPERTIES", target_props)
# target_include_directories PRIVATE
if len(s.include) > 0:
write_cmake(result, "target_include_directories", s.name, "PRIVATE", s.include)
# target_include_directories PUBLIC
if len(s.export_include) > 0:
write_cmake(result, "target_include_directories", s.name, "PUBLIC", s.export_include)
# target_link_directories PRIVATE
if len(s.link_library_path) > 0:
write_cmake(result, "target_link_directories", s.name, "PRIVATE", s.link_library_path)
# target_link_directories PUBLIC
if len(s.export_link_library_path) > 0:
write_cmake(result, "target_link_directories", s.name, "PUBLIC", s.export_link_library_path)
# target_link_libraries
link_libraries = None
export_link_libraries = None
if s.type.find("static") != -1:
# Merge export and non-export
export_link_libraries = set()
export_link_libraries.update(s.link_libraries)
export_link_libraries.update(s.export_link_libraries)
else:
link_libraries = s.link_libraries
export_link_libraries = s.export_link_libraries
if link_libraries:
write_cmake(result, "target_link_libraries", s.name, "PRIVATE", link_libraries)
if export_link_libraries:
write_cmake(result, "target_link_libraries", s.name, "PUBLIC", export_link_libraries)
if len(s.c_compile_flags) > 0:
print("# TODO: compile flags:", *s.c_compile_flags, file=result)
if len(s.c_compile_features) > 0:
print("# TODO: compile features:", *s.c_compile_features, file=result)
if len(s.cpp_compile_flags) > 0:
print("# TODO: compile flags cpp:", *s.cpp_compile_flags, file=result)
if len(s.cpp_compile_features) > 0:
print("# TODO: compile features cpp:", *s.cpp_compile_features, file=result)
if len(s.export_c_compile_flags) > 0:
print("# TODO: export compile flags:", *s.export_c_compile_flags, file=result)
if len(s.export_c_compile_features) > 0:
print("# TODO: export compile features:", *s.export_c_compile_features, file=result)
if len(s.export_c_compile_flags) > 0:
print("# TODO: export compile flags cpp:", *s.export_c_compile_flags, file=result)
if len(s.export_c_compile_features) > 0:
print("# TODO: export compile features cpp:", *s.export_c_compile_features, file=result)
if len(s.link_library_options) > 0:
print("# TODO: link options:", *s.link_library_options, file=result)
if len(s.export_link_library_options) > 0:
print("# TODO: export link options:", *s.export_link_library_options, file=result)
return result.getvalue()
def create_target_vars(path: str, arch: str, api: str):
if arch == "cmake":
return {
"LOCAL_PATH": "${CMAKE_CURRENT_SOURCE_DIR}",
"TARGET_ARCH": "${CMAKE_ANDROID_ARCH}",
"TARGET_ARCH_ABI": "${CMAKE_ANDROID_ARCH_ABI}",
"TARGET_PLATFORM": "android-${CMAKE_SYSTEM_NAME}",
"TARGET_ABI": "android-${CMAKE_SYSTEM_NAME}-${CMAKE_ANDROID_ARCH_ABI}",
}
if arch == "arm64" or arch == "arm64-v8a":
arch_pure = "arm64"
arch_abi = "arm64-v8a"
elif arch == "armeabi-v7a" or arch == "arm":
arch_pure = "arm"
arch_abi = "armeabi-v7a"
else:
arch_pure = arch
arch_abi = arch
return {
"LOCAL_PATH": os.path.dirname(os.path.realpath(path)).replace("\\", "/"),
"TARGET_ARCH": arch_pure,
"TARGET_ARCH_ABI": arch_abi,
"TARGET_PLATFORM": f"android-{api}",
"TARGET_ABI": f"android-{api}-{arch_abi}",
}
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
subparser = parser.add_subparsers(dest="command", required=True)
# CMake converter subparser
convert_parser = subparser.add_parser("convert")
convert_parser.add_argument("--arch", type=str, help="Target architecture", default="cmake")
convert_parser.add_argument("--api", type=int, help="Minimum Android API level", default=0)
convert_parser.add_argument("--no-compat", action="store_true", help='Don\'t change "love" to "luajit" target.')
convert_parser.add_argument("project", type=str, help="Project name")
convert_parser.add_argument("input", type=str, help="Android.mk")
# JSON dump subparser
dump_parser = subparser.add_parser("dump")
dump_parser.add_argument("arch", type=str, help="Target architecture")
dump_parser.add_argument("api", type=int, help="Minimum Android API level")
dump_parser.add_argument("input", type=str, help="Android.mk")
# Parse
args = parser.parse_args()
# Check command
if args.command == "convert":
if args.no_compat:
substitute_love_with_luajit = False
target_vars = create_target_vars(args.input, args.arch, args.api)
with open(args.input, "r", encoding="UTF-8") as f:
projects = separate_makefiles(f.read())
print(convert_to_cmake(projects, target_vars, args.project))
elif args.command == "dump":
target_vars = create_target_vars(args.input, args.arch, args.api)
with open(args.input, "r", encoding="UTF-8") as f:
projects = separate_makefiles(f.read())
print(convert_to_json(projects, target_vars))
@@ -0,0 +1,30 @@
This folder should contain external Lua C modules that will be shipped along with LOVE. One for each folder
Each folder must contains:
* Either CMakeLists.txt or Android.mk.
* If Android.mk is present:
The Android.mk will be converted to CMakeLists.txt. This conversion may not 100% perfect!
The LOCAL_MODULE_FILENAME must be set accordingly as ndk-build appends "lib" prefix from LOCAL_MODULE by default.
For Lua includes and libraries, simply link the native library with "liblove".
Note: This will convert Android.mk to CMakeLists.txt. The conversion may not 100% perfect. Conditionals are not
parsed and treated as if all codepaths are taken. Modify the generated CMakeLists.txt if necessary!
Caveat: If the library is meant to be loaded as require("my.library") then you MUST set LOCAL_MODULE_FILENAME to
my.library (with dots).
* If CMakeLists.txt is present:
The CMake script is loaded directly.
For Lua includes and libraries, link with "luajit" target.
Caveat: If the library is meant to be loaded as require("my.library") then you MUST set OUTPUT_NAME property to
"my.library" (with dots) and PREFIX property to "" (empty string) on your CMake target using
"set_target_properties".
* If your module interacts with Java-side, a file java.txt must contain where it should look Java source files.
Example, if you have src/java/your/package/name/MyFile.java, then you need to write "src/java" in java.txt.
If this file is absent, then your Java-side code will not be compiled along.
Note: There's bug in Android CMake support which prevents inclusion of imported *.so.
More information about it here: https://issuetracker.google.com/issues/274493986
In short:
* If your library is simply an imported target (or prebuilt in ndk-build terms), convert it to standard target.
Otherwise the associated *.so won't be bundled into the APK!
* If your library depends on imported/prebuilt target, you must add your CMake target to the `app/build.gradle`
as part of the targets that need to be compiled. Add your CMake target at
`android.defaultConfig.externalNativeBuild.cmake.targets` property.
@@ -0,0 +1,433 @@
/*
* Copyright (c) 2006-2024 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package org.love2d.android;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Rect;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.DisplayCutout;
import android.view.WindowManager;
import androidx.annotation.Keep;
import androidx.core.app.ActivityCompat;
import org.libsdl.app.SDLActivity;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class GameActivity extends SDLActivity {
private static final String TAG = "GameActivity";
public static final int RECORD_AUDIO_REQUEST_CODE = 3;
protected Vibrator vibrator;
protected boolean shortEdgesMode;
protected final int[] recordAudioRequestDummy = new int[1];
private Uri delayedUri = null;
private String[] args;
private boolean isFused;
private static native void nativeSetDefaultStreamValues(int sampleRate, int framesPerBurst);
@Override
protected String getMainSharedObject() {
String[] libs = getLibraries();
// Since Lollipop, you can simply pass "libname.so" to dlopen
// and it will resolve correct paths and load correct library.
// This is mandatory for extractNativeLibs=false support in
// Marshmallow.
return "lib" + libs[libs.length - 1] + ".so";
}
@Override
protected String[] getLibraries() {
return new String[]{
"c++_shared",
"SDL3",
"oboe",
"openal",
"luajit",
"liblove",
"love",
};
}
@Override
protected String[] getArguments() {
return args;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "started");
isFused = hasEmbeddedGame();
args = new String[0];
if (checkCallingOrSelfPermission(Manifest.permission.VIBRATE) == PackageManager.PERMISSION_GRANTED) {
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
}
Intent intent = getIntent();
handleIntent(intent, true);
// Prevent SDL sending filedropped event. Let us do that instead.
intent.setData(null);
super.onCreate(savedInstanceState);
if (mBrokenLibraries) {
return;
}
// Set low-latency audio values
nativeSetDefaultStreamValues(getAudioFreq(), getAudioSMP());
if (android.os.Build.VERSION.SDK_INT >= 28) {
WindowManager.LayoutParams attr = getWindow().getAttributes();
attr.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
shortEdgesMode = false;
}
if (delayedUri != null) {
// This delayed fd is only sent if an embedded game is present.
sendUriAsDroppedFile(delayedUri);
delayedUri = null;
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent, false);
}
@Override
protected void onDestroy() {
if (vibrator != null) {
Log.d(TAG, "Cancelling vibration");
vibrator.cancel();
}
super.onDestroy();
}
@Override
protected void onPause() {
if (vibrator != null) {
Log.d(TAG, "Cancelling vibration");
vibrator.cancel();
}
super.onPause();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0) {
Log.d("GameActivity", "Received a request permission result");
if (requestCode == RECORD_AUDIO_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("GameActivity", "Mic permission granted");
} else {
Log.d("GameActivity", "Did not get mic permission.");
}
Log.d("GameActivity", "Unlocking LÖVE thread");
synchronized (recordAudioRequestDummy) {
recordAudioRequestDummy[0] = grantResults[0];
recordAudioRequestDummy.notify();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
@Keep
public boolean hasEmbeddedGame() {
AssetManager am = getAssets();
InputStream inputStream;
try {
// Prioritize main.lua in assets folder
inputStream = am.open("main.lua");
} catch (IOException e) {
// Not found, try game.love in assets folder
try {
inputStream = am.open("game.love");
} catch (IOException e2) {
// Not found
return false;
}
}
try {
inputStream.close();
} catch (IOException ignored) {
}
return true;
}
@Keep
public void vibrate(double seconds) {
if (vibrator != null) {
long duration = (long) (seconds * 1000.);
if (android.os.Build.VERSION.SDK_INT >= 26) {
VibrationEffect ve = VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
vibrator.vibrate(ve);
} else {
vibrator.vibrate(duration);
}
}
}
@Keep
public boolean hasBackgroundMusic() {
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
return audioManager.isMusicActive();
}
@Keep
public String[] buildFileTree() {
// Map key is path, value is directory flag
HashMap<String, Boolean> map = buildFileTree(getAssets(), "", new HashMap<>());
ArrayList<String> result = new ArrayList<>();
for (Map.Entry<String, Boolean> data : map.entrySet()) {
result.add((data.getValue() ? "d" : "f") + data.getKey());
}
String[] r = new String[result.size()];
result.toArray(r);
return r;
}
@Keep
public float getDPIScale() {
DisplayMetrics metrics = getResources().getDisplayMetrics();
return metrics.density;
}
@Keep
public Rect getSafeArea() {
Rect rect = null;
if (android.os.Build.VERSION.SDK_INT >= 28) {
DisplayCutout cutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
if (cutout != null) {
rect = new Rect();
rect.set(
cutout.getSafeInsetLeft(),
cutout.getSafeInsetTop(),
cutout.getSafeInsetRight(),
cutout.getSafeInsetBottom()
);
}
}
return rect;
}
@Keep
public String getCRequirePath() {
ApplicationInfo applicationInfo = getApplicationInfo();
if (isNativeLibsExtracted()) {
return applicationInfo.nativeLibraryDir + "/?.so";
} else {
// The native libs are inside the APK and can be loaded directly.
// FIXME: What about split APKs?
String abi = android.os.Build.SUPPORTED_ABIS[0];
return applicationInfo.sourceDir + "!/lib/" + abi + "/?.so";
}
}
@Keep
public void setImmersiveMode(boolean enable) {
if (android.os.Build.VERSION.SDK_INT >= 28) {
WindowManager.LayoutParams attr = getWindow().getAttributes();
if (enable) {
attr.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
} else {
attr.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
}
}
shortEdgesMode = enable;
}
@Keep
public boolean getImmersiveMode() {
return shortEdgesMode;
}
@Keep
public boolean hasRecordAudioPermission() {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
}
@Keep
public void requestRecordAudioPermission() {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
return;
}
Log.d("GameActivity", "Requesting mic permission and locking LÖVE thread until we have an answer.");
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
RECORD_AUDIO_REQUEST_CODE);
synchronized (recordAudioRequestDummy) {
try {
recordAudioRequestDummy.wait();
} catch (InterruptedException e) {
Log.d("GameActivity", "requesting mic permission", e);
}
}
}
public int getAudioSMP() {
int smp = 256;
AudioManager a = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (a != null) {
int b = Integer.parseInt(a.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
smp = b > 0 ? b : smp;
}
return smp;
}
public int getAudioFreq() {
int freq = 44100;
AudioManager a = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (a != null) {
int b = Integer.parseInt(a.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
freq = b > 0 ? b : freq;
}
return freq;
}
public boolean isNativeLibsExtracted() {
ApplicationInfo appInfo = getApplicationInfo();
return (appInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0;
}
public void sendUriAsDroppedFile(Uri uri) {
SDLActivity.onNativeDropFile(uri.toString());
}
private void handleIntent(Intent intent, boolean onCreate) {
Uri game = intent.getData();
if (game == null) {
return;
}
if (onCreate) {
// Game is not running
if (isFused) {
// Send it as dropped file later
delayedUri = game;
} else {
// Process for arguments
processOpenGame(game);
}
} else {
// Game is already running. Send it as dropped file.
sendUriAsDroppedFile(game);
}
}
private HashMap<String, Boolean> buildFileTree(AssetManager assetManager, String dir, HashMap<String, Boolean> map) {
String strippedDir = dir.endsWith("/") ? dir.substring(0, dir.length() - 1) : dir;
// Try open dir
try {
InputStream test = assetManager.open(strippedDir);
// It's a file
test.close();
map.put(strippedDir, false);
} catch (FileNotFoundException e) {
// It's a directory
String[] list = null;
// List files
try {
list = assetManager.list(strippedDir);
} catch (IOException e2) {
Log.e(TAG, strippedDir, e2);
}
// Mark as file
map.put(dir, true);
if (!strippedDir.equals(dir)) {
map.put(strippedDir, true);
}
if (list != null) {
for (String path : list) {
buildFileTree(assetManager, dir + path + "/", map);
}
}
} catch (IOException e) {
Log.e(TAG, dir, e);
}
return map;
}
private void processOpenGame(Uri game) {
String scheme = game.getScheme();
String path = game.getPath();
if (scheme != null) {
if (scheme.equals("content")) {
// Pass content URI as-is.
args = new String[]{game.toString()};
} else if (scheme.equals("file")) {
// Regular file, pass as-is.
args = new String[]{path};
}
}
}
}
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2006-2024 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package org.love2d.android;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.Nullable;
import java.util.Objects;
public class IntentReceiverActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent mainIntent = getIntent();
Intent intent = new Intent(this, GameActivity.class);
if (Objects.equals(mainIntent.getAction(), Intent.ACTION_SEND)) {
// Convert to simpler intent that our GameActivity can process.
Uri uri = mainIntent.getParcelableExtra(Intent.EXTRA_STREAM);
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivity(intent);
finish();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+46
View File
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application android:icon="@drawable/love">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat.DayNight">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
Important: GameActivity class name MUST be explicitly written as
"org.love2d.android.GameActivity" without any shortcuts.
-->
<activity
android:name="org.love2d.android.GameActivity"
android:exported="false"
tools:replace="android:exported">
<intent-filter tools:node="removeAll" />
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</activity>
<activity
android:name=".AboutActivity"
android:exported="false"
android:parentActivityName=".MainActivity"
android:theme="@style/Theme.AppCompat.DayNight" />
<provider
android:name="org.love2d.android.LoveDocumentsProvider"
android:authorities="${applicationId}.documents"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
</application>
</manifest>
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2006-2024 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package org.love2d.android;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class AboutActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
// Set button click listener
Button button = findViewById(R.id.button);
button.setOnClickListener(v -> {
Uri uri = Uri.parse("https://love2d.org/");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
});
// Set version
try {
String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
TextView versionText = findViewById(R.id.textView4);
versionText.setText(getString(R.string.version_info, version));
} catch (PackageManager.NameNotFoundException ignored) {
}
}
}
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2006-2024 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package org.love2d.android;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.io.File;
public class GameListAdapter extends RecyclerView.Adapter<GameListAdapter.ViewHolder> {
private Data[] data = null;
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_game, parent, false);
ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(holder);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setData(this.data[position]);
}
@Override
public int getItemCount() {
return data != null ? data.length : 0;
}
public void setData(Data[] data) {
this.data = data;
}
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final TextView name;
private final ImageView image;
private File file;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.textView);
image = itemView.findViewById(R.id.imageView);
}
public void setData(Data data) {
name.setText(data.path.getName());
image.setImageResource(data.directory ? R.drawable.ic_baseline_folder_32 : R.drawable.ic_baseline_insert_drive_file_32);
file = data.path;
}
@Override
public void onClick(View v) {
if (file == null) {
return;
}
Context context = v.getContext();
Intent intent = new Intent(context, GameActivity.class);
intent.setData(Uri.fromFile(file));
context.startActivity(intent);
}
}
static class Data {
// Absolute path of the file.
public File path;
// Denote if this game is a directory.
public boolean directory;
}
}
@@ -0,0 +1,656 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.
*/
/*
* Modified for use with LOVE by the LOVE Development Team
* Copyright (C) 2024 LOVE Development Team
*/
package org.love2d.android;
import static android.os.Build.VERSION.SDK_INT;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Point;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import android.util.Log;
import android.webkit.MimeTypeMap;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Objects;
import java.util.PriorityQueue;
/**
* Manages documents and exposes them to the Android system for sharing.
*/
public class LoveDocumentsProvider extends DocumentsProvider {
private static final String TAG = "LoveDocumentsProvider";
// Use these as the default columns to return information about a root if no specific
// columns are requested in a query.
private static final String[] DEFAULT_ROOT_PROJECTION = new String[]{
Root.COLUMN_ROOT_ID,
Root.COLUMN_MIME_TYPES,
Root.COLUMN_FLAGS,
Root.COLUMN_ICON,
Root.COLUMN_TITLE,
Root.COLUMN_SUMMARY,
Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES
};
// Use these as the default columns to return information about a document if no specific
// columns are requested in a query.
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[]{
Document.COLUMN_DOCUMENT_ID,
Document.COLUMN_MIME_TYPE,
Document.COLUMN_DISPLAY_NAME,
Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_FLAGS,
Document.COLUMN_SIZE
};
// No official policy on how many to return, but make sure you do limit the number of recent
// and search results.
private static final int MAX_SEARCH_RESULTS = 20;
private static final int MAX_LAST_MODIFIED = 5;
private static final String ROOT = "root";
// This file is the base of our root
private File mBaseDir;
@Override
public boolean onCreate() {
Log.v(TAG, "onCreate");
mBaseDir = Objects.requireNonNull(getContext()).getExternalFilesDir(null);
return true;
}
@Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
Log.v(TAG, "queryRoots");
// Create a cursor with either the requested fields, or the default projection. This
// cursor is returned to the Android system picker UI and used to display all roots from
// this provider.
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
// It's possible to have multiple roots
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, ROOT);
row.add(Root.COLUMN_SUMMARY, null);
// FLAG_SUPPORTS_CREATE means at least one directory under the root supports creating
// documents. FLAG_SUPPORTS_RECENTS means your application's most recently used
// documents will show up in the "Recents" category. FLAG_SUPPORTS_SEARCH allows users
// to search all documents the application shares. FLAG_SUPPORTS_IS_CHILD allows
// testing parent child relationships, available after SDK 21 (Lollipop).
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE |
Root.FLAG_SUPPORTS_RECENTS |
Root.FLAG_SUPPORTS_SEARCH |
Root.FLAG_SUPPORTS_IS_CHILD);
// COLUMN_TITLE is the root title (e.g. what will be displayed to identify your provider).
row.add(Root.COLUMN_TITLE, Objects.requireNonNull(getContext()).getApplicationInfo().loadLabel(getContext().getPackageManager()).toString());
// This document id must be unique within this provider and consistent across time. The
// system picker UI may save it and refer to it later.
row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(mBaseDir));
// The child MIME types are used to filter the roots and only present to the user roots
// that contain the desired type somewhere in their file hierarchy.
row.add(Root.COLUMN_MIME_TYPES, "*/*");
row.add(Root.COLUMN_AVAILABLE_BYTES, mBaseDir.getFreeSpace());
row.add(Root.COLUMN_ICON, R.drawable.love);
return result;
}
@Override
public Cursor queryRecentDocuments(String rootId, String[] projection)
throws FileNotFoundException {
Log.v(TAG, "queryRecentDocuments");
// This implementation walks a local file structure to find the most recently
// modified files.
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(rootId);
// Create a queue to store the most recent documents, which orders by last modified.
PriorityQueue<File> lastModifiedFiles = new PriorityQueue<File>(5, new Comparator<File>() {
public int compare(File i, File j) {
return Long.compare(i.lastModified(), j.lastModified());
}
});
// Iterate through all files and directories in the file structure under the root. If
// the file is more recent than the least recently modified, add it to the queue,
// limiting the number of results.
final LinkedList<File> pending = new LinkedList<File>();
// Start by adding the parent to the list of files to be processed
pending.add(parent);
// Do while we still have unexamined files
while (!pending.isEmpty()) {
// Take a file from the list of unprocessed files
final File file = pending.removeFirst();
if (file.isDirectory()) {
// If it's a directory, add all its children to the unprocessed list
File[] files = file.listFiles();
if (files != null) {
Collections.addAll(pending, files);
}
} else {
// If it's a file, add it to the ordered queue.
lastModifiedFiles.add(file);
}
}
// Add the most recent files to the cursor, not exceeding the max number of results.
int includedCount = 0;
while (includedCount < MAX_LAST_MODIFIED + 1 && !lastModifiedFiles.isEmpty()) {
final File file = lastModifiedFiles.remove();
includeFile(result, null, file);
includedCount++;
}
return result;
}
@Override
public Cursor querySearchDocuments(String rootId, String query, String[] projection)
throws FileNotFoundException {
Log.v(TAG, "querySearchDocuments");
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(rootId);
// This implementation searches file names for the query and doesn't rank search
// results, so we can stop as soon as we find a sufficient number of matches. Other
// implementations might use other data about files, rather than the file name, to
// produce a match;
// Iterate through all files in the file structure under the root until we reach the
// desired number of matches.
final LinkedList<File> pending = new LinkedList<File>();
// Start by adding the parent to the list of files to be processed
pending.add(parent);
// Do while we still have unexamined files, and fewer than the max search results
while (!pending.isEmpty() && result.getCount() < MAX_SEARCH_RESULTS) {
// Take a file from the list of unprocessed files
final File file = pending.removeFirst();
if (file.isDirectory()) {
// If it's a directory, add all its children to the unprocessed list
File[] files = file.listFiles();
if (files != null) {
Collections.addAll(pending, files);
}
} else {
// If it's a file and it matches, add it to the result cursor.
if (file.getName().toLowerCase().contains(query)) {
includeFile(result, null, file);
}
}
}
return result;
}
@Override
public AssetFileDescriptor openDocumentThumbnail(String documentId, Point sizeHint,
CancellationSignal signal)
throws FileNotFoundException {
Log.v(TAG, "openDocumentThumbnail");
final File file = getFileForDocId(documentId);
final ParcelFileDescriptor pfd =
ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
}
@Override
public Cursor queryDocument(String documentId, String[] projection)
throws FileNotFoundException {
Log.v(TAG, "queryDocument");
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
includeFile(result, documentId, null);
return result;
}
@Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
String sortOrder) throws FileNotFoundException {
Log.v(TAG, "queryChildDocuments, parentDocumentId: " +
parentDocumentId +
" sortOrder: " +
sortOrder);
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(parentDocumentId);
File[] files = parent.listFiles();
if (files != null) {
for (File file : files) {
includeFile(result, null, file);
}
}
return result;
}
@Override
public ParcelFileDescriptor openDocument(final String documentId, final String mode, CancellationSignal signal) throws FileNotFoundException {
Log.v(TAG, "openDocument, mode: " + mode);
final File file = getFileForDocId(documentId);
final int accessMode = ParcelFileDescriptor.parseMode(mode);
return ParcelFileDescriptor.open(file, accessMode);
}
public boolean isChildFile(File parentFile, File childFile) {
File realFileParent = childFile.getParentFile();
return realFileParent == null || realFileParent.equals(parentFile);
}
@Override
public boolean isChildDocument(String parentDocumentId, String documentId) {
Log.v(TAG, "isChildDocument");
return documentId.startsWith(parentDocumentId);
}
@Override
public String createDocument(String documentId, String mimeType, String displayName)
throws FileNotFoundException {
Log.v(TAG, "createDocument");
File parent = getFileForDocId(documentId);
File file = new File(parent.getPath(), displayName);
int conflictId = 1;
while (file.exists()) {
file = new File(parent.getPath(), displayName + "(" + conflictId++ + ")");
}
try {
// Create the new File to copy into
boolean wasNewFileCreated = false;
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
wasNewFileCreated = file.mkdir();
} else {
wasNewFileCreated = file.createNewFile();
}
if (!wasNewFileCreated) {
throw new FileNotFoundException("Failed to create document with name " +
displayName + " and documentId " + documentId);
}
} catch (IOException e) {
throw new FileNotFoundException("Failed to create document with name " +
displayName + " and documentId " + documentId);
}
return getDocIdForFile(file);
}
@Override
public String renameDocument(String documentId, String displayName)
throws FileNotFoundException {
Log.v(TAG, "renameDocument");
if (displayName == null) {
throw new FileNotFoundException("Failed to rename document, new name is null");
}
// Create the destination file in the same directory as the source file
File sourceFile = getFileForDocId(documentId);
File sourceParentFile = sourceFile.getParentFile();
if (sourceParentFile == null) {
throw new FileNotFoundException("Failed to rename document. File has no parent.");
}
File destFile = new File(sourceParentFile.getPath(), displayName);
// Try to do the rename
try {
boolean renameSucceeded = sourceFile.renameTo(destFile);
if (!renameSucceeded) {
throw new FileNotFoundException("Failed to rename document. Renamed failed.");
}
} catch (Exception e) {
Log.w(TAG, "Rename exception : " + e.getLocalizedMessage() + e.getCause());
throw new FileNotFoundException("Failed to rename document. Error: " + e.getMessage());
}
return getDocIdForFile(destFile);
}
@Override
public void deleteDocument(String documentId) throws FileNotFoundException {
Log.v(TAG, "deleteDocument");
File file = getFileForDocId(documentId);
if (file.delete()) {
Log.i(TAG, "Deleted file with id " + documentId);
} else {
throw new FileNotFoundException("Failed to delete document with id " + documentId);
}
}
@Override
public void removeDocument(String documentId, String parentDocumentId)
throws FileNotFoundException {
Log.v(TAG, "removeDocument");
File parent = getFileForDocId(parentDocumentId);
File file = getFileForDocId(documentId);
if (file == null) {
throw new FileNotFoundException("Failed to delete document with id " + documentId);
}
// removeDocument is the same as deleteDocument but allows the parent to be specified
// Check here if the specified parentDocumentId matches the true parent of documentId
boolean doesFileParentMatch = false;
File fileParent = file.getParentFile();
if (fileParent == null || fileParent.equals(parent)) {
doesFileParentMatch = true;
}
// Remove the file if parent matches or file and parent are equal
if (parent.equals(file) || doesFileParentMatch) {
if (file.delete()) {
Log.i(TAG, "Deleted file with id " + documentId);
} else {
throw new FileNotFoundException("Failed to delete document with id " + documentId);
}
} else {
throw new FileNotFoundException("Failed to delete document with id " + documentId);
}
}
/**
* overload copyDocument to insist that the parent matches
*/
public String copyDocument(String sourceDocumentId, String sourceParentDocumentId,
String targetParentDocumentId) throws FileNotFoundException {
Log.v(TAG, "copyDocument with document parent");
if (!isChildDocument(sourceParentDocumentId, sourceDocumentId)) {
throw new FileNotFoundException("Failed to copy document with id " +
sourceDocumentId + ". Parent is not: " + sourceParentDocumentId);
}
return copyDocument(sourceDocumentId, targetParentDocumentId);
}
@Override
public String copyDocument(String sourceDocumentId, String targetParentDocumentId)
throws FileNotFoundException {
Log.v(TAG, "copyDocument");
File parent = getFileForDocId(targetParentDocumentId);
File oldFile = getFileForDocId(sourceDocumentId);
File newFile = new File(parent.getPath(), oldFile.getName());
try {
int conflictId = 1;
while (newFile.exists()) {
newFile = new File(parent.getPath(), oldFile.getName() + "(" + conflictId++ + ")");
}
// Create the new File to copy into
boolean wasNewFileCreated = false;
boolean isDirectory = Document.MIME_TYPE_DIR.equals(getTypeForFile(oldFile));
if (isDirectory) {
if (newFile.mkdir()) {
if (newFile.setWritable(true) && newFile.setReadable(true)) {
wasNewFileCreated = true;
}
}
} else {
if (newFile.createNewFile()) {
if (newFile.setWritable(true) && newFile.setReadable(true)) {
wasNewFileCreated = true;
}
}
}
if (!wasNewFileCreated) {
throw new FileNotFoundException("Failed to copy document " + sourceDocumentId +
". Could not create new file.");
}
if (!isDirectory) {
// Copy the bytes into the new file
try (FileInputStream inStream = new FileInputStream(oldFile)) {
try (FileOutputStream outStream = new FileOutputStream(newFile)) {
// Transfer bytes from in to out
byte[] buf = new byte[16384]; // disk: 8-64k
int len;
while ((len = inStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
}
}
}
} catch (IOException e) {
throw new FileNotFoundException("Failed to copy document: " + sourceDocumentId +
". " + e.getMessage());
}
return getDocIdForFile(newFile);
}
@Override
public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
String targetParentDocumentId) throws FileNotFoundException {
Log.v(TAG, "moveDocument");
try {
// Copy document, insisting that the parent is correct
String newDocumentId = copyDocument(sourceDocumentId, sourceParentDocumentId,
targetParentDocumentId);
// Remove old document
removeDocument(sourceDocumentId, sourceParentDocumentId);
return newDocumentId;
} catch (FileNotFoundException e) {
throw new FileNotFoundException("Failed to move document " + sourceDocumentId);
}
}
@Override
public String getDocumentType(String documentId) throws FileNotFoundException {
File file = getFileForDocId(documentId);
return getTypeForFile(file);
}
/**
* @param projection the requested root column projection
* @return either the requested root column projection, or the default projection if the
* requested projection is null.
*/
private static String[] resolveRootProjection(String[] projection) {
return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
}
private static String[] resolveDocumentProjection(String[] projection) {
return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
}
/**
* Get a file's MIME type
*
* @param file the File object whose type we want
* @return the MIME type of the file
*/
private static String getTypeForFile(File file) {
if (file.isDirectory()) {
return Document.MIME_TYPE_DIR;
} else {
return getTypeForName(file.getName());
}
}
/**
* Get the MIME data type of a document, given its filename.
*
* @param name the filename of the document
* @return the MIME data type of a document
*/
private static String getTypeForName(String name) {
final int lastDot = name.lastIndexOf('.');
if (lastDot >= 0) {
final String extension = name.substring(lastDot + 1);
if (extension.equals("love")) {
return "application/x-love-game";
}
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mime != null) {
return mime;
}
}
return "application/octet-stream";
}
/**
* Get the document ID given a File. The document id must be consistent across time. Other
* applications may save the ID and use it to reference documents later.
* <p/>
* This implementation is specific to this demo. It assumes only one root and is built
* directly from the file structure. However, it is possible for a document to be a child of
* multiple directories (for example "android" and "images"), in which case the file must have
* the same consistent, unique document ID in both cases.
*
* @param file the File whose document ID you want
* @return the corresponding document ID
*/
private String getDocIdForFile(File file) {
String path = file.getAbsolutePath();
// Start at first char of path under root
final String rootPath = mBaseDir.getPath();
if (rootPath.equals(path)) {
path = "";
} else if (rootPath.endsWith("/")) {
path = path.substring(rootPath.length());
} else {
path = path.substring(rootPath.length() + 1);
}
return ROOT + ':' + path;
}
/**
* Add a representation of a file to a cursor.
*
* @param result the cursor to modify
* @param docId the document ID representing the desired file (may be null if given file)
* @param file the File object representing the desired file (may be null if given docID)
*/
private void includeFile(MatrixCursor result, String docId, File file)
throws FileNotFoundException {
if (docId == null) {
docId = getDocIdForFile(file);
} else {
file = getFileForDocId(docId);
}
int flags = 0;
if (file.isDirectory()) {
// Add FLAG_DIR_SUPPORTS_CREATE if the file is a writable directory.
if (file.isDirectory() && file.canWrite()) {
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
}
} else if (file.canWrite()) {
// If the file is writable set FLAG_SUPPORTS_WRITE and
// FLAG_SUPPORTS_DELETE
flags |= Document.FLAG_SUPPORTS_WRITE;
flags |= Document.FLAG_SUPPORTS_DELETE;
flags |= Document.FLAG_SUPPORTS_RENAME;
if (SDK_INT >= Build.VERSION_CODES.N) {
flags |= Document.FLAG_SUPPORTS_REMOVE;
flags |= Document.FLAG_SUPPORTS_MOVE;
flags |= Document.FLAG_SUPPORTS_COPY;
}
}
final String displayName = file.getName();
final String mimeType = getTypeForFile(file);
if (mimeType.startsWith("image/")) {
// Allow the image to be represented by a thumbnail rather than an icon
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
}
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Document.COLUMN_DOCUMENT_ID, docId);
if (file.getAbsolutePath().equals(mBaseDir.getAbsolutePath())) {
row.add(Document.COLUMN_DISPLAY_NAME, Objects.requireNonNull(getContext()).getApplicationInfo().loadLabel(getContext().getPackageManager()).toString());
} else {
row.add(Document.COLUMN_DISPLAY_NAME, displayName);
}
row.add(Document.COLUMN_SIZE, file.length());
row.add(Document.COLUMN_MIME_TYPE, mimeType);
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
row.add(Document.COLUMN_FLAGS, flags);
// Add a custom icon
if (mimeType.equals("application/x-love-game")) {
row.add(Document.COLUMN_ICON, R.drawable.love);
} else {
row.add(Document.COLUMN_ICON, null);
}
}
/**
* Translate your custom URI scheme into a File object.
*
* @param docId the document ID representing the desired file
* @return a File represented by the given document ID
*/
private File getFileForDocId(String docId) throws FileNotFoundException {
File target = mBaseDir;
if (docId.equals(ROOT)) {
return target;
}
final int splitIndex = docId.indexOf(':', 1);
if (splitIndex < 0) {
throw new FileNotFoundException("Missing root for " + docId);
} else {
final String path = docId.substring(splitIndex + 1);
target = new File(target, path);
if (!target.exists()) {
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
}
return target;
}
}
}
@@ -0,0 +1,225 @@
/*
* Copyright (c) 2006-2024 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package org.love2d.android;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.zip.ZipFile;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private final Executor executor = Executors.newSingleThreadExecutor();
private final ActivityResultLauncher<String[]> openFileLauncher = registerForActivityResult(
new ActivityResultContracts.OpenDocument(),
(Uri result) -> {
if (result != null) {
Intent intent = new Intent(this, GameActivity.class);
intent.setData(result);
startActivity(intent);
}
}
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
SwipeRefreshLayout swipeLayout = findViewById(R.id.swipeRefreshLayout);
ConstraintLayout noGameText = findViewById(R.id.constraintLayout);
GameListAdapter adapter = new GameListAdapter();
// Set refresh listener
swipeLayout.setOnRefreshListener(() -> {
scanGames(adapter, noGameText, swipeLayout);
});
// Set layout manager and adapter
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
scanGames(adapter, noGameText, null);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
// Handle item selection
if (itemId == R.id.optionItem) {
openFileLauncher.launch(new String[]{"*/*"});
return true;
} else if (itemId == R.id.optionItem2) {
Intent intent = new Intent(this, GameActivity.class);
startActivity(intent);
return true;
} else if (itemId == R.id.optionItem3) {
getGameFolderDialog().show();
return true;
} else if (itemId == R.id.optionItem4) {
Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private AlertDialog getGameFolderDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(getString(R.string.game_folder))
.setPositiveButton(R.string.ok, (dialog1, which) -> {
});
StringBuilder message = new StringBuilder()
.append(getString(R.string.game_folder_location, getPackageName()))
.append("\n\n");
if (Build.VERSION.SDK_INT >= 30) {
message.append(getString(R.string.game_folder_inaccessible));
} else {
message.append(getString(R.string.game_folder_accessible));
}
return builder.setMessage(message.toString()).create();
}
@SuppressLint("NotifyDataSetChanged")
private void scanGames(GameListAdapter adapter, ConstraintLayout noGameText, SwipeRefreshLayout swipeRefreshLayout) {
executor.execute(() -> {
File extDir = getExternalFilesDir("games");
if (extDir != null) {
if (!extDir.isDirectory()) {
if (!extDir.mkdir()) {
// Scan failure, abort
runOnUiThread(() -> {
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(false);
}
});
Log.e(TAG, "Directory creation failure.");
return;
}
}
ArrayList<GameListAdapter.Data> validGames = new ArrayList<>();
File[] files = extDir.listFiles();
if (files != null) {
for (File file : files) {
GameListAdapter.Data gameData = null;
if (file.isDirectory()) {
if (isValidGamedir(file)) {
gameData = new GameListAdapter.Data();
gameData.path = file;
gameData.directory = true;
}
} else {
if (isValidLovegame(file)) {
gameData = new GameListAdapter.Data();
gameData.path = file;
gameData.directory = false;
}
}
if (gameData != null) {
validGames.add(gameData);
}
}
}
boolean empty = validGames.isEmpty();
runOnUiThread(() -> {
if (empty) {
adapter.setData(null);
} else {
GameListAdapter.Data[] gameDatas = new GameListAdapter.Data[validGames.size()];
validGames.toArray(gameDatas);
adapter.setData(gameDatas);
}
adapter.notifyDataSetChanged();
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(false);
}
noGameText.setVisibility(empty ? View.VISIBLE : View.INVISIBLE);
});
}
});
}
public static boolean isValidLovegame(File file) {
boolean valid = false;
try {
ZipFile zip = new ZipFile(file, ZipFile.OPEN_READ);
valid = zip.getEntry("main.lua") != null;
zip.close();
} catch (IOException ignored) {
}
return valid;
}
public static boolean isValidGamedir(File file) {
File mainLua = new File(file, "main.lua");
return mainLua.isFile();
}
}
@@ -0,0 +1,5 @@
<vector android:height="32dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
</vector>
@@ -0,0 +1,5 @@
<vector android:height="32dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
</vector>
@@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="32dp"
android:tint="?attr/colorControlNormal" android:viewportHeight="24"
android:viewportWidth="24" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"/>
</vector>
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
tools:context=".AboutActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.35" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:adjustViewBounds="true"
app:layout_constraintBottom_toTopOf="@+id/guideline1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_max="160dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
app:srcCompat="@drawable/love" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="LÖVE for Android"
android:textSize="29sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline1" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/version_info"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="@string/copyright"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:text="@string/disclaimer"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/official_website"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView7" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/row_game">
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_games"
android:textSize="29sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_horizontal"
android:text="@string/no_games_info"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:padding="16dp"
android:focusable="true">
<ImageView
android:id="@+id/imageView"
android:layout_width="24dp"
android:layout_height="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_baseline_insert_drive_file_32"
app:tint="#000000" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="TextView"
android:textColor="#DE000000"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/optionItem"
android:title="@string/open_love_file" />
<item
android:id="@+id/optionItem2"
android:title="@string/launch_nogame" />
<item
android:id="@+id/optionItem3"
android:title="@string/game_folder" />
<item
android:id="@+id/optionItem4"
android:title="@string/about" />
</menu>
+16
View File
@@ -0,0 +1,16 @@
<resources>
<string name="version_info">Version %1$s</string>
<string name="copyright">Copyright © 20062024 LÖVE Development Team</string>
<string name="disclaimer">This software is provided \'as-is\', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.</string>
<string name="official_website">Official Website</string>
<string name="no_games">No Games :(</string>
<string name="no_games_info">Looks like there are no LÖVE games found in the games folder. See the \"Game Folder\" in the options menu for more information.</string>
<string name="open_love_file">Open .love File</string>
<string name="launch_nogame">Launch No-Game</string>
<string name="game_folder">Game Folder</string>
<string name="about">About</string>
<string name="ok">OK</string>
<string name="game_folder_location">The game folder is located in your internal storage at Android/data/%1$s/files/games.</string>
<string name="game_folder_accessible">The folder should be accessible with your favorite file manager.</string>
<string name="game_folder_inaccessible">Unfortunately the folder is only accessible through MTP in PC.</string>
</resources>
+13
View File
@@ -0,0 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:9.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
-17
View File
@@ -1,17 +0,0 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked in Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
-93
View File
@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This should be changed to the name of your project -->
<project name="love_android_sdl2" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
-11
View File
@@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-19
@@ -0,0 +1,33 @@
Additions:
• Added "LÖVE Loader" launcher on Android for easier loading of .love files.
Other Changes:
• Changed iOS game selector to alphabetically sort the list of .love files.
• Changed JIT compilation on macOS arm64 (Apple Silicon) to be off by default, since performance and available JIT memory isn't reliable.
Fixes:
• Fixed inconsistent and buggy behaviour of 'pairs' by updating LuaJIT.
• Fixed "unexpected alignment" errors when running love on some 32 bit Linux systems.
• Fixed running fused games on Windows when the executable has been code-signed.
• Fixed undefined behaviour in love.data.hash's implementation.
• Fixed writing files when a symlink exists in the save directory's path.
• Fixed love.threaderror not being called if the error message is an empty string.
• Fixed a race condition when a Thread is destroyed immediately after Thread:start.
• Fixed unexpectedly slow first frames on macOS.
• Fixed love.joystick.setGamepadMapping when replacing an existing mapping.
• Fixed love.joystick.getGamepadMappingString.
• Fixed duplicate platform fields in love.joystick.saveGamepadMappings.
• Fixed DistanceJoint type information.
• Fixed time drift in Source:tell after a Source loops.
• Fixed audio not always pausing when the app is minimized on Android.
• Fixed RecordingDevice:start to return false instead of hard-crashing on iOS.
• Fixed identical frames in Ogg Theora videos being skipped.
• Fixed love.font.newBMFontRasterizer's single file parameter variant.
• Fixed the original window size not always being restored when exiting fullscreen on Linux.
• Fixed some cases of framerate hitches in Windows when vsync is enabled in windowed mode.
• Fixed colors appearing over-saturated on P3 displays in macOS.
• Fixed textures looking washed out when gamma-correct rendering is used on some Android devices.
• Fixed images with mipmaps when ANGLE is used with an AMD GPU.
• Fixed line rendering when duplicate points are used in the line.
• Fixed line rendering with miter and bevel line join modes when antiparallel lines are formed.
• Fixed a crash when calling Text:add with an empty string parameter.
@@ -0,0 +1,142 @@
Additions:
• Added support for launching a specific .lua file as the main file.
• Added basic usage instructions printed to the console when '--help' is used as a command-line parameter, and when the no-game screen is run.
• Added love.parsedGameArguments and love.rawGameArguments tables, in the main thread.
• Added love.markDeprecated.
• Added HTTPS Lua module.
• Added love.event.restart(optionalvalue). A new love.restart field will contain the value after restarting.
• Added love.system.getPreferredLocales.
• Added love.localechanged callback.
• Added love.audiodisconnected callback.
• Added love.filesystem.mountFullPath and love.filesystem.unmountFullPath, including opt-in mount-for-write support.
• Added love.filesystem.mountCommonPath, unmountCommonPath, and getFullCommonPath.
• Added 'readonly' field to love.filesystem.getInfo's returned table.
• Added love.filesystem.openFile (replaces love.filesystem.newFile).
• Added an optional load mode parameter to love.filesystem.load whetever to only allow binary chunks, text chunks, or both.
• Added love.math.perlinNoise and love.math.simplexNoise (replaces love.math.noise).
• Added SoundData:copyFrom.
• Added SoundData:slice.
• Added optional stream type parameter to love.audio.newSource streaming sources ("file" or "memory"). It defaults to "file".
• Added love.audio.getPlaybackDevice, love.audio.getPlaybackDevices, and love.audio.setPlaybackDevice.
• Added love.keyboard.isModifierActive.
• Added Joystick:setPlayerIndex and Joystick:getPlayerIndex.
• Added Joystick:getJoystickType.
• Added Joystick:getGamepadType.
• Added Joystick:hasSensor.
• Added Joystick:isSensorEnabled and Joystick:setSensorEnabled.
• Added Joystick:getSensorData.
• Added new Gamepad API buttons: "misc1", "paddle1", "paddle2", "paddle3", "paddle4". and "touchpad".
• Added World:getFixturesInArea().
• Added support for saving .exr image files via ImageData:encode.
• Added a Metal backend to love.graphics, available on macOS 10.15+ and iOS 13+.
• Added a Vulkan backend to love.graphics, available on Windows, Linux, and Android 7+.
• Added '--renderers a,b,c' and '--excluderenderers a,b,c' command line arguments.
• Added t.renderers and t.excluderenderers love.conf options.
• Added t.highdpi startup flag in love.conf, replacing t.window.highdpi and the highdpi flag of love.window.setMode.
• Added support for highdpi mode in Windows.
• Added per-shader opt in support for the GLSL 4.30 (desktop) and GLSL ES 3.20 (mobile) shading languages, via #pragma language glsl4.
• Added compile options table parameter to love.graphics.newShader. Allows setting #define values via newShader.
• Added love.graphics.newTexture. newImage and newCanvas still exist as convenience constructor functions.
• Added optional 'mipmapcount' field to the settings table in newTexture/newImage/newCanvas.
• Added optional 'computewrite' boolean field to the settings table in newTexture/newImage/newCanvas.
• Added love.graphics.getTextureFormats, which replaces getImageFormats and getCanvasFormats.
• Added Texture:isCanvas and Texture:isComputeWritable.
• Added Texture:isFormatLinear, Texture:getMSAA, Texture:generateMipmaps, Texture:replacePixels, and Texture:renderTo (moved from old Canvas and Image subclasses).
• Added integer pixel formats for Textures and ImageData.
• Added Graphics Buffer objects, including vertex, index, texel, shader storage, and indirect draw/dispatch argument buffers.
• Added love.graphics.copyBuffer, copyBufferToTexture, and copyTextureToBuffer.
• Added APIs for interacting with the Buffer objects owned by Meshes.
• Added Mesh:getAttachedAttributes.
• Added an optional start array index parameter to Mesh:attachAttribute.
• Added integer buffer data formats.
• Added love.graphics.readbackTexture and love.graphics.readbackTextureAsync (replaces Texture:newImageData).
• Added love.graphics.readbackBuffer and love.graphics.readbackBufferAsync.
• Added 'readback' buffer data usage enum, useful for advanced memory optimization when using love.graphics.readbackBuffer.
• Added new lower level 'vertexmain' and 'pixelmain' shader entry points.
• Added Compute Shader support via love.graphics.newComputeShader and a new 'computemain' shader entry point.
• Added love.graphics.dispatchThreadgroups and love.graphics.dispatchIndirect for running compute shaders.
• Added Shader:hasStage.
• Added love.graphics.drawFromShader.
• Added love.graphics.drawFromShaderIndirect.
• Added love.graphics.drawIndirect.
• Added love.graphics.getQuadIndexBuffer.
• Added variants of love.graphics.applyTransform and replaceTransform which accept x,y,angle,sx,sy,ox,oy parameters.
• Added APIs to override the default orthographic projection: love.graphics.setOrthoProjection, setPerspectiveProjection, and resetProjection.
• Added ability to set point size within a vertex shader by setting the 'love_PointSize' variable.
• Added love.graphics.setBlendState, which gives lower level control over blend operations than setBlendMode.
• Added high level love.graphics.setStencilMode and getStencilMode functions. Replaces love.graphics.stencil and setStencilTest.
• Added lower level love.graphics.setStencilState and getStencilState functions.
• Added a variant of love.graphics.setColorMask which accepts a single boolean.
• Added new 'clampone' wrap mode.
• Added 'clampone', 'texelbuffer', 'indexbuffer32bit', 'mipmaprange', and 'indirectdraw' graphics feature enums.
• Added 'copybuffer', 'copybuffertotexture', 'copytexturetobuffer', and 'copyrendertargettobuffer' graphics feature enums.
• Added initial support for right-to-left (RTL) text when using TrueType and OpenType fonts.
• Added a variant of Font:getWidth which takes a codepoint number argument.
• Added love.graphics.newTextBatch (renamed from love.graphics.newText).
• Added love.sensor module.
• Added love.sensorupdated callback.
• Added love.joysticksensorupdated callback.
• Added variant for enet peer:send and host:broadcast which accepts a pointer (light userdata) and a size.
Other Changes:
• Changed love.filesystem.exists to no longer be deprecated.
• Changed the default font from Vera size 12 to Noto Sans size 13.
• Changed TrueType and OpenType font handling to have improved kerning and character combining support.
• Changed the Texture class and implementation to no longer have separate Canvas and Image subclasses.
• Changed Images to no longer hold onto a CPU copy of their pixel data after creation.
• Changed love.graphics.newImage to error instead of loading a placeholder texture, when the image dimensions are too large for the system.
• Changed love.graphics.newImage to allow creating a mipmapped texture with less than the full mipmap range, instead of erroring.
• Changed love.graphics.newMesh to no longer default to the "fan" Mesh draw mode.
• Changed the behaviour of Meshes to no longer allow a vertex map or index buffer when the "fan" mesh draw mode is used.
• Changed love.window.setMode to no longer clear the contents of Canvases or otherwise recreate OpenGL resources.
• Changed love.graphics.points to require 'love_PointSize' to be set in the vertex shader, if a custom shader is used.
• Changed love.graphics.setCanvas to always clear auto-generated temporary depth and stencil buffers when they're used.
• Changed shader code parsing to ignore shader entry point functions inside comments.
• Changed audio file decoding to choose the most appropriate decoder based on file contents instead of the file extension.
• Changed Videos to stream audio from the file instead of loading all the video file into memory for use with audio decoding.
• Changed love.filesystem.exists to no longer be deprecated.
• Changed RevoluteJoint:getMotorTorque and WheelJoint:getMotorTorque to take 'dt' as a parameter instead of 'inverse_dt'.
• Changed love.math.perlinNoise and simplexNoise to use higher precision numbers for its internal calculations.
• Changed t.accelerometerjoystick startup flag in love.conf to unset by default.
• Renamed 'display' field to 'displayindex' in love.window.setMode/updateMode/getMode and love.conf.
• Renamed love.graphics Text objects to TextBatch.
• Updated Box2D from 2.3 to 2.4.1.
• Updated LuaSocket from 3.0-rc1 to 3.1.0.
Deprecations:
• Deprecated usage of slashes instead of dots for module separators in require.
• Deprecated love.filesystem.newFile (replaced by openFile).
• Deprecated love.math.noise (replaced by perlinNoise and simplexNoise).
• Deprecated love.graphics.setNewFont (use love.graphics.newFont and love.graphics.setFont instead).
• Deprecated love.graphics.newText (renamed to love.graphics.newTextBatch).
• Deprecated love.graphics.getImageFormats and love.graphics.getCanvasFormats (replaced by getTextureFormats).
• Deprecated love.graphics.stencil (replaced by love.graphics.setStencilMode or love.graphics.setStencilState).
• Deprecated love.graphics.setStencilTest and love.graphics.getStencilTest (replaced by love.graphics.setStencilMode or setStencilState).
• Deprecated t.window.highdpi in love.conf and the highdpi flag of love.window.setMode (replaced by t.highdpi in love.conf).
• Deprecated t.accelerometerjoystick in love.conf (replaced by love.sensor module).
• Deprecated the variants of Mesh:attachAttribute and SpriteBatch:attachAttribute which accept a Mesh (replaced by variants which accept a Buffer).
• Deprecated Texture:newImageData (replaced by love.graphics.readbackTexture).
Removals:
• Removed the variant of SpriteBatch:setColor() which turns off all previously set colors.
• Removed the no-argument variant of love.graphics.setColorMask.
• Removed functions deprecated in LOVE 11:
• Removed love.audio.getSourceCount (renamed to love.audio.getActiveSourceCount).
• Removed Source:getChannels (renamed to Source:getChannelCount).
• Removed Decoder:getChannels (renamed to Decoder:getChannelCount).
• Removed love.filesystem.isDirectory (replaced by love.filesystem.getInfo).
• Removed love.filesystem.isFile (replaced by love.filesystem.getInfo).
• Removed love.filesystem.isSymlink (replaced by love.filesystem.getInfo).
• Removed love.filesystem.getLastModified (replaced by love.filesystem.getInfo).
• Removed love.filesystem.getSize (replaced by love.filesystem.getInfo).
• Removed ParticleSystem:setAreaSpread and ParticleSystem:getAreaSpread (renamed to ParticleSystem:setEmissionArea and getEmissionArea).
• Removed love.math.compress and love.math.decompress (replaced by love.data.compress and love.data.decompress).
• Removed World:getBodyList, World:getJointList, and World:getContactList (renamed to World:getBodies, World:getJoints, and World:getContacts).
• Removed Body:getFixtureList, Body:getJointList, and Body:getContactList (renamed to Body:getFixtures, Body:getJoints, and Body:getContacts).
• Removed PrismaticJoint:hasLimitsEnabled (renamed to PrismaticJoint:areLimitsEnabled).
• Removed RevoluteJoint:hasLimitsEnabled (renamed to RevoluteJoint:areLimitsEnabled).
Fixes:
• Fixed BezierCurve:render adding collinear points in some situations.
• Fixed sound Decoders to cause a Lua error instead of hard-crashing when memory for the decoding buffer can't be allocated.
• Fixed enum misspelling for thousandsseparator from thsousandsseparator for both keyboard and scancode enums.
@@ -0,0 +1,24 @@
<p>
<b>LÖVE is an awesome 2D game framework for Lua.</b>
</p>
<p>
LÖVE is a free, open-source, cross-platform framework released under the zlib license for developing video games. The framework is written in C++ and uses Lua as its scripting language.
</p>
<p>
This is the Android port of LÖVE. It can load games from *.love files and from /sdcard/lovegame (or /sdcard/Android/data/org.love2d.android/files/games/lovegame) folder.
</p>
<p>
<b>These features come with the framework:</b>
</p>
<ul>
<li>Supports OpenGL pixel shaders GLSL.</li>
<li>Supports touchscreen for mobile devices.</li>
<li>Supports joysticks by providing interface for connected joysticks.</li>
<li>Supports UTF-8.</li>
<li>Supports image formats: PNG, JPEG, GIF, TGA and BMP.</li>
<li>Supports audio formats: WAV, OGG, and MP3.</li>
<li>Supports video formats: OGV.</li>
<li>Supports the physics engine Box2D in games, which can be disabled to lighten the library.</li>
<li>Supports the LuaSocket library for network communications TCP/UDP.</li>
<li>Supports the lua-enet library, another network library implementing Enet, a reliable protocol based on UDP.</li>
</ul>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1 @@
Android Port of LÖVE, an awesome 2D game engine for Lua
@@ -0,0 +1 @@
LÖVE for Android
+19
View File
@@ -0,0 +1,19 @@
# To set the application display name, only define either `app.name` or `app.name_byte_array`.
# For a rule of thumb:
# * Use `app.name` if your app name doesn't contain any non-ANSI characters.
# * Otherwise, convert your app name to UTF-8 byte array, comma delimited, and put
# it in `app.name_byte_array`
#app.name=LÖVE for Android
app.name_byte_array=76,195,150,86,69,32,102,111,114,32,65,110,100,114,111,105,100
app.application_id=org.love2d.android
app.orientation=landscape
app.version_code=33
app.version_name=12.0
# No need to modify anything past this line!
android.enableJetifier=false
android.useAndroidX=true
android.nonTransitiveRClass=true
android.nonFinalResIds=true
android.dependency.useConstraints=true
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+244
View File
@@ -0,0 +1,244 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+92
View File
@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
-1
View File
@@ -1 +0,0 @@
include $(call all-subdir-makefiles)
-9
View File
@@ -1,9 +0,0 @@
# Uncomment this if you're using STL in your project
# See CPLUSPLUS-SUPPORT.html in the NDK documentation for more information
# APP_STL := stlport_static
APP_STL := gnustl_shared
APP_ABI := armeabi armeabi-v7a
APP_CPPFLAGS := -frtti
APP_LDFLAGS := -llog -landroid -lz
# APP_OPTIM := debug
-8
View File
@@ -1,8 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libluajit
LOCAL_SRC_FILES := android/$(TARGET_ARCH_ABI)/libluajit.a
include $(PREBUILT_STATIC_LIBRARY)
-56
View File
@@ -1,56 +0,0 @@
===============================================================================
LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
Copyright (C) 2005-2013 Mike Pall. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
===============================================================================
[ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ]
Copyright (C) 1994-2012 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
[ LuaJIT includes code from dlmalloc, which has this license statement: ]
This is a version (aka dlmalloc) of malloc/free/realloc written by
Doug Lea and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain
===============================================================================
-149
View File
@@ -1,149 +0,0 @@
##############################################################################
# LuaJIT top level Makefile for installation. Requires GNU Make.
#
# Please read doc/install.html before changing any variables!
#
# Suitable for POSIX platforms (Linux, *BSD, OSX etc.).
# Note: src/Makefile has many more configurable options.
#
# ##### This Makefile is NOT useful for Windows! #####
# For MSVC, please follow the instructions given in src/msvcbuild.bat.
# For MinGW and Cygwin, cd to src and run make with the Makefile there.
#
# Copyright (C) 2005-2013 Mike Pall. See Copyright Notice in luajit.h
##############################################################################
MAJVER= 2
MINVER= 0
RELVER= 1
VERSION= $(MAJVER).$(MINVER).$(RELVER)
ABIVER= 5.1
##############################################################################
#
# Change the installation path as needed. This automatically adjusts
# the paths in src/luaconf.h, too. Note: PREFIX must be an absolute path!
#
export PREFIX= /usr/local
##############################################################################
DPREFIX= $(DESTDIR)$(PREFIX)
INSTALL_BIN= $(DPREFIX)/bin
INSTALL_LIB= $(DPREFIX)/lib
INSTALL_SHARE= $(DPREFIX)/share
INSTALL_INC= $(DPREFIX)/include/luajit-$(MAJVER).$(MINVER)
INSTALL_LJLIBD= $(INSTALL_SHARE)/luajit-$(VERSION)
INSTALL_JITLIB= $(INSTALL_LJLIBD)/jit
INSTALL_LMODD= $(INSTALL_SHARE)/lua
INSTALL_LMOD= $(INSTALL_LMODD)/$(ABIVER)
INSTALL_CMODD= $(INSTALL_LIB)/lua
INSTALL_CMOD= $(INSTALL_CMODD)/$(ABIVER)
INSTALL_MAN= $(INSTALL_SHARE)/man/man1
INSTALL_PKGCONFIG= $(INSTALL_LIB)/pkgconfig
INSTALL_TNAME= luajit-$(VERSION)
INSTALL_TSYMNAME= luajit
INSTALL_ANAME= libluajit-$(ABIVER).a
INSTALL_SONAME= libluajit-$(ABIVER).so.$(MAJVER).$(MINVER).$(RELVER)
INSTALL_SOSHORT= libluajit-$(ABIVER).so
INSTALL_DYLIBNAME= libluajit-$(ABIVER).$(MAJVER).$(MINVER).$(RELVER).dylib
INSTALL_DYLIBSHORT1= libluajit-$(ABIVER).dylib
INSTALL_DYLIBSHORT2= libluajit-$(ABIVER).$(MAJVER).dylib
INSTALL_PCNAME= luajit.pc
INSTALL_STATIC= $(INSTALL_LIB)/$(INSTALL_ANAME)
INSTALL_DYN= $(INSTALL_LIB)/$(INSTALL_SONAME)
INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_SOSHORT)
INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_SOSHORT)
INSTALL_T= $(INSTALL_BIN)/$(INSTALL_TNAME)
INSTALL_TSYM= $(INSTALL_BIN)/$(INSTALL_TSYMNAME)
INSTALL_PC= $(INSTALL_PKGCONFIG)/$(INSTALL_PCNAME)
INSTALL_DIRS= $(INSTALL_BIN) $(INSTALL_LIB) $(INSTALL_INC) $(INSTALL_MAN) \
$(INSTALL_PKGCONFIG) $(INSTALL_JITLIB) $(INSTALL_LMOD) $(INSTALL_CMOD)
UNINSTALL_DIRS= $(INSTALL_JITLIB) $(INSTALL_LJLIBD) $(INSTALL_INC) \
$(INSTALL_LMOD) $(INSTALL_LMODD) $(INSTALL_CMOD) $(INSTALL_CMODD)
RM= rm -f
MKDIR= mkdir -p
RMDIR= rmdir 2>/dev/null
SYMLINK= ln -sf
INSTALL_X= install -m 0755
INSTALL_F= install -m 0644
UNINSTALL= $(RM)
LDCONFIG= ldconfig -n
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|"
FILE_T= luajit
FILE_A= libluajit.a
FILE_SO= libluajit.so
FILE_MAN= luajit.1
FILE_PC= luajit.pc
FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
FILES_JITLIB= bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua dis_arm.lua \
dis_ppc.lua dis_mips.lua dis_mipsel.lua bcsave.lua vmdef.lua
ifeq (,$(findstring Windows,$(OS)))
ifeq (Darwin,$(shell uname -s))
INSTALL_SONAME= $(INSTALL_DYLIBNAME)
INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_DYLIBSHORT1)
INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_DYLIBSHORT2)
LDCONFIG= :
endif
endif
##############################################################################
INSTALL_DEP= src/luajit
default all $(INSTALL_DEP):
@echo "==== Building LuaJIT $(VERSION) ===="
$(MAKE) -C src
@echo "==== Successfully built LuaJIT $(VERSION) ===="
install: $(INSTALL_DEP)
@echo "==== Installing LuaJIT $(VERSION) to $(PREFIX) ===="
$(MKDIR) $(INSTALL_DIRS)
cd src && $(INSTALL_X) $(FILE_T) $(INSTALL_T)
cd src && test -f $(FILE_A) && $(INSTALL_F) $(FILE_A) $(INSTALL_STATIC) || :
$(RM) $(INSTALL_TSYM) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2)
cd src && test -f $(FILE_SO) && \
$(INSTALL_X) $(FILE_SO) $(INSTALL_DYN) && \
$(LDCONFIG) $(INSTALL_LIB) && \
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT1) && \
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT2) || :
cd etc && $(INSTALL_F) $(FILE_MAN) $(INSTALL_MAN)
cd etc && $(SED_PC) $(FILE_PC) > $(FILE_PC).tmp && \
$(INSTALL_F) $(FILE_PC).tmp $(INSTALL_PC) && \
$(RM) $(FILE_PC).tmp
cd src && $(INSTALL_F) $(FILES_INC) $(INSTALL_INC)
cd src/jit && $(INSTALL_F) $(FILES_JITLIB) $(INSTALL_JITLIB)
$(SYMLINK) $(INSTALL_TNAME) $(INSTALL_TSYM)
@echo "==== Successfully installed LuaJIT $(VERSION) to $(PREFIX) ===="
uninstall:
@echo "==== Uninstalling LuaJIT $(VERSION) from $(PREFIX) ===="
$(UNINSTALL) $(INSTALL_TSYM) $(INSTALL_T) $(INSTALL_STATIC) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2) $(INSTALL_MAN)/$(FILE_MAN) $(INSTALL_PC)
for file in $(FILES_JITLIB); do \
$(UNINSTALL) $(INSTALL_JITLIB)/$$file; \
done
for file in $(FILES_INC); do \
$(UNINSTALL) $(INSTALL_INC)/$$file; \
done
$(LDCONFIG) $(INSTALL_LIB)
$(RMDIR) $(UNINSTALL_DIRS) || :
@echo "==== Successfully uninstalled LuaJIT $(VERSION) from $(PREFIX) ===="
##############################################################################
amalg:
@echo "Building LuaJIT $(VERSION)"
$(MAKE) -C src amalg
clean:
$(MAKE) -C src clean
.PHONY: all install amalg clean
##############################################################################
-16
View File
@@ -1,16 +0,0 @@
README for LuaJIT 2.0.1
-----------------------
LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
Project Homepage: http://luajit.org/
LuaJIT is Copyright (C) 2005-2013 Mike Pall.
LuaJIT is free software, released under the MIT license.
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
Documentation for LuaJIT is available in HTML format.
Please point your favorite browser to:
doc/luajit.html
Binary file not shown.
Binary file not shown.
-58
View File
@@ -1,58 +0,0 @@
#!/bin/bash
#================================================================#
# Build script based on
# https://github.com/moai/moai-dev/blob/master/ant/libmoai/jni/luajit/build.sh
#================================================================#
host_os=`uname -s | tr "[:upper:]" "[:lower:]"`
host_arch=`uname -m`
if [ -f android/armeabi/libluajit.a ] &&
[ -f android/armeabi-v7a/libluajit.a ]; then
echo "LuaJIT Already built"
exit 0
fi
NDK_BUILD_LOCATION=${ANDROID_NDK}
if [[ x$NDK_BUILD_LOCATION = "x" ]]; then
echo "The Android NDK must be on your path."
exit 1
fi
NDK="${NDK_BUILD_LOCATION%/ndk-build}"
if [[ x$NDK = "x" ]]; then
echo "The Android NDK must be on your path."
exit 1
fi
NDKABI=8
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.6
NDKP=$NDKVER/prebuilt/${host_os}-${host_arch}/bin/arm-linux-androideabi-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
CFLAGS=""
buildLuaJIT()
{
arch="$1"
ndkarch="$2"
DESTDIR=../android/$arch
mkdir -p $DESTDIR 2>/dev/null
rm "$DESTDIR"/*.a 2>/dev/null
make clean
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_SYS=Linux TARGET_FLAGS="$NDKF $ndkarch" TARGET_CFLAGS="$CFLAGS" libluajit.a
if [ -f libluajit.a ]; then
mv libluajit.a $DESTDIR/libluajit.a
fi;
}
cd src
# Android/ARM, armeabi (ARMv5TE soft-float), Android 2.2+ (Froyo)
buildLuaJIT armeabi
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
buildLuaJIT armeabi-v7a "-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wl,--fix-cortex-a8"
make clean
-166
View File
@@ -1,166 +0,0 @@
/* Copyright (C) 2004-2013 Mike Pall.
*
* You are welcome to use the general ideas of this design for your own sites.
* But please do not steal the stylesheet, the layout or the color scheme.
*/
body {
font-family: serif;
font-size: 11pt;
margin: 0 3em;
padding: 0;
border: none;
}
a:link, a:visited, a:hover, a:active {
text-decoration: none;
background: transparent;
color: #0000ff;
}
h1, h2, h3 {
font-family: sans-serif;
font-weight: bold;
text-align: left;
margin: 0.5em 0;
padding: 0;
}
h1 {
font-size: 200%;
}
h2 {
font-size: 150%;
}
h3 {
font-size: 125%;
}
p {
margin: 0 0 0.5em 0;
padding: 0;
}
ul, ol {
margin: 0.5em 0;
padding: 0 0 0 2em;
}
ul {
list-style: outside square;
}
ol {
list-style: outside decimal;
}
li {
margin: 0;
padding: 0;
}
dl {
margin: 1em 0;
padding: 1em;
border: 1px solid black;
}
dt {
font-weight: bold;
margin: 0;
padding: 0;
}
dt sup {
float: right;
margin-left: 1em;
}
dd {
margin: 0.5em 0 0 2em;
padding: 0;
}
table {
table-layout: fixed;
width: 100%;
margin: 1em 0;
padding: 0;
border: 1px solid black;
border-spacing: 0;
border-collapse: collapse;
}
tr {
margin: 0;
padding: 0;
border: none;
}
td {
text-align: left;
margin: 0;
padding: 0.2em 0.5em;
border-top: 1px solid black;
border-bottom: 1px solid black;
}
tr.separate td {
border-top: double;
}
tt, pre, code, kbd, samp {
font-family: monospace;
font-size: 75%;
}
kbd {
font-weight: bolder;
}
blockquote, pre {
margin: 1em 2em;
padding: 0;
}
img {
border: none;
vertical-align: baseline;
margin: 0;
padding: 0;
}
img.left {
float: left;
margin: 0.5em 1em 0.5em 0;
}
img.right {
float: right;
margin: 0.5em 0 0.5em 1em;
}
.flush {
clear: both;
visibility: hidden;
}
.hide, .noprint, #nav {
display: none !important;
}
.pagebreak {
page-break-before: always;
}
#site {
text-align: right;
font-family: sans-serif;
font-weight: bold;
margin: 0 1em;
border-bottom: 1pt solid black;
}
#site a {
font-size: 1.2em;
}
#site a:link, #site a:visited {
text-decoration: none;
font-weight: bold;
background: transparent;
color: #ffffff;
}
#logo {
color: #ff8000;
}
#head {
clear: both;
margin: 0 1em;
}
#main {
line-height: 1.3;
text-align: justify;
margin: 1em;
}
#foot {
clear: both;
font-size: 80%;
text-align: center;
margin: 0 1.25em;
padding: 0.5em 0 0 0;
border-top: 1pt solid black;
page-break-before: avoid;
page-break-after: avoid;
}
-325
View File
@@ -1,325 +0,0 @@
/* Copyright (C) 2004-2013 Mike Pall.
*
* You are welcome to use the general ideas of this design for your own sites.
* But please do not steal the stylesheet, the layout or the color scheme.
*/
/* colorscheme:
*
* site | head #4162bf/white | #6078bf/#e6ecff
* ------+------ ----------------+-------------------
* nav | main #bfcfff | #e6ecff/black
*
* nav: hiback loback #c5d5ff #b9c9f9
* hiborder loborder #e6ecff #97a7d7
* link hover #2142bf #ff0000
*
* link: link visited hover #2142bf #8122bf #ff0000
*
* main: boxback boxborder #f0f4ff #bfcfff
*/
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
margin: 0;
padding: 0;
border: none;
background: #e0e0e0;
color: #000000;
}
a:link {
text-decoration: none;
background: transparent;
color: #2142bf;
}
a:visited {
text-decoration: none;
background: transparent;
color: #8122bf;
}
a:hover, a:active {
text-decoration: underline;
background: transparent;
color: #ff0000;
}
h1, h2, h3 {
font-weight: bold;
text-align: left;
margin: 0.5em 0;
padding: 0;
background: transparent;
}
h1 {
font-size: 200%;
line-height: 3em; /* really 6em relative to body, match #site span */
margin: 0;
}
h2 {
font-size: 150%;
color: #606060;
}
h3 {
font-size: 125%;
color: #404040;
}
p {
max-width: 600px;
margin: 0 0 0.5em 0;
padding: 0;
}
b {
color: #404040;
}
ul, ol {
max-width: 600px;
margin: 0.5em 0;
padding: 0 0 0 2em;
}
ul {
list-style: outside square;
}
ol {
list-style: outside decimal;
}
li {
margin: 0;
padding: 0;
}
dl {
max-width: 600px;
margin: 1em 0;
padding: 1em;
border: 1px solid #bfcfff;
background: #f0f4ff;
}
dt {
font-weight: bold;
margin: 0;
padding: 0;
}
dt sup {
float: right;
margin-left: 1em;
color: #808080;
}
dt a:visited {
text-decoration: none;
color: #2142bf;
}
dt a:hover, dt a:active {
text-decoration: none;
color: #ff0000;
}
dd {
margin: 0.5em 0 0 2em;
padding: 0;
}
div.tablewrap { /* for IE *sigh* */
max-width: 600px;
}
table {
table-layout: fixed;
border-spacing: 0;
border-collapse: collapse;
max-width: 600px;
width: 100%;
margin: 1em 0;
padding: 0;
border: 1px solid #bfcfff;
}
tr {
margin: 0;
padding: 0;
border: none;
}
tr.odd {
background: #f0f4ff;
}
tr.separate td {
border-top: 1px solid #bfcfff;
}
td {
text-align: left;
margin: 0;
padding: 0.2em 0.5em;
border: none;
}
tt, code, kbd, samp {
font-family: Courier New, Courier, monospace;
line-height: 1.2;
font-size: 110%;
}
kbd {
font-weight: bolder;
}
blockquote, pre {
max-width: 600px;
margin: 1em 2em;
padding: 0;
}
pre {
line-height: 1.1;
}
pre.code {
line-height: 1.4;
margin: 0.5em 0 1em 0.5em;
padding: 0.5em 1em;
border: 1px solid #bfcfff;
background: #f0f4ff;
}
pre.mark {
padding-left: 2em;
}
span.codemark {
position:absolute;
left: 16em;
color: #4040c0;
}
span.mark {
color: #4040c0;
font-family: Courier New, Courier, monospace;
line-height: 1.1;
}
img {
border: none;
vertical-align: baseline;
margin: 0;
padding: 0;
}
img.left {
float: left;
margin: 0.5em 1em 0.5em 0;
}
img.right {
float: right;
margin: 0.5em 0 0.5em 1em;
}
.indent {
padding-left: 1em;
}
.flush {
clear: both;
visibility: hidden;
}
.hide, .noscreen {
display: none !important;
}
.ext {
color: #ff8000;
}
.new {
font-size: 6pt;
vertical-align: middle;
background: #ff8000;
color: #ffffff;
}
#site {
clear: both;
float: left;
width: 13em;
text-align: center;
font-weight: bold;
margin: 0;
padding: 0;
background: transparent;
color: #ffffff;
}
#site a {
font-size: 200%;
}
#site a:link, #site a:visited {
text-decoration: none;
font-weight: bold;
background: transparent;
color: #ffffff;
}
#site span {
line-height: 3em; /* really 6em relative to body, match h1 */
}
#logo {
color: #ffb380;
}
#head {
margin: 0;
padding: 0 0 0 2em;
border-left: solid 13em #4162bf;
border-right: solid 3em #6078bf;
background: #6078bf;
color: #e6ecff;
}
#nav {
clear: both;
float: left;
overflow: hidden;
text-align: left;
line-height: 1.5;
width: 13em;
padding-top: 1em;
background: transparent;
}
#nav ul {
list-style: none outside;
margin: 0;
padding: 0;
}
#nav li {
margin: 0;
padding: 0;
}
#nav a {
display: block;
text-decoration: none;
font-weight: bold;
margin: 0;
padding: 2px 1em;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
background: transparent;
color: #2142bf;
}
#nav a:hover, #nav a:active {
text-decoration: none;
border-top: 1px solid #97a7d7;
border-bottom: 1px solid #e6ecff;
background: #b9c9f9;
color: #ff0000;
}
#nav a.current, #nav a.current:hover, #nav a.current:active {
border-top: 1px solid #e6ecff;
border-bottom: 1px solid #97a7d7;
background: #c5d5ff;
color: #2142bf;
}
#nav ul ul a {
padding: 0 1em 0 1.7em;
}
#nav ul ul ul a {
padding: 0 0.5em 0 2.4em;
}
#main {
line-height: 1.5;
text-align: left;
margin: 0;
padding: 1em 2em;
border-left: solid 13em #bfcfff;
border-right: solid 3em #e6ecff;
background: #e6ecff;
}
#foot {
clear: both;
font-size: 80%;
text-align: center;
margin: 0;
padding: 0.5em;
background: #6078bf;
color: #ffffff;
}
#foot a:link, #foot a:visited {
text-decoration: underline;
background: transparent;
color: #ffffff;
}
#foot a:hover, #foot a:active {
text-decoration: underline;
background: transparent;
color: #bfcfff;
}
-862
View File
@@ -1,862 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>LuaJIT Change History</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
div.major { max-width: 600px; padding: 1em; margin: 1em 0 1em 0; }
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>LuaJIT Change History</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a class="current" href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
This is a list of changes between the released versions of LuaJIT.<br>
The current <span style="color: #0000c0;">stable version</span> is <strong>LuaJIT&nbsp;2.0.1</strong>.<br>
</p>
<p>
Please check the
<a href="http://luajit.org/changes.html"><span class="ext">&raquo;</span>&nbsp;Online Change History</a>
to see whether newer versions are available.
</p>
<div class="major" style="background: #d0d0ff;">
<h2 id="LuaJIT-2.0.1">LuaJIT 2.0.1 &mdash; 2013-02-19</h2>
<ul>
<li>Don't clear frame for out-of-memory error.</li>
<li>Leave hook when resume catches error thrown from hook.</li>
<li>Add missing GC steps for template table creation.</li>
<li>Fix discharge order of comparisons in Lua parser.</li>
<li>Improve buffer handling for <tt>io.read()</tt>.</li>
<li>OSX: Add support for Mach-O object files to <tt>-b</tt> option.</li>
<li>Fix PS3 port.</li>
<li>Fix/enable Xbox 360 port.</li>
<li>x86/x64: Always mark ref for shift count as non-weak.</li>
<li>x64: Don't fuse implicitly 32-to-64 extended operands.</li>
<li>ARM: Fix armhf call argument handling.</li>
<li>ARM: Fix code generation for integer math.min/math.max.</li>
<li>PPC/e500: Fix <tt>lj_vm_floor()</tt> for Inf/NaN.</li>
<li>FFI: Change priority of table initializer variants for structs.</li>
<li>FFI: Fix code generation for bool call result check on x86/x64.</li>
<li>FFI: Load FFI library on-demand for bytecode with cdata literals.</li>
<li>FFI: Fix handling of qualified transparent structs/unions.</li>
</ul>
<h2 id="LuaJIT-2.0.0">LuaJIT 2.0.0 &mdash; 2012-11-08</h2>
<ul>
<li>Correctness and completeness:
<ul>
<li>Fix Android/x86 build.</li>
<li>Fix recording of equality comparisons with <tt>__eq</tt> metamethods.</li>
<li>Fix detection of immutable upvalues.</li>
<li>Replace error with PANIC for callbacks from JIT-compiled code.</li>
<li>Fix builtin string to number conversion for <tt>INT_MIN</tt>.</li>
<li>Don't create unneeded array part for template tables.</li>
<li>Fix <tt>CONV.num.int</tt> sinking.</li>
<li>Don't propagate implicitly widened number to index metamethods.</li>
<li>ARM: Fix ordered comparisons of number vs. non-number.</li>
<li>FFI: Fix code generation for replay of sunk float fields.</li>
<li>FFI: Fix signedness of bool.</li>
<li>FFI: Fix recording of bool call result check on x86/x64.</li>
<li>FFI: Fix stack-adjustment for <tt>__thiscall</tt> callbacks.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta11">LuaJIT 2.0.0-beta11 &mdash; 2012-10-16</h2>
<ul>
<li>New features:
<ul>
<li>Use ARM VFP instructions, if available (build-time detection).</li>
<li>Add support for ARM hard-float EABI (<tt>armhf</tt>).</li>
<li>Add PS3 port.</li>
<li>Add many features from Lua&nbsp;5.2, e.g. <tt>goto</tt>/labels.
Refer to <a href="extensions.html#lua52">this list</a>.</li>
<li>FFI: Add parameterized C types.</li>
<li>FFI: Add support for copy constructors.</li>
<li>FFI: Equality comparisons never raise an error (treat as unequal instead).</li>
<li>FFI: Box all accessed or returned enums.</li>
<li>FFI: Check for <tt>__new</tt> metamethod when calling a constructor.</li>
<li>FFI: Handle <tt>__pairs</tt>/<tt>__ipairs</tt> metamethods for cdata objects.</li>
<li>FFI: Convert <tt>io.*</tt> file handle to <tt>FILE *</tt> pointer (but as a <tt>void *</tt>).</li>
<li>FFI: Detect and support type punning through unions.</li>
<li>FFI: Improve various error messages.</li>
</ul></li>
<li>Build-system reorganization:
<ul>
<li>Reorganize directory layout:<br>
<tt>lib/*</tt> &rarr; <tt>src/jit/*</tt><br>
<tt>src/buildvm_*.dasc</tt> &rarr; <tt>src/vm_*.dasc</tt><br>
<tt>src/buildvm_*.h</tt> &rarr; removed<br>
<tt>src/buildvm*</tt> &rarr; <tt>src/host/*</tt></li>
<li>Add minified Lua interpreter plus Lua BitOp (<tt>minilua</tt>) to run DynASM.</li>
<li>Change DynASM bit operations to use Lua BitOp</li>
<li>Translate only <tt>vm_*.dasc</tt> for detected target architecture.</li>
<li>Improve target detection for <tt>msvcbuild.bat</tt>.</li>
<li>Fix build issues on Cygwin and MinGW with optional MSys.</li>
<li>Handle cross-compiles with FPU/no-FPU or hard-fp/soft-fp ABI mismatch.</li>
<li>Remove some library functions for no-JIT/no-FFI builds.</li>
<li>Add uninstall target to top-level Makefile.</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>Preserve snapshot #0 PC for all traces.</li>
<li>Fix argument checks for <tt>coroutine.create()</tt>.</li>
<li>Command line prints version and JIT status to <tt>stdout</tt>, not <tt>stderr</tt>.</li>
<li>Fix userdata <tt>__gc</tt> separations at Lua state close.</li>
<li>Fix <tt>TDUP</tt> to <tt>HLOAD</tt> forwarding for <tt>LJ_DUALNUM</tt> builds.</li>
<li>Fix buffer check in bytecode writer.</li>
<li>Make <tt>os.date()</tt> thread-safe.</li>
<li>Add missing declarations for MSVC intrinsics.</li>
<li>Fix dispatch table modifications for return hooks.</li>
<li>Workaround for MSVC conversion bug (<tt>double</tt> &rarr; <tt>uint32_t</tt> &rarr; <tt>int32_t</tt>).</li>
<li>Fix FOLD rule <tt>(i-j)-i => 0-j</tt>.</li>
<li>Never use DWARF unwinder on Windows.</li>
<li>Fix shrinking of direct mapped blocks in builtin allocator.</li>
<li>Limit recursion depth in <tt>string.match()</tt> et al.</li>
<li>Fix late despecialization of <tt>ITERN</tt> after loop has been entered.</li>
<li>Fix <tt>'f'</tt> and <tt>'L'</tt> options for <tt>debug.getinfo()</tt> and <tt>lua_getinfo()</tt>.</li>
<li>Fix <tt>package.searchpath()</tt>.</li>
<li>OSX: Change dylib names to be consistent with other platforms.</li>
<li>Android: Workaround for broken <tt>sprintf("%g",&nbsp;-0.0)</tt>.</li>
<li>x86: Remove support for ancient CPUs without <tt>CMOV</tt> (before Pentium Pro).</li>
<li>x86: Fix register allocation for calls returning register pair.</li>
<li>x86/x64: Fix fusion of unsigned byte comparisons with swapped operands.</li>
<li>ARM: Fix <tt>tonumber()</tt> argument check.</li>
<li>ARM: Fix modulo operator and <tt>math.floor()</tt>/<tt>math.ceil()</tt> for <tt>inf</tt>/<tt>nan</tt>.</li>
<li>ARM: Invoke SPLIT pass for leftover <tt>IR_TOBIT</tt>.</li>
<li>ARM: Fix BASE register coalescing.</li>
<li>PPC: Fix interpreter state setup in callbacks.</li>
<li>PPC: Fix <tt>string.sub()</tt> range check.</li>
<li>MIPS: Support generation of MIPS/MIPSEL bytecode object files.</li>
<li>MIPS: Fix calls to <tt>floor()</tt>/<tt>ceil()</tt><tt>/trunc()</tt>.</li>
<li>ARM/PPC: Detect more target architecture variants.</li>
<li>ARM/PPC/e500/MIPS: Fix tailcalls from fast functions, esp. <tt>tostring()</tt>.</li>
<li>ARM/PPC/MIPS: Fix rematerialization of FP constants.</li>
<li>FFI: Don't call <tt>FreeLibrary()</tt> on our own EXE/DLL.</li>
<li>FFI: Resolve metamethods for constructors, too.</li>
<li>FFI: Properly disable callbacks on iOS (would require executable memory).</li>
<li>FFI: Fix cdecl string parsing during recording.</li>
<li>FFI: Show address pointed to for <tt>tostring(ref)</tt>, too.</li>
<li>FFI: Fix alignment of C call argument/return structure.</li>
<li>FFI: Initialize all fields of standard types.</li>
<li>FFI: Fix callback handling when new C&nbsp;types are declared in callback.</li>
<li>FFI: Fix recording of constructors for pointers.</li>
<li>FFI: Always resolve metamethods for pointers to structs.</li>
<li>FFI: Correctly propagate alignment when interning nested types.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Add allocation sinking and store sinking optimization.</li>
<li>Constify immutable upvalues.</li>
<li>Add builtin string to integer or FP number conversion. Improves cross-platform consistency and correctness.</li>
<li>Create string hash slots in template tables for non-const values, too. Avoids later table resizes.</li>
<li>Eliminate <tt>HREFK</tt> guard for template table references.</li>
<li>Add various new FOLD rules.</li>
<li>Don't use stack unwinding for <tt>lua_yield()</tt> (slow on x64).</li>
<li>ARM, PPC, MIPS: Improve <tt>XLOAD</tt> operand fusion and register hinting.</li>
<li>PPC, MIPS: Compile <tt>math.sqrt()</tt> to sqrt instruction, if available.</li>
<li>FFI: Fold <tt>KPTR</tt> + constant offset in SPLIT pass.</li>
<li>FFI: Optimize/inline <tt>ffi.copy()</tt> and <tt>ffi.fill()</tt>.</li>
<li>FFI: Compile and optimize array/struct copies.</li>
<li>FFI: Compile <tt>ffi.typeof(cdata|ctype)</tt>, <tt>ffi.sizeof()</tt>, <tt>ffi.alignof()</tt>, <tt>ffi.offsetof()</tt> and <tt>ffi.gc()</tt>.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta10">LuaJIT 2.0.0-beta10 &mdash; 2012-05-09</h2>
<ul>
<li>New features:
<ul>
<li>The MIPS of LuaJIT is complete. It requires a CPU conforming to the
MIPS32&nbsp;R1 architecture with hardware FPU. O32 hard-fp ABI,
little-endian or big-endian.</li>
<li>Auto-detect target arch via cross-compiler. No need for
<tt>TARGET=arch</tt> anymore.</li>
<li>Make DynASM compatible with Lua 5.2.</li>
<li>From Lua 5.2: Try <tt>__tostring</tt> metamethod on non-string error
messages..</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>Fix parsing of hex literals with exponents.</li>
<li>Fix bytecode dump for certain number constants.</li>
<li>Fix argument type in error message for relative arguments.</li>
<li>Fix argument error handling on Lua stacks without a frame.</li>
<li>Add missing mcode limit check in assembler backend.</li>
<li>Fix compilation on OpenBSD.</li>
<li>Avoid recursive GC steps after GC-triggered trace exit.</li>
<li>Replace <tt>&lt;unwind.h&gt;</tt> definitions with our own.</li>
<li>Fix OSX build issues. Bump minimum required OSX version to 10.4.</li>
<li>Fix discharge order of comparisons in Lua parser.</li>
<li>Ensure running <tt>__gc</tt> of userdata created in <tt>__gc</tt>
at state close.</li>
<li>Limit number of userdata <tt>__gc</tt> separations at state close.</li>
<li>Fix bytecode <tt>JMP</tt> slot range when optimizing
<tt>and</tt>/<tt>or</tt> with constant LHS.</li>
<li>Fix DSE of <tt>USTORE</tt>.</li>
<li>Make <tt>lua_concat()</tt> work from C&nbsp;hook with partial frame.</li>
<li>Add required PHIs for implicit conversions, e.g. via <tt>XREF</tt>
forwarding.</li>
<li>Add more comparison variants to Valgrind suppressions file.</li>
<li>Disable loading bytecode with an extra header (BOM or <tt>#!</tt>).</li>
<li>Fix PHI stack slot syncing.</li>
<li>ARM: Reorder type/value tests to silence Valgrind.</li>
<li>ARM: Fix register allocation for <tt>ldrd</tt>-optimized
<tt>HREFK</tt>.</li>
<li>ARM: Fix conditional branch fixup for <tt>OBAR</tt>.</li>
<li>ARM: Invoke SPLIT pass for <tt>double</tt> args in FFI call.</li>
<li>ARM: Handle all <tt>CALL*</tt> ops with <tt>double</tt> results in
SPLIT pass.</li>
<li>ARM: Fix rejoin of <tt>POW</tt> in SPLIT pass.</li>
<li>ARM: Fix compilation of <tt>math.sinh</tt>, <tt>math.cosh</tt>,
<tt>math.tanh</tt>.</li>
<li>ARM, PPC: Avoid pointless arg clearing in <tt>BC_IFUNCF</tt>.</li>
<li>PPC: Fix resume after yield from hook.</li>
<li>PPC: Fix argument checking for <tt>rawget()</tt>.</li>
<li>PPC: Fix fusion of floating-point <tt>XLOAD</tt>/<tt>XSTORE</tt>.</li>
<li>PPC: Fix <tt>HREFK</tt> code generation for huge tables.</li>
<li>PPC: Use builtin D-Cache/I-Cache sync code.</li>
</ul></li>
<li>FFI library:
<ul>
<li>Ignore empty statements in <tt>ffi.cdef()</tt>.</li>
<li>Ignore number parsing errors while skipping definitions.</li>
<li>Don't touch frame in callbacks with tailcalls to fast functions.</li>
<li>Fix library unloading on POSIX systems.</li>
<li>Finalize cdata before userdata when closing the state.</li>
<li>Change <tt>ffi.load()</tt> library name resolution for Cygwin.</li>
<li>Fix resolving of function name redirects on Windows/x86.</li>
<li>Fix symbol resolving error messages on Windows.</li>
<li>Fix blacklisting of C functions calling callbacks.</li>
<li>Fix result type of pointer difference.</li>
<li>Use correct PC in FFI metamethod error message.</li>
<li>Allow <tt>'typedef _Bool int BOOL;'</tt> for the Windows API.</li>
<li>Don't record test for bool result of call, if ignored.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta9">LuaJIT 2.0.0-beta9 &mdash; 2011-12-14</h2>
<ul>
<li>New features:
<ul>
<li>PPC port of LuaJIT is complete. Default is the dual-number port
(usually faster). Single-number port selectable via <tt>src/Makefile</tt>
at build time.</li>
<li>Add FFI callback support.</li>
<li>Extend <tt>-b</tt> to generate <tt>.c</tt>, <tt>.h</tt> or <tt>.obj/.o</tt>
files with embedded bytecode.</li>
<li>Allow loading embedded bytecode with <tt>require()</tt>.</li>
<li>From Lua 5.2: Change to <tt>'\z'</tt> escape. Reject undefined escape
sequences.</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>Fix OSX 10.7 build. Fix <tt>install_name</tt> and versioning on OSX.</li>
<li>Fix iOS build.</li>
<li>Install <tt>dis_arm.lua</tt>, too.</li>
<li>Mark installed shared library as executable.</li>
<li>Add debug option to <tt>msvcbuild.bat</tt> and improve error handling.</li>
<li>Fix data-flow analysis for iterators.</li>
<li>Fix forced unwinding triggered by external unwinder.</li>
<li>Record missing <tt>for</tt> loop slot loads (return to lower frame).</li>
<li>Always use ANSI variants of Windows system functions.</li>
<li>Fix GC barrier for multi-result table constructor (<tt>TSETM</tt>).</li>
<li>Fix/add various FOLD rules.</li>
<li>Add potential PHI for number conversions due to type instability.</li>
<li>Do not eliminate PHIs only referenced from other PHIs.</li>
<li>Correctly anchor implicit number to string conversions in Lua/C API.</li>
<li>Fix various stack limit checks.</li>
<li>x64: Use thread-safe exceptions for external unwinding (GCC platforms).</li>
<li>x64: Fix result type of cdata index conversions.</li>
<li>x64: Fix <tt>math.random()</tt> and <tt>bit.bswap()</tt> code generation.</li>
<li>x64: Fix <tt>lightuserdata</tt> comparisons.</li>
<li>x64: Always extend stack-passed arguments to pointer size.</li>
<li>ARM: Many fixes to code generation backend.</li>
<li>PPC/e500: Fix dispatch for binop metamethods.</li>
<li>PPC/e500: Save/restore condition registers when entering/leaving the VM.</li>
<li>PPC/e500: Fix write barrier in stores of strings to upvalues.</li>
</ul></li>
<li>FFI library:
<ul>
<li>Fix C comment parsing.</li>
<li>Fix snapshot optimization for cdata comparisons.</li>
<li>Fix recording of const/enum lookups in namespaces.</li>
<li>Fix call argument and return handling for <tt>I8/U8/I16/U16</tt> types.</li>
<li>Fix unfused loads of float fields.</li>
<li>Fix <tt>ffi.string()</tt> recording.</li>
<li>Save <tt>GetLastError()</tt> around <tt>ffi.load()</tt> and symbol
resolving, too.</li>
<li>Improve ld script detection in <tt>ffi.load()</tt>.</li>
<li>Record loads/stores to external variables in namespaces.</li>
<li>Compile calls to stdcall, fastcall and vararg functions.</li>
<li>Treat function ctypes like pointers in comparisons.</li>
<li>Resolve <tt>__call</tt> metamethod for pointers, too.</li>
<li>Record C function calls with bool return values.</li>
<li>Record <tt>ffi.errno()</tt>.</li>
<li>x86: Fix number to <tt>uint32_t</tt> conversion rounding.</li>
<li>x86: Fix 64 bit arithmetic in assembler backend.</li>
<li>x64: Fix struct-by-value calling conventions.</li>
<li>ARM: Ensure invocation of SPLIT pass for float conversions.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Display trace types with <tt>-jv</tt> and <tt>-jdump</tt>.</li>
<li>Record isolated calls. But prefer recording loops over calls.</li>
<li>Specialize to prototype for non-monomorphic functions. Solves the
trace-explosion problem for closure-heavy programming styles.</li>
<li>Always generate a portable <tt>vmdef.lua</tt>. Easier for distros.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta8">LuaJIT 2.0.0-beta8 &mdash; 2011-06-23</h2>
<ul>
<li>New features:
<ul>
<li>Soft-float ARM port of LuaJIT is complete.</li>
<li>Add support for bytecode loading/saving and <tt>-b</tt> command line
option.</li>
<li>From Lua 5.2: <tt>__len</tt> metamethod for tables
(disabled by default).</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>ARM: Misc. fixes for interpreter.</li>
<li>x86/x64: Fix <tt>bit.*</tt> argument checking in interpreter.</li>
<li>Catch early out-of-memory in memory allocator initialization.</li>
<li>Fix data-flow analysis for paths leading to an upvalue close.</li>
<li>Fix check for missing arguments in <tt>string.format()</tt>.</li>
<li>Fix Solaris/x86 build (note: not a supported target).</li>
<li>Fix recording of loops with instable directions in side traces.</li>
<li>x86/x64: Fix fusion of comparisons with <tt>u8</tt>/<tt>u16</tt>
<tt>XLOAD</tt>.</li>
<li>x86/x64: Fix register allocation for variable shifts.</li>
</ul></li>
<li>FFI library:
<ul>
<li>Add <tt>ffi.errno()</tt>. Save <tt>errno</tt>/<tt>GetLastError()</tt>
around allocations etc.</li>
<li>Fix <tt>__gc</tt> for VLA/VLS cdata objects.</li>
<li>Fix recording of casts from 32 bit cdata pointers to integers.</li>
<li><tt>tonumber(cdata)</tt> returns <tt>nil</tt> for non-numbers.</li>
<li>Show address pointed to for <tt>tostring(pointer)</tt>.</li>
<li>Print <tt>NULL</tt> pointers as <tt>"cdata&lt;... *&gt;: NULL"</tt>.</li>
<li>Support <tt>__tostring</tt> metamethod for pointers to structs, too.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>More tuning for loop unrolling heuristics.</li>
<li>Flatten and compress in-memory debug info (saves ~70%).</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta7">LuaJIT 2.0.0-beta7 &mdash; 2011-05-05</h2>
<ul>
<li>New features:
<ul>
<li>ARM port of the LuaJIT interpreter is complete.</li>
<li>FFI library: Add <tt>ffi.gc()</tt>, <tt>ffi.metatype()</tt>,
<tt>ffi.istype()</tt>.</li>
<li>FFI library: Resolve ld script redirection in <tt>ffi.load()</tt>.</li>
<li>From Lua 5.2: <tt>package.searchpath()</tt>, <tt>fp:read("*L")</tt>,
<tt>load(string)</tt>.</li>
<li>From Lua 5.2, disabled by default: empty statement,
<tt>table.unpack()</tt>, modified <tt>coroutine.running()</tt>.</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>FFI library: numerous fixes.</li>
<li>Fix type mismatches in store-to-load forwarding.</li>
<li>Fix error handling within metamethods.</li>
<li>Fix <tt>table.maxn()</tt>.</li>
<li>Improve accuracy of <tt>x^-k</tt> on x64.</li>
<li>Fix code generation for Intel Atom in x64 mode.</li>
<li>Fix narrowing of POW.</li>
<li>Fix recording of retried fast functions.</li>
<li>Fix code generation for <tt>bit.bnot()</tt> and multiplies.</li>
<li>Fix error location within cpcall frames.</li>
<li>Add workaround for old libgcc unwind bug.</li>
<li>Fix <tt>lua_yield()</tt> and <tt>getmetatable(lightuserdata)</tt> on x64.</li>
<li>Misc. fixes for PPC/e500 interpreter.</li>
<li>Fix stack slot updates for down-recursion.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Add dual-number mode (int/double) for the VM. Enabled for ARM.</li>
<li>Improve narrowing of arithmetic operators and <tt>for</tt> loops.</li>
<li>Tune loop unrolling heuristics and increase trace recorder limits.</li>
<li>Eliminate dead slots in snapshots using bytecode data-flow analysis.</li>
<li>Avoid phantom stores to proxy tables.</li>
<li>Optimize lookups in empty proxy tables.</li>
<li>Improve bytecode optimization of <tt>and</tt>/<tt>or</tt> operators.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta6">LuaJIT 2.0.0-beta6 &mdash; 2011-02-11</h2>
<ul>
<li>New features:
<ul>
<li>PowerPC/e500v2 port of the LuaJIT interpreter is complete.</li>
<li>Various minor features from Lua 5.2: Hex escapes in literals,
<tt>'\*'</tt> escape, reversible <tt>string.format("%q",s)</tt>,
<tt>"%g"</tt> pattern, <tt>table.sort</tt> checks callbacks,
<tt>os.exit(status|true|false[,close])</tt>.</li>
<li>Lua 5.2 <tt>__pairs</tt> and <tt>__ipairs</tt> metamethods
(disabled by default).</li>
<li>Initial release of the FFI library.</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>Fix <tt>string.format()</tt> for non-finite numbers.</li>
<li>Fix memory leak when compiled to use the built-in allocator.</li>
<li>x86/x64: Fix unnecessary resize in <tt>TSETM</tt> bytecode.</li>
<li>Fix various GC issues with traces and <tt>jit.flush()</tt>.</li>
<li>x64: Fix fusion of indexes for array references.</li>
<li>x86/x64: Fix stack overflow handling for coroutine results.</li>
<li>Enable low-2GB memory allocation on FreeBSD/x64.</li>
<li>Fix <tt>collectgarbage("count")</tt> result if more than 2GB is in use.</li>
<li>Fix parsing of hex floats.</li>
<li>x86/x64: Fix loop branch inversion with trailing
<tt>HREF+NE/EQ</tt>.</li>
<li>Add <tt>jit.os</tt> string.</li>
<li><tt>coroutine.create()</tt> permits running C functions, too.</li>
<li>Fix OSX build to work with newer ld64 versions.</li>
<li>Fix bytecode optimization of <tt>and</tt>/<tt>or</tt> operators.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Emit specialized bytecode for <tt>pairs()</tt>/<tt>next()</tt>.</li>
<li>Improve bytecode coalescing of <tt>nil</tt> constants.</li>
<li>Compile calls to vararg functions.</li>
<li>Compile <tt>select()</tt>.</li>
<li>Improve alias analysis, esp. for loads from allocations.</li>
<li>Tuning of various compiler heuristics.</li>
<li>Refactor and extend IR conversion instructions.</li>
<li>x86/x64: Various backend enhancements related to the FFI.</li>
<li>Add SPLIT pass to split 64 bit IR instructions for 32 bit CPUs.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta5">LuaJIT 2.0.0-beta5 &mdash; 2010-08-24</h2>
<ul>
<li>Correctness and completeness:
<ul>
<li>Fix trace exit dispatch to function headers.</li>
<li>Fix Windows and OSX builds with LUAJIT_DISABLE_JIT.</li>
<li>Reorganize and fix placement of generated machine code on x64.</li>
<li>Fix TNEW in x64 interpreter.</li>
<li>Do not eliminate PHIs for values only referenced from side exits.</li>
<li>OS-independent canonicalization of strings for non-finite numbers.</li>
<li>Fix <tt>string.char()</tt> range check on x64.</li>
<li>Fix <tt>tostring()</tt> resolving within <tt>print()</tt>.</li>
<li>Fix error handling for <tt>next()</tt>.</li>
<li>Fix passing of constant arguments to external calls on x64.</li>
<li>Fix interpreter argument check for two-argument SSE math functions.</li>
<li>Fix C frame chain corruption caused by <tt>lua_cpcall()</tt>.</li>
<li>Fix return from <tt>pcall()</tt> within active hook.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Replace on-trace GC frame syncing with interpreter exit.</li>
<li>Improve hash lookup specialization by not removing dead keys during GC.</li>
<li>Turn traces into true GC objects.</li>
<li>Avoid starting a GC cycle immediately after library init.</li>
<li>Add weak guards to improve dead-code elimination.</li>
<li>Speed up string interning.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta4">LuaJIT 2.0.0-beta4 &mdash; 2010-03-28</h2>
<ul>
<li>Correctness and completeness:
<ul>
<li>Fix precondition for on-trace creation of table keys.</li>
<li>Fix <tt>{f()}</tt> on x64 when table is resized.</li>
<li>Fix folding of ordered comparisons with same references.</li>
<li>Fix snapshot restores for multi-result bytecodes.</li>
<li>Fix potential hang when recording bytecode with nested closures.</li>
<li>Fix recording of <tt>getmetatable()</tt>, <tt>tonumber()</tt> and bad argument types.</li>
<li>Fix SLOAD fusion across returns to lower frames.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Add array bounds check elimination. <tt>-Oabc</tt> is enabled by default.</li>
<li>More tuning for x64, e.g. smaller table objects.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta3">LuaJIT 2.0.0-beta3 &mdash; 2010-03-07</h2>
<ul>
<li>LuaJIT x64 port:
<ul>
<li>Port integrated memory allocator to Linux/x64, Windows/x64 and OSX/x64.</li>
<li>Port interpreter and JIT compiler to x64.</li>
<li>Port DynASM to x64.</li>
<li>Many 32/64 bit cleanups in the VM.</li>
<li>Allow building the interpreter with either x87 or SSE2 arithmetics.</li>
<li>Add external unwinding and C++ exception interop (default on x64).</li>
</ul></li>
<li>Correctness and completeness:
<ul>
<li>Fix constructor bytecode generation for certain conditional values.</li>
<li>Fix some cases of ordered string comparisons.</li>
<li>Fix <tt>lua_tocfunction()</tt>.</li>
<li>Fix cutoff register in JMP bytecode for some conditional expressions.</li>
<li>Fix PHI marking algorithm for references from variant slots.</li>
<li>Fix <tt>package.cpath</tt> for non-default PREFIX.</li>
<li>Fix DWARF2 frame unwind information for interpreter on OSX.</li>
<li>Drive the GC forward on string allocations in the parser.</li>
<li>Implement call/return hooks (zero-cost if disabled).</li>
<li>Implement yield from C hooks.</li>
<li>Disable JIT compiler on older non-SSE2 CPUs instead of aborting.</li>
</ul></li>
<li>Structural and performance enhancements:
<ul>
<li>Compile recursive code (tail-, up- and down-recursion).</li>
<li>Improve heuristics for bytecode penalties and blacklisting.</li>
<li>Split CALL/FUNC recording and clean up fast function call semantics.</li>
<li>Major redesign of internal function call handling.</li>
<li>Improve FOR loop const specialization and integerness checks.</li>
<li>Switch to pre-initialized stacks. Avoid frame-clearing.</li>
<li>Colocation of prototypes and related data: bytecode, constants, debug info.</li>
<li>Cleanup parser and streamline bytecode generation.</li>
<li>Add support for weak IR references to register allocator.</li>
<li>Switch to compressed, extensible snapshots.</li>
<li>Compile returns to frames below the start frame.</li>
<li>Improve alias analysis of upvalues using a disambiguation hash value.</li>
<li>Compile floor/ceil/trunc to SSE2 helper calls or SSE4.1 instructions.</li>
<li>Add generic C call handling to IR and backend.</li>
<li>Improve KNUM fuse vs. load heuristics.</li>
<li>Compile various <tt>io.*()</tt> functions.</li>
<li>Compile <tt>math.sinh()</tt>, <tt>math.cosh()</tt>, <tt>math.tanh()</tt>
and <tt>math.random()</tt>.</li>
</ul></li>
</ul>
<h2 id="LuaJIT-2.0.0-beta2">LuaJIT 2.0.0-beta2 &mdash; 2009-11-09</h2>
<ul>
<li>Reorganize build system. Build static+shared library on POSIX.</li>
<li>Allow C++ exception conversion on all platforms
using a wrapper function.</li>
<li>Automatically catch C++ exceptions and rethrow Lua error
(DWARF2 only).</li>
<li>Check for the correct x87 FPU precision at strategic points.</li>
<li>Always use wrappers for libm functions.</li>
<li>Resurrect metamethod name strings before copying them.</li>
<li>Mark current trace, even if compiler is idle.</li>
<li>Ensure FILE metatable is created only once.</li>
<li>Fix type comparisons when different integer types are involved.</li>
<li>Fix <tt>getmetatable()</tt> recording.</li>
<li>Fix TDUP with dead keys in template table.</li>
<li><tt>jit.flush(tr)</tt> returns status.
Prevent manual flush of a trace that's still linked.</li>
<li>Improve register allocation heuristics for invariant references.</li>
<li>Compile the push/pop variants of <tt>table.insert()</tt> and
<tt>table.remove()</tt>.</li>
<li>Compatibility with MSVC <tt>link&nbsp/debug</tt>.</li>
<li>Fix <tt>lua_iscfunction()</tt>.</li>
<li>Fix <tt>math.random()</tt> when compiled with <tt>-fpic</tt> (OSX).</li>
<li>Fix <tt>table.maxn()</tt>.</li>
<li>Bump <tt>MACOSX_DEPLOYMENT_TARGET</tt> to <tt>10.4</tt></li>
<li><tt>luaL_check*()</tt> and <tt>luaL_opt*()</tt> now support
negative arguments, too.<br>
This matches the behavior of Lua 5.1, but not the specification.</li>
</ul>
<h2 id="LuaJIT-2.0.0-beta1">LuaJIT 2.0.0-beta1 &mdash; 2009-10-31</h2>
<ul>
<li>This is the first public release of LuaJIT 2.0.</li>
<li>The whole VM has been rewritten from the ground up, so there's
no point in listing differences over earlier versions.</li>
</ul>
</div>
<div class="major" style="background: #ffff80;">
<h2 id="LuaJIT-1.1.8">LuaJIT 1.1.8 &mdash; 2012-04-16</h2>
<ul>
<li>Merged with Lua 5.1.5. Also integrated fixes for all
<a href="http://www.lua.org/bugs.html#5.1.5"><span class="ext">&raquo;</span>&nbsp;<span class="ext">&raquo;</span>&nbsp;currently known bugs in Lua 5.1.5</a>.</li>
</ul>
<h2 id="LuaJIT-1.1.7">LuaJIT 1.1.7 &mdash; 2011-05-05</h2>
<ul>
<li>Added fixes for the
<a href="http://www.lua.org/bugs.html#5.1.4"><span class="ext">&raquo;</span>&nbsp;currently known bugs in Lua 5.1.4</a>.</li>
</ul>
<h2 id="LuaJIT-1.1.6">LuaJIT 1.1.6 &mdash; 2010-03-28</h2>
<ul>
<li>Added fixes for the
<a href="http://www.lua.org/bugs.html#5.1.4"><span class="ext">&raquo;</span>&nbsp;currently known bugs in Lua 5.1.4</a>.</li>
<li>Removed wrong GC check in <tt>jit_createstate()</tt>.
Thanks to Tim Mensch.</li>
<li>Fixed bad assertions while compiling <tt>table.insert()</tt> and
<tt>table.remove()</tt>.</li>
</ul>
<h2 id="LuaJIT-1.1.5">LuaJIT 1.1.5 &mdash; 2008-10-25</h2>
<ul>
<li>Merged with Lua 5.1.4. Fixes all
<a href="http://www.lua.org/bugs.html#5.1.3"><span class="ext">&raquo;</span>&nbsp;known bugs in Lua 5.1.3</a>.</li>
</ul>
<h2 id="LuaJIT-1.1.4">LuaJIT 1.1.4 &mdash; 2008-02-05</h2>
<ul>
<li>Merged with Lua 5.1.3. Fixes all
<a href="http://www.lua.org/bugs.html#5.1.2"><span class="ext">&raquo;</span>&nbsp;known bugs in Lua 5.1.2</a>.</li>
<li>Fixed possible (but unlikely) stack corruption while compiling
<tt>k^x</tt> expressions.</li>
<li>Fixed DynASM template for cmpss instruction.</li>
</ul>
<h2 id="LuaJIT-1.1.3">LuaJIT 1.1.3 &mdash; 2007-05-24</h2>
<ul>
<li>Merged with Lua 5.1.2. Fixes all
<a href="http://www.lua.org/bugs.html#5.1.1"><span class="ext">&raquo;</span>&nbsp;known bugs in Lua 5.1.1</a>.</li>
<li>Merged pending Lua 5.1.x fixes: "return -nil" bug, spurious count hook call.</li>
<li>Remove a (sometimes) wrong assertion in <tt>luaJIT_findpc()</tt>.</li>
<li>DynASM now allows labels for displacements and <tt>.aword</tt>.</li>
<li>Fix some compiler warnings for DynASM glue (internal API change).</li>
<li>Correct naming for SSSE3 (temporarily known as SSE4) in DynASM and x86 disassembler.</li>
<li>The loadable debug modules now handle redirection to stdout
(e.g. <tt>-j&nbsp;trace=-</tt>).</li>
</ul>
<h2 id="LuaJIT-1.1.2">LuaJIT 1.1.2 &mdash; 2006-06-24</h2>
<ul>
<li>Fix MSVC inline assembly: use only local variables with
<tt>lua_number2int()</tt>.</li>
<li>Fix "attempt to call a thread value" bug on Mac OS X:
make values of consts used as lightuserdata keys unique
to avoid joining by the compiler/linker.</li>
</ul>
<h2 id="LuaJIT-1.1.1">LuaJIT 1.1.1 &mdash; 2006-06-20</h2>
<ul>
<li>Merged with Lua 5.1.1. Fixes all
<a href="http://www.lua.org/bugs.html#5.1"><span class="ext">&raquo;</span>&nbsp;known bugs in Lua 5.1</a>.</li>
<li>Enforce (dynamic) linker error for EXE/DLL version mismatches.</li>
<li>Minor changes to DynASM: faster pre-processing, smaller encoding
for some immediates.</li>
</ul>
<p>
This release is in sync with Coco 1.1.1 (see the
<a href="http://coco.luajit.org/changes.html"><span class="ext">&raquo;</span>&nbsp;Coco Change History</a>).
</p>
<h2 id="LuaJIT-1.1.0">LuaJIT 1.1.0 &mdash; 2006-03-13</h2>
<ul>
<li>Merged with Lua 5.1 (final).</li>
<li>New JIT call frame setup:
<ul>
<li>The C stack is kept 16 byte aligned (faster).
Mandatory for Mac OS X on Intel, too.</li>
<li>Faster calling conventions for internal C helper functions.</li>
<li>Better instruction scheduling for function prologue, OP_CALL and
OP_RETURN.</li>
</ul></li>
<li>Miscellaneous optimizations:
<ul>
<li>Faster loads of FP constants. Remove narrow-to-wide store-to-load
forwarding stalls.</li>
<li>Use (scalar) SSE2 ops (if the CPU supports it) to speed up slot moves
and FP to integer conversions.</li>
<li>Optimized the two-argument form of <tt>OP_CONCAT</tt> (<tt>a..b</tt>).</li>
<li>Inlined <tt>OP_MOD</tt> (<tt>a%b</tt>).
With better accuracy than the C variant, too.</li>
<li>Inlined <tt>OP_POW</tt> (<tt>a^b</tt>). Unroll <tt>x^k</tt> or
use <tt>k^x = 2^(log2(k)*x)</tt> or call <tt>pow()</tt>.</li>
</ul></li>
<li>Changes in the optimizer:
<ul>
<li>Improved hinting for table keys derived from table values
(<tt>t1[t2[x]]</tt>).</li>
<li>Lookup hinting now works with arbitrary object types and
supports index chains, too.</li>
<li>Generate type hints for arithmetic and comparison operators,
OP_LEN, OP_CONCAT and OP_FORPREP.</li>
<li>Remove several hint definitions in favour of a generic COMBINE hint.</li>
<li>Complete rewrite of <tt>jit.opt_inline</tt> module
(ex <tt>jit.opt_lib</tt>).</li>
</ul></li>
<li>Use adaptive deoptimization:
<ul>
<li>If runtime verification of a contract fails, the affected
instruction is recompiled and patched on-the-fly.
Regular programs will trigger deoptimization only occasionally.</li>
<li>This avoids generating code for uncommon fallback cases
most of the time. Generated code is up to 30% smaller compared to
LuaJIT&nbsp;1.0.3.</li>
<li>Deoptimization is used for many opcodes and contracts:
<ul>
<li>OP_CALL, OP_TAILCALL: type mismatch for callable.</li>
<li>Inlined calls: closure mismatch, parameter number and type mismatches.</li>
<li>OP_GETTABLE, OP_SETTABLE: table or key type and range mismatches.</li>
<li>All arithmetic and comparison operators, OP_LEN, OP_CONCAT,
OP_FORPREP: operand type and range mismatches.</li>
</ul></li>
<li>Complete redesign of the debug and traceback info
(bytecode &harr; mcode) to support deoptimization.
Much more flexible and needs only 50% of the space.</li>
<li>The modules <tt>jit.trace</tt>, <tt>jit.dumphints</tt> and
<tt>jit.dump</tt> handle deoptimization.</li>
</ul></li>
<li>Inlined many popular library functions
(for commonly used arguments only):
<ul>
<li>Most <tt>math.*</tt> functions (the 18 most used ones)
[2x-10x faster].</li>
<li><tt>string.len</tt>, <tt>string.sub</tt> and <tt>string.char</tt>
[2x-10x faster].</li>
<li><tt>table.insert</tt>, <tt>table.remove</tt> and <tt>table.getn</tt>
[3x-5x faster].</li>
<li><tt>coroutine.yield</tt> and <tt>coroutine.resume</tt>
[3x-5x faster].</li>
<li><tt>pairs</tt>, <tt>ipairs</tt> and the corresponding iterators
[8x-15x faster].</li>
</ul></li>
<li>Changes in the core and loadable modules and the stand-alone executable:
<ul>
<li>Added <tt>jit.version</tt>, <tt>jit.version_num</tt>
and <tt>jit.arch</tt>.</li>
<li>Reorganized some internal API functions (<tt>jit.util.*mcode*</tt>).</li>
<li>The <tt>-j dump</tt> output now shows JSUB names, too.</li>
<li>New x86 disassembler module written in pure Lua. No dependency
on ndisasm anymore. Flexible API, very compact (500 lines)
and complete (x87, MMX, SSE, SSE2, SSE3, SSSE3, privileged instructions).</li>
<li><tt>luajit -v</tt> prints the LuaJIT version and copyright
on a separate line.</li>
</ul></li>
<li>Added SSE, SSE2, SSE3 and SSSE3 support to DynASM.</li>
<li>Miscellaneous doc changes. Added a section about
<a href="install.html#embedding">embedding LuaJIT</a>.</li>
</ul>
<p>
This release is in sync with Coco 1.1.0 (see the
<a href="http://coco.luajit.org/changes.html"><span class="ext">&raquo;</span>&nbsp;Coco Change History</a>).
</p>
</div>
<div class="major" style="background: #ffffd0;">
<h2 id="LuaJIT-1.0.3">LuaJIT 1.0.3 &mdash; 2005-09-08</h2>
<ul>
<li>Even more docs.</li>
<li>Unified closure checks in <tt>jit.*</tt>.</li>
<li>Fixed some range checks in <tt>jit.util.*</tt>.</li>
<li>Fixed __newindex call originating from <tt>jit_settable_str()</tt>.</li>
<li>Merged with Lua 5.1 alpha (including early bug fixes).</li>
</ul>
<p>
This is the first public release of LuaJIT.
</p>
<h2 id="LuaJIT-1.0.2">LuaJIT 1.0.2 &mdash; 2005-09-02</h2>
<ul>
<li>Add support for flushing the Valgrind translation cache <br>
(<tt>MYCFLAGS= -DUSE_VALGRIND</tt>).</li>
<li>Add support for freeing executable mcode memory to the <tt>mmap()</tt>-based
variant for POSIX systems.</li>
<li>Reorganized the C&nbsp;function signature handling in
<tt>jit.opt_lib</tt>.</li>
<li>Changed to index-based hints for inlining C&nbsp;functions.
Still no support in the backend for inlining.</li>
<li>Hardcode <tt>HEAP_CREATE_ENABLE_EXECUTE</tt> value if undefined.</li>
<li>Misc. changes to the <tt>jit.*</tt> modules.</li>
<li>Misc. changes to the Makefiles.</li>
<li>Lots of new docs.</li>
<li>Complete doc reorg.</li>
</ul>
<p>
Not released because Lua 5.1 alpha came out today.
</p>
<h2 id="LuaJIT-1.0.1">LuaJIT 1.0.1 &mdash; 2005-08-31</h2>
<ul>
<li>Missing GC step in <tt>OP_CONCAT</tt>.</li>
<li>Fix result handling for C &ndash;> JIT calls.</li>
<li>Detect CPU feature bits.</li>
<li>Encode conditional moves (<tt>fucomip</tt>) only when supported.</li>
<li>Add fallback instructions for FP compares.</li>
<li>Add support for <tt>LUA_COMPAT_VARARG</tt>. Still disabled by default.</li>
<li>MSVC needs a specific place for the <tt>CALLBACK</tt> attribute
(David Burgess).</li>
<li>Misc. doc updates.</li>
</ul>
<p>
Interim non-public release.
Special thanks to Adam D. Moss for reporting most of the bugs.
</p>
<h2 id="LuaJIT-1.0.0">LuaJIT 1.0.0 &mdash; 2005-08-29</h2>
<p>
This is the initial non-public release of LuaJIT.
</p>
</div>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-102
View File
@@ -1,102 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Contact</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Contact</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
Please send general questions to the
<a href="http://luajit.org/list.html"><span class="ext">&raquo;</span>&nbsp;LuaJIT mailing list</a>.
You can also send any questions you have directly to me:
</p>
<script type="text/javascript">
<!--
var xS="@-:\" .0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<abc>defghijklmnopqrstuvwxyz";function xD(s)
{var len=s.length;var r="";for(var i=0;i<len;i++)
{var c=s.charAt(i);var n=xS.indexOf(c);if(n!=-1)c=xS.charAt(69-n);r+=c;}
document.write("<"+"p>"+r+"<"+"/p>\n");}
//-->
</script>
<script type="text/javascript">
<!--
xD("fyZKB8xv\"FJytmz8.KAB0u52D")
//--></script>
<noscript>
<p><img src="img/contact.png" alt="Contact info in image" width="170" height="13">
</p>
</noscript>
<h2>Copyright</h2>
<p>
All documentation is
Copyright &copy; 2005-2013 Mike Pall.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-187
View File
@@ -1,187 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Lua/C API Extensions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Lua/C API Extensions</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a class="current" href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
LuaJIT adds some extensions to the standard Lua/C API. The LuaJIT include
directory must be in the compiler search path (<tt>-I<i>path</i></tt>)
to be able to include the required header for C code:
</p>
<pre class="code">
#include "luajit.h"
</pre>
<p>
Or for C++ code:
</p>
<pre class="code">
#include "lua.hpp"
</pre>
<h2 id="luaJIT_setmode"><tt>luaJIT_setmode(L, idx, mode)</tt>
&mdash; Control VM</h2>
<p>
This is a C API extension to allow control of the VM from C code. The
full prototype of <tt>LuaJIT_setmode</tt> is:
</p>
<pre class="code">
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
</pre>
<p>
The returned status is either success (<tt>1</tt>) or failure (<tt>0</tt>).
The second argument is either <tt>0</tt> or a stack index (similar to the
other Lua/C API functions).
</p>
<p>
The third argument specifies the mode, which is 'or'ed with a flag.
The flag can be <tt>LUAJIT_MODE_OFF</tt> to turn a feature on,
<tt>LUAJIT_MODE_ON</tt> to turn a feature off, or
<tt>LUAJIT_MODE_FLUSH</tt> to flush cached code.
</p>
<p>
The following modes are defined:
</p>
<h3 id="mode_engine"><tt>luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|flag)</tt></h3>
<p>
Turn the whole JIT compiler on or off or flush the whole cache of compiled code.
</p>
<h3 id="mode_func"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_FUNC|flag)</tt><br>
<tt>luaJIT_setmode(L, idx, LUAJIT_MODE_ALLFUNC|flag)</tt><br>
<tt>luaJIT_setmode(L, idx, LUAJIT_MODE_ALLSUBFUNC|flag)</tt></h3>
<p>
This sets the mode for the function at the stack index <tt>idx</tt> or
the parent of the calling function (<tt>idx = 0</tt>). It either
enables JIT compilation for a function, disables it and flushes any
already compiled code or only flushes already compiled code. This
applies recursively to all sub-functions of the function with
<tt>LUAJIT_MODE_ALLFUNC</tt> or only to the sub-functions with
<tt>LUAJIT_MODE_ALLSUBFUNC</tt>.
</p>
<h3 id="mode_trace"><tt>luaJIT_setmode(L, trace,<br>
&nbsp;&nbsp;LUAJIT_MODE_TRACE|LUAJIT_MODE_FLUSH)</tt></h3>
<p>
Flushes the specified root trace and all of its side traces from the cache.
The code for the trace will be retained as long as there are any other
traces which link to it.
</p>
<h3 id="mode_wrapcfunc"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC|flag)</tt></h3>
<p>
This mode defines a wrapper function for calls to C functions. If
called with <tt>LUAJIT_MODE_ON</tt>, the stack index at <tt>idx</tt>
must be a <tt>lightuserdata</tt> object holding a pointer to the wrapper
function. From now on all C functions are called through the wrapper
function. If called with <tt>LUAJIT_MODE_OFF</tt> this mode is turned
off and all C functions are directly called.
</p>
<p>
The wrapper function can be used for debugging purposes or to catch
and convert foreign exceptions. But please read the section on
<a href="extensions.html#exceptions">C++&nbsp;exception interoperability</a>
first. Recommended usage can be seen in this C++ code excerpt:
</p>
<pre class="code">
#include &lt;exception&gt;
#include "lua.hpp"
// Catch C++ exceptions and convert them to Lua error messages.
// Customize as needed for your own exception classes.
static int wrap_exceptions(lua_State *L, lua_CFunction f)
{
try {
return f(L); // Call wrapped function and return result.
} catch (const char *s) { // Catch and convert exceptions.
lua_pushstring(L, s);
} catch (std::exception& e) {
lua_pushstring(L, e.what());
} catch (...) {
lua_pushliteral(L, "caught (...)");
}
return lua_error(L); // Rethrow as a Lua error.
}
static int myinit(lua_State *L)
{
...
// Define wrapper function and enable it.
lua_pushlightuserdata(L, (void *)wrap_exceptions);
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
lua_pop(L, 1);
...
}
</pre>
<p>
Note that you can only define <b>a single global wrapper function</b>,
so be careful when using this mechanism from multiple C++ modules.
Also note that this mechanism is not without overhead.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-330
View File
@@ -1,330 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>FFI Library</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>FFI Library</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a class="current" href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
The FFI library allows <b>calling external C&nbsp;functions</b> and
<b>using C&nbsp;data structures</b> from pure Lua code.
</p>
<p>
The FFI library largely obviates the need to write tedious manual
Lua/C bindings in C. No need to learn a separate binding language
&mdash; <b>it parses plain C&nbsp;declarations!</b> These can be
cut-n-pasted from C&nbsp;header files or reference manuals. It's up to
the task of binding large libraries without the need for dealing with
fragile binding generators.
</p>
<p>
The FFI library is tightly integrated into LuaJIT (it's not available
as a separate module). The code generated by the JIT-compiler for
accesses to C&nbsp;data structures from Lua code is on par with the
code a C&nbsp;compiler would generate. Calls to C&nbsp;functions can
be inlined in JIT-compiled code, unlike calls to functions bound via
the classic Lua/C API.
</p>
<p>
This page gives a short introduction to the usage of the FFI library.
<em>Please use the FFI sub-topics in the navigation bar to learn more.</em>
</p>
<h2 id="call">Motivating Example: Calling External C Functions</h2>
<p>
It's really easy to call an external C&nbsp;library function:
</p>
<pre class="code mark">
<span class="codemark">&#9312;
&#9313;
&#9314;</span>local ffi = require("ffi")
ffi.cdef[[
<span style="color:#00a000;">int printf(const char *fmt, ...);</span>
]]
ffi.C.printf("Hello %s!", "world")
</pre>
<p>
So, let's pick that apart:
</p>
<p>
<span class="mark">&#9312;</span> Load the FFI library.
</p>
<p>
<span class="mark">&#9313;</span> Add a C&nbsp;declaration
for the function. The part inside the double-brackets (in green) is
just standard C&nbsp;syntax.
</p>
<p>
<span class="mark">&#9314;</span> Call the named
C&nbsp;function &mdash; Yes, it's that simple!
</p>
<p style="font-size: 8pt;">
Actually, what goes on behind the scenes is far from simple: <span
style="color:#4040c0;">&#9314;</span> makes use of the standard
C&nbsp;library namespace <tt>ffi.C</tt>. Indexing this namespace with
a symbol name (<tt>"printf"</tt>) automatically binds it to the
standard C&nbsp;library. The result is a special kind of object which,
when called, runs the <tt>printf</tt> function. The arguments passed
to this function are automatically converted from Lua objects to the
corresponding C&nbsp;types.
</p>
<p>
Ok, so maybe the use of <tt>printf()</tt> wasn't such a spectacular
example. You could have done that with <tt>io.write()</tt> and
<tt>string.format()</tt>, too. But you get the idea ...
</p>
<p>
So here's something to pop up a message box on Windows:
</p>
<pre class="code">
local ffi = require("ffi")
ffi.cdef[[
<span style="color:#00a000;">int MessageBoxA(void *w, const char *txt, const char *cap, int type);</span>
]]
ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
</pre>
<p>
Bing! Again, that was far too easy, no?
</p>
<p style="font-size: 8pt;">
Compare this with the effort required to bind that function using the
classic Lua/C API: create an extra C&nbsp;file, add a C&nbsp;function
that retrieves and checks the argument types passed from Lua and calls
the actual C&nbsp;function, add a list of module functions and their
names, add a <tt>luaopen_*</tt> function and register all module
functions, compile and link it into a shared library (DLL), move it to
the proper path, add Lua code that loads the module aaaand ... finally
call the binding function. Phew!
</p>
<h2 id="cdata">Motivating Example: Using C Data Structures</h2>
<p>
The FFI library allows you to create and access C&nbsp;data
structures. Of course the main use for this is for interfacing with
C&nbsp;functions. But they can be used stand-alone, too.
</p>
<p>
Lua is built upon high-level data types. They are flexible, extensible
and dynamic. That's why we all love Lua so much. Alas, this can be
inefficient for certain tasks, where you'd really want a low-level
data type. E.g. a large array of a fixed structure needs to be
implemented with a big table holding lots of tiny tables. This imposes
both a substantial memory overhead as well as a performance overhead.
</p>
<p>
Here's a sketch of a library that operates on color images plus a
simple benchmark. First, the plain Lua version:
</p>
<pre class="code">
local floor = math.floor
local function image_ramp_green(n)
local img = {}
local f = 255/(n-1)
for i=1,n do
img[i] = { red = 0, green = floor((i-1)*f), blue = 0, alpha = 255 }
end
return img
end
local function image_to_grey(img, n)
for i=1,n do
local y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)
img[i].red = y; img[i].green = y; img[i].blue = y
end
end
local N = 400*400
local img = image_ramp_green(N)
for i=1,1000 do
image_to_grey(img, N)
end
</pre>
<p>
This creates a table with 160.000 pixels, each of which is a table
holding four number values in the range of 0-255. First an image with
a green ramp is created (1D for simplicity), then the image is
converted to greyscale 1000 times. Yes, that's silly, but I was in
need of a simple example ...
</p>
<p>
And here's the FFI version. The modified parts have been marked in
bold:
</p>
<pre class="code mark">
<span class="codemark">&#9312;
&#9313;
&#9314;
&#9315;
&#9314;
&#9316;</span><b>local ffi = require("ffi")
ffi.cdef[[
</b><span style="color:#00a000;">typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;</span><b>
]]</b>
local function image_ramp_green(n)
<b>local img = ffi.new("rgba_pixel[?]", n)</b>
local f = 255/(n-1)
for i=<b>0,n-1</b> do
<b>img[i].green = i*f</b>
<b>img[i].alpha = 255</b>
end
return img
end
local function image_to_grey(img, n)
for i=<b>0,n-1</b> do
local y = <b>0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue</b>
img[i].red = y; img[i].green = y; img[i].blue = y
end
end
local N = 400*400
local img = image_ramp_green(N)
for i=1,1000 do
image_to_grey(img, N)
end
</pre>
<p>
Ok, so that wasn't too difficult:
</p>
<p>
<span class="mark">&#9312;</span> First, load the FFI
library and declare the low-level data type. Here we choose a
<tt>struct</tt> which holds four byte fields, one for each component
of a 4x8&nbsp;bit RGBA pixel.
</p>
<p>
<span class="mark">&#9313;</span> Creating the data
structure with <tt>ffi.new()</tt> is straightforward &mdash; the
<tt>'?'</tt> is a placeholder for the number of elements of a
variable-length array.
</p>
<p>
<span class="mark">&#9314;</span> C&nbsp;arrays are
zero-based, so the indexes have to run from <tt>0</tt> to
<tt>n-1</tt>. One might want to allocate one more element instead to
simplify converting legacy code.
</p>
<p>
<span class="mark">&#9315;</span> Since <tt>ffi.new()</tt>
zero-fills the array by default, we only need to set the green and the
alpha fields.
</p>
<p>
<span class="mark">&#9316;</span> The calls to
<tt>math.floor()</tt> can be omitted here, because floating-point
numbers are already truncated towards zero when converting them to an
integer. This happens implicitly when the number is stored in the
fields of each pixel.
</p>
<p>
Now let's have a look at the impact of the changes: first, memory
consumption for the image is down from 22&nbsp;Megabytes to
640&nbsp;Kilobytes (400*400*4 bytes). That's a factor of 35x less! So,
yes, tables do have a noticeable overhead. BTW: The original program
would consume 40&nbsp;Megabytes in plain Lua (on x64).
</p>
<p>
Next, performance: the pure Lua version runs in 9.57 seconds (52.9
seconds with the Lua interpreter) and the FFI version runs in 0.48
seconds on my machine (YMMV). That's a factor of 20x faster (110x
faster than the Lua interpreter).
</p>
<p style="font-size: 8pt;">
The avid reader may notice that converting the pure Lua version over
to use array indexes for the colors (<tt>[1]</tt> instead of
<tt>.red</tt>, <tt>[2]</tt> instead of <tt>.green</tt> etc.) ought to
be more compact and faster. This is certainly true (by a factor of
~1.7x). Switching to a struct-of-arrays would help, too.
</p>
<p style="font-size: 8pt;">
However the resulting code would be less idiomatic and rather
error-prone. And it still doesn't get even close to the performance of
the FFI version of the code. Also, high-level data structures cannot
be easily passed to other C&nbsp;functions, especially I/O functions,
without undue conversion penalties.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-566
View File
@@ -1,566 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>ffi.* API Functions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
table.abitable { width: 30em; line-height: 1.2; }
tr.abihead td { font-weight: bold; }
td.abiparam { font-weight: bold; width: 6em; }
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1><tt>ffi.*</tt> API Functions</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a class="current" href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
This page describes the API functions provided by the FFI library in
detail. It's recommended to read through the
<a href="ext_ffi.html">introduction</a> and the
<a href="ext_ffi_tutorial.html">FFI tutorial</a> first.
</p>
<h2 id="glossary">Glossary</h2>
<ul>
<li><b>cdecl</b> &mdash; An abstract C&nbsp;type declaration (a Lua
string).</li>
<li><b>ctype</b> &mdash; A C&nbsp;type object. This is a special kind of
<b>cdata</b> returned by <tt>ffi.typeof()</tt>. It serves as a
<b>cdata</b> <a href="#ffi_new">constructor</a> when called.</li>
<li><b>cdata</b> &mdash; A C&nbsp;data object. It holds a value of the
corresponding <b>ctype</b>.</li>
<li><b>ct</b> &mdash; A C&nbsp;type specification which can be used for
most of the API functions. Either a <b>cdecl</b>, a <b>ctype</b> or a
<b>cdata</b> serving as a template type.</li>
<li><b>cb</b> &mdash; A callback object. This is a C&nbsp;data object
holding a special function pointer. Calling this function from
C&nbsp;code runs an associated Lua function.</li>
<li><b>VLA</b> &mdash; A variable-length array is declared with a
<tt>?</tt> instead of the number of elements, e.g. <tt>"int[?]"</tt>.
The number of elements (<tt>nelem</tt>) must be given when it's
<a href="#ffi_new">created</a>.</li>
<li><b>VLS</b> &mdash; A variable-length struct is a <tt>struct</tt> C
type where the last element is a <b>VLA</b>. The same rules for
declaration and creation apply.</li>
</ul>
<h2 id="decl">Declaring and Accessing External Symbols</h2>
<p>
External symbols must be declared first and can then be accessed by
indexing a <a href="ext_ffi_semantics.html#clib">C&nbsp;library
namespace</a>, which automatically binds the symbol to a specific
library.
</p>
<h3 id="ffi_cdef"><tt>ffi.cdef(def)</tt></h3>
<p>
Adds multiple C&nbsp;declarations for types or external symbols (named
variables or functions). <tt>def</tt> must be a Lua string. It's
recommended to use the syntactic sugar for string arguments as
follows:
</p>
<pre class="code">
ffi.cdef[[
<span style="color:#00a000;">typedef struct foo { int a, b; } foo_t; // Declare a struct and typedef.
int dofoo(foo_t *f, int n); /* Declare an external C function. */</span>
]]
</pre>
<p>
The contents of the string (the part in green above) must be a
sequence of
<a href="ext_ffi_semantics.html#clang">C&nbsp;declarations</a>,
separated by semicolons. The trailing semicolon for a single
declaration may be omitted.
</p>
<p>
Please note that external symbols are only <em>declared</em>, but they
are <em>not bound</em> to any specific address, yet. Binding is
achieved with C&nbsp;library namespaces (see below).
</p>
<p style="color: #c00000;">
C&nbsp;declarations are not passed through a C&nbsp;pre-processor,
yet. No pre-processor tokens are allowed, except for
<tt>#pragma&nbsp;pack</tt>. Replace <tt>#define</tt> in existing
C&nbsp;header files with <tt>enum</tt>, <tt>static&nbsp;const</tt>
or <tt>typedef</tt> and/or pass the files through an external
C&nbsp;pre-processor (once). Be careful not to include unneeded or
redundant declarations from unrelated header files.
</p>
<h3 id="ffi_C"><tt>ffi.C</tt></h3>
<p>
This is the default C&nbsp;library namespace &mdash; note the
uppercase <tt>'C'</tt>. It binds to the default set of symbols or
libraries on the target system. These are more or less the same as a
C&nbsp;compiler would offer by default, without specifying extra link
libraries.
</p>
<p>
On POSIX systems, this binds to symbols in the default or global
namespace. This includes all exported symbols from the executable and
any libraries loaded into the global namespace. This includes at least
<tt>libc</tt>, <tt>libm</tt>, <tt>libdl</tt> (on Linux),
<tt>libgcc</tt> (if compiled with GCC), as well as any exported
symbols from the Lua/C&nbsp;API provided by LuaJIT itself.
</p>
<p>
On Windows systems, this binds to symbols exported from the
<tt>*.exe</tt>, the <tt>lua51.dll</tt> (i.e. the Lua/C&nbsp;API
provided by LuaJIT itself), the C&nbsp;runtime library LuaJIT was linked
with (<tt>msvcrt*.dll</tt>), <tt>kernel32.dll</tt>,
<tt>user32.dll</tt> and <tt>gdi32.dll</tt>.
</p>
<h3 id="ffi_load"><tt>clib = ffi.load(name [,global])</tt></h3>
<p>
This loads the dynamic library given by <tt>name</tt> and returns
a new C&nbsp;library namespace which binds to its symbols. On POSIX
systems, if <tt>global</tt> is <tt>true</tt>, the library symbols are
loaded into the global namespace, too.
</p>
<p>
If <tt>name</tt> is a path, the library is loaded from this path.
Otherwise <tt>name</tt> is canonicalized in a system-dependent way and
searched in the default search path for dynamic libraries:
</p>
<p>
On POSIX systems, if the name contains no dot, the extension
<tt>.so</tt> is appended. Also, the <tt>lib</tt> prefix is prepended
if necessary. So <tt>ffi.load("z")</tt> looks for <tt>"libz.so"</tt>
in the default shared library search path.
</p>
<p>
On Windows systems, if the name contains no dot, the extension
<tt>.dll</tt> is appended. So <tt>ffi.load("ws2_32")</tt> looks for
<tt>"ws2_32.dll"</tt> in the default DLL search path.
</p>
<h2 id="create">Creating cdata Objects</h2>
<p>
The following API functions create cdata objects (<tt>type()</tt>
returns <tt>"cdata"</tt>). All created cdata objects are
<a href="ext_ffi_semantics.html#gc">garbage collected</a>.
</p>
<h3 id="ffi_new"><tt>cdata = ffi.new(ct [,nelem] [,init...])<br>
cdata = <em>ctype</em>([nelem,] [init...])</tt></h3>
<p>
Creates a cdata object for the given <tt>ct</tt>. VLA/VLS types
require the <tt>nelem</tt> argument. The second syntax uses a ctype as
a constructor and is otherwise fully equivalent.
</p>
<p>
The cdata object is initialized according to the
<a href="ext_ffi_semantics.html#init">rules for initializers</a>,
using the optional <tt>init</tt> arguments. Excess initializers cause
an error.
</p>
<p>
Performance notice: if you want to create many objects of one kind,
parse the cdecl only once and get its ctype with
<tt>ffi.typeof()</tt>. Then use the ctype as a constructor repeatedly.
</p>
<p style="font-size: 8pt;">
Please note that an anonymous <tt>struct</tt> declaration implicitly
creates a new and distinguished ctype every time you use it for
<tt>ffi.new()</tt>. This is probably <b>not</b> what you want,
especially if you create more than one cdata object. Different anonymous
<tt>structs</tt> are not considered assignment-compatible by the
C&nbsp;standard, even though they may have the same fields! Also, they
are considered different types by the JIT-compiler, which may cause an
excessive number of traces. It's strongly suggested to either declare
a named <tt>struct</tt> or <tt>typedef</tt> with <tt>ffi.cdef()</tt>
or to create a single ctype object for an anonymous <tt>struct</tt>
with <tt>ffi.typeof()</tt>.
</p>
<h3 id="ffi_typeof"><tt>ctype = ffi.typeof(ct)</tt></h3>
<p>
Creates a ctype object for the given <tt>ct</tt>.
</p>
<p>
This function is especially useful to parse a cdecl only once and then
use the resulting ctype object as a <a href="#ffi_new">constructor</a>.
</p>
<h3 id="ffi_cast"><tt>cdata = ffi.cast(ct, init)</tt></h3>
<p>
Creates a scalar cdata object for the given <tt>ct</tt>. The cdata
object is initialized with <tt>init</tt> using the "cast" variant of
the <a href="ext_ffi_semantics.html#convert">C&nbsp;type conversion
rules</a>.
</p>
<p>
This functions is mainly useful to override the pointer compatibility
checks or to convert pointers to addresses or vice versa.
</p>
<h3 id="ffi_metatype"><tt>ctype = ffi.metatype(ct, metatable)</tt></h3>
<p>
Creates a ctype object for the given <tt>ct</tt> and associates it with
a metatable. Only <tt>struct</tt>/<tt>union</tt> types, complex numbers
and vectors are allowed. Other types may be wrapped in a
<tt>struct</tt>, if needed.
</p>
<p>
The association with a metatable is permanent and cannot be changed
afterwards. Neither the contents of the <tt>metatable</tt> nor the
contents of an <tt>__index</tt> table (if any) may be modified
afterwards. The associated metatable automatically applies to all uses
of this type, no matter how the objects are created or where they
originate from. Note that pre-defined operations on types have
precedence (e.g. declared field names cannot be overriden).
</p>
<p>
All standard Lua metamethods are implemented. These are called directly,
without shortcuts and on any mix of types. For binary operations, the
left operand is checked first for a valid ctype metamethod. The
<tt>__gc</tt> metamethod only applies to <tt>struct</tt>/<tt>union</tt>
types and performs an implicit <a href="#ffi_gc"><tt>ffi.gc()</tt></a>
call during creation of an instance.
</p>
<h3 id="ffi_gc"><tt>cdata = ffi.gc(cdata, finalizer)</tt></h3>
<p>
Associates a finalizer with a pointer or aggregate cdata object. The
cdata object is returned unchanged.
</p>
<p>
This function allows safe integration of unmanaged resources into the
automatic memory management of the LuaJIT garbage collector. Typical
usage:
</p>
<pre class="code">
local p = ffi.gc(ffi.C.malloc(n), ffi.C.free)
...
p = nil -- Last reference to p is gone.
-- GC will eventually run finalizer: ffi.C.free(p)
</pre>
<p>
A cdata finalizer works like the <tt>__gc</tt> metamethod for userdata
objects: when the last reference to a cdata object is gone, the
associated finalizer is called with the cdata object as an argument. The
finalizer can be a Lua function or a cdata function or cdata function
pointer. An existing finalizer can be removed by setting a <tt>nil</tt>
finalizer, e.g. right before explicitly deleting a resource:
</p>
<pre class="code">
ffi.C.free(ffi.gc(p, nil)) -- Manually free the memory.
</pre>
<h2 id="info">C&nbsp;Type Information</h2>
<p>
The following API functions return information about C&nbsp;types.
They are most useful for inspecting cdata objects.
</p>
<h3 id="ffi_sizeof"><tt>size = ffi.sizeof(ct [,nelem])</tt></h3>
<p>
Returns the size of <tt>ct</tt> in bytes. Returns <tt>nil</tt> if
the size is not known (e.g. for <tt>"void"</tt> or function types).
Requires <tt>nelem</tt> for VLA/VLS types, except for cdata objects.
</p>
<h3 id="ffi_alignof"><tt>align = ffi.alignof(ct)</tt></h3>
<p>
Returns the minimum required alignment for <tt>ct</tt> in bytes.
</p>
<h3 id="ffi_offsetof"><tt>ofs [,bpos,bsize] = ffi.offsetof(ct, field)</tt></h3>
<p>
Returns the offset (in bytes) of <tt>field</tt> relative to the start
of <tt>ct</tt>, which must be a <tt>struct</tt>. Additionally returns
the position and the field size (in bits) for bit fields.
</p>
<h3 id="ffi_istype"><tt>status = ffi.istype(ct, obj)</tt></h3>
<p>
Returns <tt>true</tt> if <tt>obj</tt> has the C&nbsp;type given by
<tt>ct</tt>. Returns <tt>false</tt> otherwise.
</p>
<p>
C&nbsp;type qualifiers (<tt>const</tt> etc.) are ignored. Pointers are
checked with the standard pointer compatibility rules, but without any
special treatment for <tt>void&nbsp;*</tt>. If <tt>ct</tt> specifies a
<tt>struct</tt>/<tt>union</tt>, then a pointer to this type is accepted,
too. Otherwise the types must match exactly.
</p>
<p>
Note: this function accepts all kinds of Lua objects for the
<tt>obj</tt> argument, but always returns <tt>false</tt> for non-cdata
objects.
</p>
<h2 id="util">Utility Functions</h2>
<h3 id="ffi_errno"><tt>err = ffi.errno([newerr])</tt></h3>
<p>
Returns the error number set by the last C&nbsp;function call which
indicated an error condition. If the optional <tt>newerr</tt> argument
is present, the error number is set to the new value and the previous
value is returned.
</p>
<p>
This function offers a portable and OS-independent way to get and set the
error number. Note that only <em>some</em> C&nbsp;functions set the error
number. And it's only significant if the function actually indicated an
error condition (e.g. with a return value of <tt>-1</tt> or
<tt>NULL</tt>). Otherwise, it may or may not contain any previously set
value.
</p>
<p>
You're advised to call this function only when needed and as close as
possible after the return of the related C&nbsp;function. The
<tt>errno</tt> value is preserved across hooks, memory allocations,
invocations of the JIT compiler and other internal VM activity. The same
applies to the value returned by <tt>GetLastError()</tt> on Windows, but
you need to declare and call it yourself.
</p>
<h3 id="ffi_string"><tt>str = ffi.string(ptr [,len])</tt></h3>
<p>
Creates an interned Lua string from the data pointed to by
<tt>ptr</tt>.
</p>
<p>
If the optional argument <tt>len</tt> is missing, <tt>ptr</tt> is
converted to a <tt>"char&nbsp;*"</tt> and the data is assumed to be
zero-terminated. The length of the string is computed with
<tt>strlen()</tt>.
</p>
<p>
Otherwise <tt>ptr</tt> is converted to a <tt>"void&nbsp;*"</tt> and
<tt>len</tt> gives the length of the data. The data may contain
embedded zeros and need not be byte-oriented (though this may cause
endianess issues).
</p>
<p>
This function is mainly useful to convert (temporary)
<tt>"const&nbsp;char&nbsp;*"</tt> pointers returned by
C&nbsp;functions to Lua strings and store them or pass them to other
functions expecting a Lua string. The Lua string is an (interned) copy
of the data and bears no relation to the original data area anymore.
Lua strings are 8&nbsp;bit clean and may be used to hold arbitrary,
non-character data.
</p>
<p>
Performance notice: it's faster to pass the length of the string, if
it's known. E.g. when the length is returned by a C&nbsp;call like
<tt>sprintf()</tt>.
</p>
<h3 id="ffi_copy"><tt>ffi.copy(dst, src, len)<br>
ffi.copy(dst, str)</tt></h3>
<p>
Copies the data pointed to by <tt>src</tt> to <tt>dst</tt>.
<tt>dst</tt> is converted to a <tt>"void&nbsp;*"</tt> and <tt>src</tt>
is converted to a <tt>"const void&nbsp;*"</tt>.
</p>
<p>
In the first syntax, <tt>len</tt> gives the number of bytes to copy.
Caveat: if <tt>src</tt> is a Lua string, then <tt>len</tt> must not
exceed <tt>#src+1</tt>.
</p>
<p>
In the second syntax, the source of the copy must be a Lua string. All
bytes of the string <em>plus a zero-terminator</em> are copied to
<tt>dst</tt> (i.e. <tt>#src+1</tt> bytes).
</p>
<p>
Performance notice: <tt>ffi.copy()</tt> may be used as a faster
(inlinable) replacement for the C&nbsp;library functions
<tt>memcpy()</tt>, <tt>strcpy()</tt> and <tt>strncpy()</tt>.
</p>
<h3 id="ffi_fill"><tt>ffi.fill(dst, len [,c])</tt></h3>
<p>
Fills the data pointed to by <tt>dst</tt> with <tt>len</tt> constant
bytes, given by <tt>c</tt>. If <tt>c</tt> is omitted, the data is
zero-filled.
</p>
<p>
Performance notice: <tt>ffi.fill()</tt> may be used as a faster
(inlinable) replacement for the C&nbsp;library function
<tt>memset(dst,&nbsp;c,&nbsp;len)</tt>. Please note the different
order of arguments!
</p>
<h2 id="target">Target-specific Information</h2>
<h3 id="ffi_abi"><tt>status = ffi.abi(param)</tt></h3>
<p>
Returns <tt>true</tt> if <tt>param</tt> (a Lua string) applies for the
target ABI (Application Binary Interface). Returns <tt>false</tt>
otherwise. The following parameters are currently defined:
</p>
<table class="abitable">
<tr class="abihead">
<td class="abiparam">Parameter</td>
<td class="abidesc">Description</td>
</tr>
<tr class="odd separate">
<td class="abiparam">32bit</td><td class="abidesc">32 bit architecture</td></tr>
<tr class="even">
<td class="abiparam">64bit</td><td class="abidesc">64 bit architecture</td></tr>
<tr class="odd separate">
<td class="abiparam">le</td><td class="abidesc">Little-endian architecture</td></tr>
<tr class="even">
<td class="abiparam">be</td><td class="abidesc">Big-endian architecture</td></tr>
<tr class="odd separate">
<td class="abiparam">fpu</td><td class="abidesc">Target has a hardware FPU</td></tr>
<tr class="even">
<td class="abiparam">softfp</td><td class="abidesc">softfp calling conventions</td></tr>
<tr class="odd">
<td class="abiparam">hardfp</td><td class="abidesc">hardfp calling conventions</td></tr>
<tr class="even separate">
<td class="abiparam">eabi</td><td class="abidesc">EABI variant of the standard ABI</td></tr>
<tr class="odd">
<td class="abiparam">win</td><td class="abidesc">Windows variant of the standard ABI</td></tr>
</table>
<h3 id="ffi_os"><tt>ffi.os</tt></h3>
<p>
Contains the target OS name. Same contents as
<a href="ext_jit.html#jit_os"><tt>jit.os</tt></a>.
</p>
<h3 id="ffi_arch"><tt>ffi.arch</tt></h3>
<p>
Contains the target architecture name. Same contents as
<a href="ext_jit.html#jit_arch"><tt>jit.arch</tt></a>.
</p>
<h2 id="callback">Methods for Callbacks</h2>
<p>
The C&nbsp;types for <a href="ext_ffi_semantics.html#callback">callbacks</a>
have some extra methods:
</p>
<h3 id="callback_free"><tt>cb:free()</tt></h3>
<p>
Free the resources associated with a callback. The associated Lua
function is unanchored and may be garbage collected. The callback
function pointer is no longer valid and must not be called anymore
(it may be reused by a subsequently created callback).
</p>
<h3 id="callback_set"><tt>cb:set(func)</tt></h3>
<p>
Associate a new Lua function with a callback. The C&nbsp;type of the
callback and the callback function pointer are unchanged.
</p>
<p>
This method is useful to dynamically switch the receiver of callbacks
without creating a new callback each time and registering it again (e.g.
with a GUI library).
</p>
<h2 id="extended">Extended Standard Library Functions</h2>
<p>
The following standard library functions have been extended to work
with cdata objects:
</p>
<h3 id="tonumber"><tt>n = tonumber(cdata)</tt></h3>
<p>
Converts a number cdata object to a <tt>double</tt> and returns it as
a Lua number. This is particularly useful for boxed 64&nbsp;bit
integer values. Caveat: this conversion may incur a precision loss.
</p>
<h3 id="tostring"><tt>s = tostring(cdata)</tt></h3>
<p>
Returns a string representation of the value of 64&nbsp;bit integers
(<tt><b>"</b>nnn<b>LL"</b></tt> or <tt><b>"</b>nnn<b>ULL"</b></tt>) or
complex numbers (<tt><b>"</b>re&plusmn;im<b>i"</b></tt>). Otherwise
returns a string representation of the C&nbsp;type of a ctype object
(<tt><b>"ctype&lt;</b>type<b>&gt;"</b></tt>) or a cdata object
(<tt><b>"cdata&lt;</b>type<b>&gt;:&nbsp;</b>address"</tt>), unless you
override it with a <tt>__tostring</tt> metamethod (see
<a href="#ffi_metatype"><tt>ffi.metatype()</tt></a>).
</p>
<h3 id="pairs"><tt>iter, obj, start = pairs(cdata)<br>
iter, obj, start = ipairs(cdata)<br></tt></h3>
<p>
Calls the <tt>__pairs</tt> or <tt>__ipairs</tt> metamethod of the
corresponding ctype.
</p>
<h2 id="literals">Extensions to the Lua Parser</h2>
<p>
The parser for Lua source code treats numeric literals with the
suffixes <tt>LL</tt> or <tt>ULL</tt> as signed or unsigned 64&nbsp;bit
integers. Case doesn't matter, but uppercase is recommended for
readability. It handles both decimal (<tt>42LL</tt>) and hexadecimal
(<tt>0x2aLL</tt>) literals.
</p>
<p>
The imaginary part of complex numbers can be specified by suffixing
number literals with <tt>i</tt> or <tt>I</tt>, e.g. <tt>12.5i</tt>.
Caveat: you'll need to use <tt>1i</tt> to get an imaginary part with
the value one, since <tt>i</tt> itself still refers to a variable
named <tt>i</tt>.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
File diff suppressed because it is too large Load Diff
-601
View File
@@ -1,601 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>FFI Tutorial</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
table.idiomtable { font-size: 90%; line-height: 1.2; }
table.idiomtable tt { font-size: 100%; }
table.idiomtable td { vertical-align: top; }
tr.idiomhead td { font-weight: bold; }
td.idiomlua b { font-weight: normal; color: #2142bf; }
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>FFI Tutorial</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a class="current" href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
This page is intended to give you an overview of the features of the FFI
library by presenting a few use cases and guidelines.
</p>
<p>
This page makes no attempt to explain all of the FFI library, though.
You'll want to have a look at the <a href="ext_ffi_api.html">ffi.* API
function reference</a> and the <a href="ext_ffi_semantics.html">FFI
semantics</a> to learn more.
</p>
<h2 id="load">Loading the FFI Library</h2>
<p>
The FFI library is built into LuaJIT by default, but it's not loaded
and initialized by default. The suggested way to use the FFI library
is to add the following to the start of every Lua file that needs one
of its functions:
</p>
<pre class="code">
local ffi = require("ffi")
</pre>
<p>
Please note this doesn't define an <tt>ffi</tt> variable in the table
of globals &mdash; you really need to use the local variable. The
<tt>require</tt> function ensures the library is only loaded once.
</p>
<p style="font-size: 8pt;">
Note: If you want to experiment with the FFI from the interactive prompt
of the command line executable, omit the <tt>local</tt>, as it doesn't
preserve local variables across lines.
</p>
<h2 id="sleep">Accessing Standard System Functions</h2>
<p>
The following code explains how to access standard system functions.
We slowly print two lines of dots by sleeping for 10&nbsp;milliseconds
after each dot:
</p>
<pre class="code mark">
<span class="codemark">&nbsp;
&#9312;
&#9313;
&#9314;
&#9315;
&#9316;
&#9317;</span>local ffi = require("ffi")
ffi.cdef[[
<span style="color:#00a000;">void Sleep(int ms);
int poll(struct pollfd *fds, unsigned long nfds, int timeout);</span>
]]
local sleep
if ffi.os == "Windows" then
function sleep(s)
ffi.C.Sleep(s*1000)
end
else
function sleep(s)
ffi.C.poll(nil, 0, s*1000)
end
end
for i=1,160 do
io.write("."); io.flush()
sleep(0.01)
end
io.write("\n")
</pre>
<p>
Here's the step-by-step explanation:
</p>
<p>
<span class="mark">&#9312;</span> This defines the
C&nbsp;library functions we're going to use. The part inside the
double-brackets (in green) is just standard C&nbsp;syntax. You can
usually get this info from the C&nbsp;header files or the
documentation provided by each C&nbsp;library or C&nbsp;compiler.
</p>
<p>
<span class="mark">&#9313;</span> The difficulty we're
facing here, is that there are different standards to choose from.
Windows has a simple <tt>Sleep()</tt> function. On other systems there
are a variety of functions available to achieve sub-second sleeps, but
with no clear consensus. Thankfully <tt>poll()</tt> can be used for
this task, too, and it's present on most non-Windows systems. The
check for <tt>ffi.os</tt> makes sure we use the Windows-specific
function only on Windows systems.
</p>
<p>
<span class="mark">&#9314;</span> Here we're wrapping the
call to the C&nbsp;function in a Lua function. This isn't strictly
necessary, but it's helpful to deal with system-specific issues only
in one part of the code. The way we're wrapping it ensures the check
for the OS is only done during initialization and not for every call.
</p>
<p>
<span class="mark">&#9315;</span> A more subtle point is
that we defined our <tt>sleep()</tt> function (for the sake of this
example) as taking the number of seconds, but accepting fractional
seconds. Multiplying this by 1000 gets us milliseconds, but that still
leaves it a Lua number, which is a floating-point value. Alas, the
<tt>Sleep()</tt> function only accepts an integer value. Luckily for
us, the FFI library automatically performs the conversion when calling
the function (truncating the FP value towards zero, like in C).
</p>
<p style="font-size: 8pt;">
Some readers will notice that <tt>Sleep()</tt> is part of
<tt>KERNEL32.DLL</tt> and is also a <tt>stdcall</tt> function. So how
can this possibly work? The FFI library provides the <tt>ffi.C</tt>
default C&nbsp;library namespace, which allows calling functions from
the default set of libraries, like a C&nbsp;compiler would. Also, the
FFI library automatically detects <tt>stdcall</tt> functions, so you
don't need to declare them as such.
</p>
<p>
<span class="mark">&#9316;</span> The <tt>poll()</tt>
function takes a couple more arguments we're not going to use. You can
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
for the <tt>nfds</tt> parameter. Please note that the
number&nbsp;<tt>0</tt> <em>does not convert to a pointer value</em>,
unlike in C++. You really have to pass pointers to pointer arguments
and numbers to number arguments.
</p>
<p style="font-size: 8pt;">
The page on <a href="ext_ffi_semantics.html">FFI semantics</a> has all
of the gory details about
<a href="ext_ffi_semantics.html#convert">conversions between Lua
objects and C&nbsp;types</a>. For the most part you don't have to deal
with this, as it's performed automatically and it's carefully designed
to bridge the semantic differences between Lua and C.
</p>
<p>
<span class="mark">&#9317;</span> Now that we have defined
our own <tt>sleep()</tt> function, we can just call it from plain Lua
code. That wasn't so bad, huh? Turning these boring animated dots into
a fascinating best-selling game is left as an exercise for the reader.
:-)
</p>
<h2 id="zlib">Accessing the zlib Compression Library</h2>
<p>
The following code shows how to access the <a
href="http://zlib.net/">zlib</a> compression library from Lua code.
We'll define two convenience wrapper functions that take a string and
compress or uncompress it to another string:
</p>
<pre class="code mark">
<span class="codemark">&nbsp;
&#9312;
&#9313;
&#9314;
&#9315;
&#9316;
&#9317;
&#9318;</span>local ffi = require("ffi")
ffi.cdef[[
<span style="color:#00a000;">unsigned long compressBound(unsigned long sourceLen);
int compress2(uint8_t *dest, unsigned long *destLen,
const uint8_t *source, unsigned long sourceLen, int level);
int uncompress(uint8_t *dest, unsigned long *destLen,
const uint8_t *source, unsigned long sourceLen);</span>
]]
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")
local function compress(txt)
local n = zlib.compressBound(#txt)
local buf = ffi.new("uint8_t[?]", n)
local buflen = ffi.new("unsigned long[1]", n)
local res = zlib.compress2(buf, buflen, txt, #txt, 9)
assert(res == 0)
return ffi.string(buf, buflen[0])
end
local function uncompress(comp, n)
local buf = ffi.new("uint8_t[?]", n)
local buflen = ffi.new("unsigned long[1]", n)
local res = zlib.uncompress(buf, buflen, comp, #comp)
assert(res == 0)
return ffi.string(buf, buflen[0])
end
-- Simple test code.
local txt = string.rep("abcd", 1000)
print("Uncompressed size: ", #txt)
local c = compress(txt)
print("Compressed size: ", #c)
local txt2 = uncompress(c, #txt)
assert(txt2 == txt)
</pre>
<p>
Here's the step-by-step explanation:
</p>
<p>
<span class="mark">&#9312;</span> This defines some of the
C&nbsp;functions provided by zlib. For the sake of this example, some
type indirections have been reduced and it uses the pre-defined
fixed-size integer types, while still adhering to the zlib API/ABI.
</p>
<p>
<span class="mark">&#9313;</span> This loads the zlib shared
library. On POSIX systems it's named <tt>libz.so</tt> and usually
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
missing standard prefixes/suffixes, we can simply load the
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
you'll have to download it first from the
<a href="http://zlib.net/"><span class="ext">&raquo;</span>&nbsp;zlib site</a>. The check for
<tt>ffi.os</tt> makes sure we pass the right name to
<tt>ffi.load()</tt>.
</p>
<p>
<span class="mark">&#9314;</span> First, the maximum size of
the compression buffer is obtained by calling the
<tt>zlib.compressBound</tt> function with the length of the
uncompressed string. The next line allocates a byte buffer of this
size. The <tt>[?]</tt> in the type specification indicates a
variable-length array (VLA). The actual number of elements of this
array is given as the 2nd argument to <tt>ffi.new()</tt>.
</p>
<p>
<span class="mark">&#9315;</span> This may look strange at
first, but have a look at the declaration of the <tt>compress2</tt>
function from zlib: the destination length is defined as a pointer!
This is because you pass in the maximum buffer size and get back the
actual length that was used.
</p>
<p>
In C you'd pass in the address of a local variable
(<tt>&amp;buflen</tt>). But since there's no address-of operator in
Lua, we'll just pass in a one-element array. Conveniently it can be
initialized with the maximum buffer size in one step. Calling the
actual <tt>zlib.compress2</tt> function is then straightforward.
</p>
<p>
<span class="mark">&#9316;</span> We want to return the
compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>.
It needs a pointer to the start of the data and the actual length. The
length has been returned in the <tt>buflen</tt> array, so we'll just
get it from there.
</p>
<p style="font-size: 8pt;">
Note that since the function returns now, the <tt>buf</tt> and
<tt>buflen</tt> variables will eventually be garbage collected. This
is fine, because <tt>ffi.string()</tt> has copied the contents to a
newly created (interned) Lua string. If you plan to call this function
lots of times, consider reusing the buffers and/or handing back the
results in buffers instead of strings. This will reduce the overhead
for garbage collection and string interning.
</p>
<p>
<span class="mark">&#9317;</span> The <tt>uncompress</tt>
functions does the exact opposite of the <tt>compress</tt> function.
The compressed data doesn't include the size of the original string,
so this needs to be passed in. Otherwise no surprises here.
</p>
<p>
<span class="mark">&#9318;</span> The code, that makes use
of the functions we just defined, is just plain Lua code. It doesn't
need to know anything about the LuaJIT FFI &mdash; the convenience
wrapper functions completely hide it.
</p>
<p>
One major advantage of the LuaJIT FFI is that you are now able to
write those wrappers <em>in Lua</em>. And at a fraction of the time it
would cost you to create an extra C&nbsp;module using the Lua/C API.
Many of the simpler C&nbsp;functions can probably be used directly
from your Lua code, without any wrappers.
</p>
<p style="font-size: 8pt;">
Side note: the zlib API uses the <tt>long</tt> type for passing
lengths and sizes around. But all those zlib functions actually only
deal with 32&nbsp;bit values. This is an unfortunate choice for a
public API, but may be explained by zlib's history &mdash; we'll just
have to deal with it.
</p>
<p style="font-size: 8pt;">
First, you should know that a <tt>long</tt> is a 64&nbsp;bit type e.g.
on POSIX/x64 systems, but a 32&nbsp;bit type on Windows/x64 and on
32&nbsp;bit systems. Thus a <tt>long</tt> result can be either a plain
Lua number or a boxed 64&nbsp;bit integer cdata object, depending on
the target system.
</p>
<p style="font-size: 8pt;">
Ok, so the <tt>ffi.*</tt> functions generally accept cdata objects
wherever you'd want to use a number. That's why we get a away with
passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua
library functions or modules don't know how to deal with this. So for
maximum portability one needs to use <tt>tonumber()</tt> on returned
<tt>long</tt> results before passing them on. Otherwise the
application might work on some systems, but would fail in a POSIX/x64
environment.
</p>
<h2 id="metatype">Defining Metamethods for a C&nbsp;Type</h2>
<p>
The following code explains how to define metamethods for a C type.
We define a simple point type and add some operations to it:
</p>
<pre class="code mark">
<span class="codemark">&nbsp;
&#9312;
&#9313;
&#9314;
&#9315;
&#9316;
&#9317;</span>local ffi = require("ffi")
ffi.cdef[[
<span style="color:#00a000;">typedef struct { double x, y; } point_t;</span>
]]
local point
local mt = {
__add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
__len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
__index = {
area = function(a) return a.x*a.x + a.y*a.y end,
},
}
point = ffi.metatype("point_t", mt)
local a = point(3, 4)
print(a.x, a.y) --> 3 4
print(#a) --> 5
print(a:area()) --> 25
local b = a + point(0.5, 8)
print(#b) --> 12.5
</pre>
<p>
Here's the step-by-step explanation:
</p>
<p>
<span class="mark">&#9312;</span> This defines the C&nbsp;type for a
two-dimensional point object.
</p>
<p>
<span class="mark">&#9313;</span> We have to declare the variable
holding the point constructor first, because it's used inside of a
metamethod.
</p>
<p>
<span class="mark">&#9314;</span> Let's define an <tt>__add</tt>
metamethod which adds the coordinates of two points and creates a new
point object. For simplicity, this function assumes that both arguments
are points. But it could be any mix of objects, if at least one operand
is of the required type (e.g. adding a point plus a number or vice
versa). Our <tt>__len</tt> metamethod returns the distance of a point to
the origin.
</p>
<p>
<span class="mark">&#9315;</span> If we run out of operators, we can
define named methods, too. Here the <tt>__index</tt> table defines an
<tt>area</tt> function. For custom indexing needs, one might want to
define <tt>__index</tt> and <tt>__newindex</tt> <em>functions</em> instead.
</p>
<p>
<span class="mark">&#9316;</span> This associates the metamethods with
our C&nbsp;type. This only needs to be done once. For convenience, a
constructor is returned by
<a href="ext_ffi_api.html#ffi_metatype"><tt>ffi.metatype()</tt></a>.
We're not required to use it, though. The original C&nbsp;type can still
be used e.g. to create an array of points. The metamethods automatically
apply to any and all uses of this type.
</p>
<p>
Please note that the association with a metatable is permanent and
<b>the metatable must not be modified afterwards!</b> Ditto for the
<tt>__index</tt> table.
</p>
<p>
<span class="mark">&#9317;</span> Here are some simple usage examples
for the point type and their expected results. The pre-defined
operations (such as <tt>a.x</tt>) can be freely mixed with the newly
defined metamethods. Note that <tt>area</tt> is a method and must be
called with the Lua syntax for methods: <tt>a:area()</tt>, not
<tt>a.area()</tt>.
</p>
<p>
The C&nbsp;type metamethod mechanism is most useful when used in
conjunction with C&nbsp;libraries that are written in an object-oriented
style. Creators return a pointer to a new instance and methods take an
instance pointer as the first argument. Sometimes you can just point
<tt>__index</tt> to the library namespace and <tt>__gc</tt> to the
destructor and you're done. But often enough you'll want to add
convenience wrappers, e.g. to return actual Lua strings or when
returning multiple values.
</p>
<p>
Some C libraries only declare instance pointers as an opaque
<tt>void&nbsp;*</tt> type. In this case you can use a fake type for all
declarations, e.g. a pointer to a named (incomplete) struct will do:
<tt>typedef struct foo_type *foo_handle</tt>. The C&nbsp;side doesn't
know what you declare with the LuaJIT FFI, but as long as the underlying
types are compatible, everything still works.
</p>
<h2 id="idioms">Translating C&nbsp;Idioms</h2>
<p>
Here's a list of common C&nbsp;idioms and their translation to the
LuaJIT FFI:
</p>
<table class="idiomtable">
<tr class="idiomhead">
<td class="idiomdesc">Idiom</td>
<td class="idiomc">C&nbsp;code</td>
<td class="idiomlua">Lua code</td>
</tr>
<tr class="odd separate">
<td class="idiomdesc">Pointer dereference<br><tt>int *p;</tt></td><td class="idiomc"><tt>x = *p;<br>*p = y;</tt></td><td class="idiomlua"><tt>x = <b>p[0]</b><br><b>p[0]</b> = y</tt></td></tr>
<tr class="even">
<td class="idiomdesc">Pointer indexing<br><tt>int i, *p;</tt></td><td class="idiomc"><tt>x = p[i];<br>p[i+1] = y;</tt></td><td class="idiomlua"><tt>x = p[i]<br>p[i+1] = y</tt></td></tr>
<tr class="odd">
<td class="idiomdesc">Array indexing<br><tt>int i, a[];</tt></td><td class="idiomc"><tt>x = a[i];<br>a[i+1] = y;</tt></td><td class="idiomlua"><tt>x = a[i]<br>a[i+1] = y</tt></td></tr>
<tr class="even separate">
<td class="idiomdesc"><tt>struct</tt>/<tt>union</tt> dereference<br><tt>struct foo s;</tt></td><td class="idiomc"><tt>x = s.field;<br>s.field = y;</tt></td><td class="idiomlua"><tt>x = s.field<br>s.field = y</tt></td></tr>
<tr class="odd">
<td class="idiomdesc"><tt>struct</tt>/<tt>union</tt> pointer deref.<br><tt>struct foo *sp;</tt></td><td class="idiomc"><tt>x = sp->field;<br>sp->field = y;</tt></td><td class="idiomlua"><tt>x = <b>s.field</b><br><b>s.field</b> = y</tt></td></tr>
<tr class="even separate">
<td class="idiomdesc">Pointer arithmetic<br><tt>int i, *p;</tt></td><td class="idiomc"><tt>x = p + i;<br>y = p - i;</tt></td><td class="idiomlua"><tt>x = p + i<br>y = p - i</tt></td></tr>
<tr class="odd">
<td class="idiomdesc">Pointer difference<br><tt>int *p1, *p2;</tt></td><td class="idiomc"><tt>x = p1 - p2;</tt></td><td class="idiomlua"><tt>x = p1 - p2</tt></td></tr>
<tr class="even">
<td class="idiomdesc">Array element pointer<br><tt>int i, a[];</tt></td><td class="idiomc"><tt>x = &amp;a[i];</tt></td><td class="idiomlua"><tt>x = <b>a+i</b></tt></td></tr>
<tr class="odd">
<td class="idiomdesc">Cast pointer to address<br><tt>int *p;</tt></td><td class="idiomc"><tt>x = (intptr_t)p;</tt></td><td class="idiomlua"><tt>x = <b>tonumber(<br>&nbsp;ffi.cast("intptr_t",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p))</b></tt></td></tr>
<tr class="even separate">
<td class="idiomdesc">Functions with outargs<br><tt>void foo(int *inoutlen);</tt></td><td class="idiomc"><tt>int len = x;<br>foo(&amp;len);<br>y = len;</tt></td><td class="idiomlua"><tt><b>local len =<br>&nbsp;&nbsp;ffi.new("int[1]", x)<br>foo(len)<br>y = len[0]</b></tt></td></tr>
<tr class="odd">
<td class="idiomdesc"><a href="ext_ffi_semantics.html#convert_vararg">Vararg conversions</a><br><tt>int printf(char *fmt, ...);</tt></td><td class="idiomc"><tt>printf("%g", 1.0);<br>printf("%d", 1);<br>&nbsp;</tt></td><td class="idiomlua"><tt>printf("%g", 1);<br>printf("%d",<br>&nbsp;&nbsp;<b>ffi.new("int", 1)</b>)</tt></td></tr>
</table>
<h2 id="cache">To Cache or Not to Cache</h2>
<p>
It's a common Lua idiom to cache library functions in local variables
or upvalues, e.g.:
</p>
<pre class="code">
local byte, char = string.byte, string.char
local function foo(x)
return char(byte(x)+1)
end
</pre>
<p>
This replaces several hash-table lookups with a (faster) direct use of
a local or an upvalue. This is less important with LuaJIT, since the
JIT compiler optimizes hash-table lookups a lot and is even able to
hoist most of them out of the inner loops. It can't eliminate
<em>all</em> of them, though, and it saves some typing for often-used
functions. So there's still a place for this, even with LuaJIT.
</p>
<p>
The situation is a bit different with C&nbsp;function calls via the
FFI library. The JIT compiler has special logic to eliminate <em>all
of the lookup overhead</em> for functions resolved from a
<a href="ext_ffi_semantics.html#clib">C&nbsp;library namespace</a>!
Thus it's not helpful and actually counter-productive to cache
individual C&nbsp;functions like this:
</p>
<pre class="code">
local <b>funca</b>, <b>funcb</b> = ffi.C.funcb, ffi.C.funcb -- <span style="color:#c00000;">Not helpful!</span>
local function foo(x, n)
for i=1,n do <b>funcb</b>(<b>funca</b>(x, i), 1) end
end
</pre>
<p>
This turns them into indirect calls and generates bigger and slower
machine code. Instead you'll want to cache the namespace itself and
rely on the JIT compiler to eliminate the lookups:
</p>
<pre class="code">
local <b>C</b> = ffi.C -- <span style="color:#00a000;">Instead use this!</span>
local function foo(x, n)
for i=1,n do <b>C.funcb</b>(<b>C.funca</b>(x, i), 1) end
end
</pre>
<p>
This generates both shorter and faster code. So <b>don't cache
C&nbsp;functions</b>, but <b>do</b> cache namespaces! Most often the
namespace is already in a local variable at an outer scope, e.g. from
<tt>local&nbsp;lib&nbsp;=&nbsp;ffi.load(...)</tt>. Note that copying
it to a local variable in the function scope is unnecessary.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-199
View File
@@ -1,199 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>jit.* Library</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1><tt>jit.*</tt> Library</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a class="current" href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
The functions in this built-in module control the behavior of the JIT
compiler engine. Note that JIT-compilation is fully automatic &mdash;
you probably won't need to use any of the following functions unless
you have special needs.
</p>
<h3 id="jit_onoff"><tt>jit.on()<br>
jit.off()</tt></h3>
<p>
Turns the whole JIT compiler on (default) or off.
</p>
<p>
These functions are typically used with the command line options
<tt>-j on</tt> or <tt>-j off</tt>.
</p>
<h3 id="jit_flush"><tt>jit.flush()</tt></h3>
<p>
Flushes the whole cache of compiled code.
</p>
<h3 id="jit_onoff_func"><tt>jit.on(func|true [,true|false])<br>
jit.off(func|true [,true|false])<br>
jit.flush(func|true [,true|false])</tt></h3>
<p>
<tt>jit.on</tt> enables JIT compilation for a Lua function (this is
the default).
</p>
<p>
<tt>jit.off</tt> disables JIT compilation for a Lua function and
flushes any already compiled code from the code cache.
</p>
<p>
<tt>jit.flush</tt> flushes the code, but doesn't affect the
enable/disable status.
</p>
<p>
The current function, i.e. the Lua function calling this library
function, can also be specified by passing <tt>true</tt> as the first
argument.
</p>
<p>
If the second argument is <tt>true</tt>, JIT compilation is also
enabled, disabled or flushed recursively for all sub-functions of a
function. With <tt>false</tt> only the sub-functions are affected.
</p>
<p>
The <tt>jit.on</tt> and <tt>jit.off</tt> functions only set a flag
which is checked when the function is about to be compiled. They do
not trigger immediate compilation.
</p>
<p>
Typical usage is <tt>jit.off(true, true)</tt> in the main chunk
of a module to turn off JIT compilation for the whole module for
debugging purposes.
</p>
<h3 id="jit_flush_tr"><tt>jit.flush(tr)</tt></h3>
<p>
Flushes the root trace, specified by its number, and all of its side
traces from the cache. The code for the trace will be retained as long
as there are any other traces which link to it.
</p>
<h3 id="jit_status"><tt>status, ... = jit.status()</tt></h3>
<p>
Returns the current status of the JIT compiler. The first result is
either <tt>true</tt> or <tt>false</tt> if the JIT compiler is turned
on or off. The remaining results are strings for CPU-specific features
and enabled optimizations.
</p>
<h3 id="jit_version"><tt>jit.version</tt></h3>
<p>
Contains the LuaJIT version string.
</p>
<h3 id="jit_version_num"><tt>jit.version_num</tt></h3>
<p>
Contains the version number of the LuaJIT core. Version xx.yy.zz
is represented by the decimal number xxyyzz.
</p>
<h3 id="jit_os"><tt>jit.os</tt></h3>
<p>
Contains the target OS name:
"Windows", "Linux", "OSX", "BSD", "POSIX" or "Other".
</p>
<h3 id="jit_arch"><tt>jit.arch</tt></h3>
<p>
Contains the target architecture name:
"x86", "x64" or "ppcspe".
</p>
<h2 id="jit_opt"><tt>jit.opt.*</tt> &mdash; JIT compiler optimization control</h2>
<p>
This sub-module provides the backend for the <tt>-O</tt> command line
option.
</p>
<p>
You can also use it programmatically, e.g.:
</p>
<pre class="code">
jit.opt.start(2) -- same as -O2
jit.opt.start("-dce")
jit.opt.start("hotloop=10", "hotexit=2")
</pre>
<p>
Unlike in LuaJIT 1.x, the module is built-in and
<b>optimization is turned on by default!</b>
It's no longer necessary to run <tt>require("jit.opt").start()</tt>,
which was one of the ways to enable optimization.
</p>
<h2 id="jit_util"><tt>jit.util.*</tt> &mdash; JIT compiler introspection</h2>
<p>
This sub-module holds functions to introspect the bytecode, generated
traces, the IR and the generated machine code. The functionality
provided by this module is still in flux and therefore undocumented.
</p>
<p>
The debug modules <tt>-jbc</tt>, <tt>-jv</tt> and <tt>-jdump</tt> make
extensive use of these functions. Please check out their source code,
if you want to know more.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-407
View File
@@ -1,407 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Extensions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
table.exc {
line-height: 1.2;
}
tr.exchead td {
font-weight: bold;
}
td.excplatform {
width: 48%;
}
td.exccompiler {
width: 29%;
}
td.excinterop {
width: 23%;
}
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Extensions</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a class="current" href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
<a href="http://www.lua.org/manual/5.1/manual.html#5"><span class="ext">&raquo;</span>&nbsp;standard Lua
library functions</a> and the full set of
<a href="http://www.lua.org/manual/5.1/manual.html#3"><span class="ext">&raquo;</span>&nbsp;Lua/C API
functions</a>.
</p>
<p>
LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic
loader level. This means you can compile a C&nbsp;module against the
standard Lua headers and load the same shared library from either Lua
or LuaJIT.
</p>
<p>
LuaJIT extends the standard Lua VM with new functionality and adds
several extension modules. Please note this page is only about
<em>functional</em> enhancements and not about performance enhancements,
such as the optimized VM, the faster interpreter or the JIT compiler.
</p>
<h2 id="modules">Extensions Modules</h2>
<p>
LuaJIT comes with several built-in extension modules:
</p>
<h3 id="bit"><tt>bit.*</tt> &mdash; Bitwise operations</h3>
<p>
LuaJIT supports all bitwise operations as defined by
<a href="http://bitop.luajit.org"><span class="ext">&raquo;</span>&nbsp;Lua BitOp</a>:
</p>
<pre class="code">
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
</pre>
<p>
This module is a LuaJIT built-in &mdash; you don't need to download or
install Lua BitOp. The Lua BitOp site has full documentation for all
<a href="http://bitop.luajit.org/api.html"><span class="ext">&raquo;</span>&nbsp;Lua BitOp API functions</a>.
</p>
<p>
Please make sure to <tt>require</tt> the module before using any of
its functions:
</p>
<pre class="code">
local bit = require("bit")
</pre>
<p>
An already installed Lua BitOp module is ignored by LuaJIT.
This way you can use bit operations from both Lua and LuaJIT on a
shared installation.
</p>
<h3 id="ffi"><tt>ffi.*</tt> &mdash; FFI library</h3>
<p>
The <a href="ext_ffi.html">FFI library</a> allows calling external
C&nbsp;functions and the use of C&nbsp;data structures from pure Lua
code.
</p>
<h3 id="jit"><tt>jit.*</tt> &mdash; JIT compiler control</h3>
<p>
The functions in this module
<a href="ext_jit.html">control the behavior of the JIT compiler engine</a>.
</p>
<h3 id="c_api">C API extensions</h3>
<p>
LuaJIT adds some
<a href="ext_c_api.html">extra functions to the Lua/C API</a>.
</p>
<h2 id="library">Enhanced Standard Library Functions</h2>
<h3 id="xpcall"><tt>xpcall(f, err [,args...])</tt> passes arguments</h3>
<p>
Unlike the standard implementation in Lua 5.1, <tt>xpcall()</tt>
passes any arguments after the error function to the function
which is called in a protected context.
</p>
<h3 id="load"><tt>loadfile()</tt> etc. handle UTF-8 source code</h3>
<p>
Non-ASCII characters are handled transparently by the Lua source code parser.
This allows the use of UTF-8 characters in identifiers and strings.
A UTF-8 BOM is skipped at the start of the source code.
</p>
<h3 id="tostring"><tt>tostring()</tt> etc. canonicalize NaN and &plusmn;Inf</h3>
<p>
All number-to-string conversions consistently convert non-finite numbers
to the same strings on all platforms. NaN results in <tt>"nan"</tt>,
positive infinity results in <tt>"inf"</tt> and negative infinity results
in <tt>"-inf"</tt>.
</p>
<h3 id="tonumber"><tt>tonumber()</tt> etc. use builtin string to number conversion</h3>
<p>
All string-to-number conversions consistently convert integer and
floating-point inputs in decimal and hexadecimal on all platforms.
<tt>strtod()</tt> is <em>not</em> used anymore, which avoids numerous
problems with poor C library implementations. The builtin conversion
function provides full precision according to the IEEE-754 standard, it
works independently of the current locale and it supports hex floating-point
numbers (e.g. <tt>0x1.5p-3</tt>).
</p>
<h3 id="string_dump"><tt>string.dump(f [,strip])</tt> generates portable bytecode</h3>
<p>
An extra argument has been added to <tt>string.dump()</tt>. If set to
<tt>true</tt>, 'stripped' bytecode without debug information is
generated. This speeds up later bytecode loading and reduces memory
usage. See also the
<a href="running.html#opt_b"><tt>-b</tt> command line option</a>.
</p>
<p>
The generated bytecode is portable and can be loaded on any architecture
that LuaJIT supports, independent of word size or endianess. However the
bytecode compatibility versions must match. Bytecode stays compatible
for dot releases (x.y.0 &rarr; x.y.1), but may change with major or
minor releases (2.0 &rarr; 2.1) or between any beta release. Foreign
bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
</p>
<h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3>
<p>
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
<tt>math.random()</tt> and <tt>math.randomseed()</tt>. The quality of
the PRNG results is much superior compared to the standard Lua
implementation which uses the platform-specific ANSI rand().
</p>
<p>
The PRNG generates the same sequences from the same seeds on all
platforms and makes use of all bits in the seed argument.
<tt>math.random()</tt> without arguments generates 52 pseudo-random bits
for every call. The result is uniformly distributed between 0.0 and 1.0.
It's correctly scaled up and rounded for <tt>math.random(n&nbsp;[,m])</tt> to
preserve uniformity.
</p>
<h3 id="io"><tt>io.*</tt> functions handle 64&nbsp;bit file offsets</h3>
<p>
The file I/O functions in the standard <tt>io.*</tt> library handle
64&nbsp;bit file offsets. In particular this means it's possible
to open files larger than 2&nbsp;Gigabytes and to reposition or obtain
the current file position for offsets beyond 2&nbsp;GB
(<tt>fp:seek()</tt> method).
</p>
<h3 id="debug_meta"><tt>debug.*</tt> functions identify metamethods</h3>
<p>
<tt>debug.getinfo()</tt> and <tt>lua_getinfo()</tt> also return information
about invoked metamethods. The <tt>namewhat</tt> field is set to
<tt>"metamethod"</tt> and the <tt>name</tt> field has the name of
the corresponding metamethod (e.g. <tt>"__index"</tt>).
</p>
<h2 id="resumable">Fully Resumable VM</h2>
<p>
The LuaJIT VM is fully resumable. This means you can yield from a
coroutine even across contexts, where this would not possible with
the standard Lua&nbsp;5.1 VM: e.g. you can yield across <tt>pcall()</tt>
and <tt>xpcall()</tt>, across iterators and across metamethods.
</p>
<h2 id="lua52">Extensions from Lua 5.2</h2>
<p>
LuaJIT supports some language and library extensions from Lua&nbsp;5.2.
Features that are unlikely to break existing code are unconditionally
enabled:
</p>
<ul>
<li><tt>goto</tt> and <tt>::labels::</tt>.</li>
<li>Hex escapes <tt>'\x3F'</tt> and <tt>'\*'</tt> escape in strings.</li>
<li><tt>load(string|reader, chunkname [,mode [,env]])</tt>.
<tt>loadstring()</tt> is an alias.</li>
<li><tt>math.log(x [,base])</tt>.
<li><tt>string.rep(s, n [,sep])</tt>.
<li><tt>string.format()</tt>: <tt>%q</tt> reversible.
<tt>%s</tt> checks <tt>__tostring</tt>.
<tt>%a</tt> and <tt>"%A</tt> added.</li>
<li>String matching pattern <tt>%g</tt> added.</li>
<li><tt>io.read("*L")</tt>.</li>
<li><tt>io.lines()</tt> and <tt>file:lines()</tt> process
<tt>io.read()</tt> options.</li>
<li><tt>os.exit(status|true|false [,close])</tt>.</li>
<li><tt>package.searchpath(name, path [, sep [, rep]])</tt>.</li>
<li><tt>package.loadlib(name, "*")</tt>.</li>
<li><tt>debug.getinfo()</tt> returns <tt>nparams</tt> and <tt>isvararg</tt>
for option <tt>"u"</tt>.</li>
<li><tt>debug.getlocal()</tt> accepts function instead of level.</li>
<li><tt>debug.getlocal()</tt> and <tt>debug.setlocal()</tt> accept negative
indexes for varargs.</li>
<li><tt>debug.getupvalue()</tt> and <tt>debug.setupvalue()</tt> handle
C&nbsp;functions.</li>
<li><tt>debug.upvalueid()</tt> and <tt>debug.upvaluejoin()</tt>.</li>
<li>Command line option <tt>-E</tt>.</li>
<li>Command line checks <tt>__tostring</tt> for errors.</li>
</ul>
<p>
Other features are only enabled, if LuaJIT is built with
<tt>-DLUAJIT_ENABLE_LUA52COMPAT</tt>:
</p>
<ul>
<li><tt>goto</tt> is a keyword and not a valid variable name anymore.</li>
<li><tt>break</tt> can be placed anywhere. Empty statements (<tt>;;</tt>)
are allowed.</li>
<li><tt>__lt</tt>, <tt>__le</tt> are invoked for mixed types.</li>
<li><tt>__len</tt> for tables. <tt>rawlen()</tt> library function.</li>
<li><tt>pairs()</tt> and <tt>ipairs()</tt> check for <tt>__pairs</tt> and
<tt>__ipairs</tt>.</li>
<li><tt>coroutine.running()</tt> returns two results.</li>
<li><tt>table.pack()</tt> and <tt>table.unpack()</tt>
(same as <tt>unpack()</tt>).</li>
<li><tt>io.write()</tt> and <tt>file:write()</tt> return file handle
instead of <tt>true</tt>.</li>
<li><tt>os.execute()</tt> and <tt>pipe:close()</tt> return detailed
exit status.</li>
<li><tt>debug.setmetatable()</tt> returns object.</li>
<li><tt>debug.getuservalue()</tt> and <tt>debug.setuservalue()</tt>.</li>
<li>Remove <tt>math.mod()</tt>, <tt>string.gfind()</tt>.
</ul>
<p>
Note: this provides only partial compatibility with Lua 5.2 at the
language and Lua library level. LuaJIT is API+ABI-compatible with
Lua&nbsp;5.1, which prevents implementing features that would otherwise
break the Lua/C API and ABI (e.g. <tt>_ENV</tt>).
</p>
<h2 id="exceptions">C++ Exception Interoperability</h2>
<p>
LuaJIT has built-in support for interoperating with C++&nbsp;exceptions.
The available range of features depends on the target platform and
the toolchain used to compile LuaJIT:
</p>
<table class="exc">
<tr class="exchead">
<td class="excplatform">Platform</td>
<td class="exccompiler">Compiler</td>
<td class="excinterop">Interoperability</td>
</tr>
<tr class="odd separate">
<td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
<td class="exccompiler">GCC 4.3+</td>
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
</tr>
<tr class="even">
<td class="excplatform">Other platforms, DWARF2 unwinding</td>
<td class="exccompiler">GCC</td>
<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
</tr>
<tr class="odd">
<td class="excplatform">Windows/x64</td>
<td class="exccompiler">MSVC or WinSDK</td>
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
</tr>
<tr class="even">
<td class="excplatform">Windows/x86</td>
<td class="exccompiler">Any</td>
<td class="excinterop"><b style="color: #a00000;">No</b></td>
</tr>
<tr class="odd">
<td class="excplatform">Other platforms</td>
<td class="exccompiler">Other compilers</td>
<td class="excinterop"><b style="color: #a00000;">No</b></td>
</tr>
</table>
<p>
<b style="color: #00a000;">Full interoperability</b> means:
</p>
<ul>
<li>C++&nbsp;exceptions can be caught on the Lua side with <tt>pcall()</tt>,
<tt>lua_pcall()</tt> etc.</li>
<li>C++&nbsp;exceptions will be converted to the generic Lua error
<tt>"C++&nbsp;exception"</tt>, unless you use the
<a href="ext_c_api.html#mode_wrapcfunc">C&nbsp;call wrapper</a> feature.</li>
<li>It's safe to throw C++&nbsp;exceptions across non-protected Lua frames
on the C&nbsp;stack. The contents of the C++&nbsp;exception object
pass through unmodified.</li>
<li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
The corresponding Lua error message can be retrieved from the Lua stack.</li>
<li>Throwing Lua errors across C++ frames is safe. C++ destructors
will be called.</li>
</ul>
<p>
<b style="color: #c06000;">Limited interoperability</b> means:
</p>
<ul>
<li>C++&nbsp;exceptions can be caught on the Lua side with <tt>pcall()</tt>,
<tt>lua_pcall()</tt> etc.</li>
<li>C++&nbsp;exceptions will be converted to the generic Lua error
<tt>"C++&nbsp;exception"</tt>, unless you use the
<a href="ext_c_api.html#mode_wrapcfunc">C&nbsp;call wrapper</a> feature.</li>
<li>C++&nbsp;exceptions will be caught by non-protected Lua frames and
are rethrown as a generic Lua error. The C++&nbsp;exception object will
be destroyed.</li>
<li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
<li>Throwing Lua errors across C++ frames will <b>not</b> call
C++ destructors.</li>
</ul>
<p>
<b style="color: #a00000;">No interoperability</b> means:
</p>
<ul>
<li>It's <b>not</b> safe to throw C++&nbsp;exceptions across Lua frames.</li>
<li>C++&nbsp;exceptions <b>cannot</b> be caught on the Lua side.</li>
<li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
<li>Throwing Lua errors across C++ frames will <b>not</b> call
C++ destructors.</li>
<li>Additionally, on Windows/x86 with SEH-based C++&nbsp;exceptions:
it's <b>not</b> safe to throw a Lua error across any frames containing
a C++ function with any try/catch construct or using variables with
(implicit) destructors. This also applies to any functions which may be
inlined in such a function. It doesn't matter whether <tt>lua_error()</tt>
is called inside or outside of a try/catch or whether any object actually
needs to be destroyed: the SEH chain is corrupted and this will eventually
lead to the termination of the process.</li>
</ul>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-184
View File
@@ -1,184 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Frequently Asked Questions (FAQ)</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
dd { margin-left: 1.5em; }
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Frequently Asked Questions (FAQ)</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a class="current" href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<dl>
<dt>Q: Where can I learn more about LuaJIT and Lua?</dt>
<dd>
<ul style="padding: 0;">
<li>The <a href="http://luajit.org/list.html"><span class="ext">&raquo;</span>&nbsp;LuaJIT mailing list</a> focuses on topics
related to LuaJIT.</li>
<li>The <a href="http://wiki.luajit.org/"><span class="ext">&raquo;</span>&nbsp;LuaJIT wiki</a> gathers community
resources about LuaJIT.</li>
<li>News about Lua itself can be found at the
<a href="http://www.lua.org/lua-l.html"><span class="ext">&raquo;</span>&nbsp;Lua mailing list</a>.
The mailing list archives are worth checking out for older postings
about LuaJIT.</li>
<li>The <a href="http://lua.org"><span class="ext">&raquo;</span>&nbsp;main Lua.org site</a> has complete
<a href="http://www.lua.org/docs.html"><span class="ext">&raquo;</span>&nbsp;documentation</a> of the language
and links to books and papers about Lua.</li>
<li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">&raquo;</span>&nbsp;Lua Wiki</a>
has information about diverse topics.</li>
</ul>
</dl>
<dl>
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
<dd>
I'm planning to write more documentation about the internals of LuaJIT.
In the meantime, please use the following Google Scholar searches
to find relevant papers:<br>
Search for: <a href="http://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">&raquo;</span>&nbsp;Trace Compiler</a><br>
Search for: <a href="http://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">&raquo;</span>&nbsp;JIT Compiler</a><br>
Search for: <a href="http://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">&raquo;</span>&nbsp;Dynamic Language Optimizations</a><br>
Search for: <a href="http://scholar.google.com/scholar?q=SSA+Form"><span class="ext">&raquo;</span>&nbsp;SSA Form</a><br>
Search for: <a href="http://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">&raquo;</span>&nbsp;Linear Scan Register Allocation</a><br>
Here is a list of the <a href="http://article.gmane.org/gmane.comp.lang.lua.general/58908"><span class="ext">&raquo;</span>&nbsp;innovative features in LuaJIT</a>.<br>
And, you know, reading the source is of course the only way to enlightenment. :-)
</dd>
</dl>
<dl>
<dt>Q: Why do I get this error: "attempt to index global 'arg' (a nil value)"?<br>
Q: My vararg functions fail after switching to LuaJIT!</dt>
<dd>LuaJIT is compatible to the Lua 5.1 language standard. It doesn't
support the implicit <tt>arg</tt> parameter for old-style vararg
functions from Lua 5.0.<br>Please convert your code to the
<a href="http://www.lua.org/manual/5.1/manual.html#2.5.9"><span class="ext">&raquo;</span>&nbsp;Lua 5.1
vararg syntax</a>.</dd>
</dl>
<dl>
<dt>Q: Why do I get this error: "bad FPU precision"?<br>
<dt>Q: I get weird behavior after initializing Direct3D.<br>
<dt>Q: Some FPU operations crash after I load a Delphi DLL.<br>
</dt>
<dd>
DirectX/Direct3D (up to version 9) sets the x87 FPU to single-precision
mode by default. This violates the Windows ABI and interferes with the
operation of many programs &mdash; LuaJIT is affected, too. Please make
sure you always use the <tt>D3DCREATE_FPU_PRESERVE</tt> flag when
initializing Direct3D.<br>
Direct3D version 10 or higher do not show this behavior anymore.
Consider testing your application with older versions, too.<br>
Similarly, the Borland/Delphi runtime modifies the FPU control word and
enables FP exceptions. Of course this violates the Windows ABI, too.
Please check the Delphi docs for the Set8087CW method.
</dl>
<dl>
<dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
<dd>The interrupt signal handler sets a Lua debug hook. But this is
currently ignored by compiled code (this will eventually be fixed). If
your program is running in a tight loop and never falls back to the
interpreter, the debug hook never runs and can't throw the
"interrupted!" error.<br> In the meantime you have to press Ctrl-C
twice to get stop your program. That's similar to when it's stuck
running inside a C function under the Lua interpreter.</dd>
</dl>
<dl>
<dt>Q: Why doesn't my favorite power-patch for Lua apply against LuaJIT?</dt>
<dd>Because it's a completely redesigned VM and has very little code
in common with Lua anymore. Also, if the patch introduces changes to
the Lua semantics, these would need to be reflected everywhere in the
VM, from the interpreter up to all stages of the compiler.<br> Please
use only standard Lua language constructs. For many common needs you
can use source transformations or use wrapper or proxy functions.
The compiler will happily optimize away such indirections.</dd>
</dl>
<dl>
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
<dd>Because it's a compiler &mdash; it needs to generate native
machine code. This means the code generator must be ported to each
architecture. And the fast interpreter is written in assembler and
must be ported, too. This is quite an undertaking.<br>
The <a href="install.html">install documentation</a> shows the supported
architectures. Other architectures will follow based on sufficient user
demand and/or sponsoring.</dd>
</dl>
<dl>
<dt>Q: When will feature X be added? When will the next version be released?</dt>
<dd>When it's ready.<br>
C'mon, it's open source &mdash; I'm doing it on my own time and you're
getting it for free. You can either contribute a patch or sponsor
the development of certain features, if they are important to you.
</dd>
</dl>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

-613
View File
@@ -1,613 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Installation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
table.compat {
line-height: 1.2;
font-size: 80%;
}
table.compat td {
border: 1px solid #bfcfff;
height: 2.5em;
}
table.compat tr.compathead td {
font-weight: bold;
border-bottom: 2px solid #bfcfff;
}
tr.compathead td.compatos {
vertical-align: top;
}
table.compat td.compatcpu {
width: 18%;
border-right: 2px solid #bfcfff;
}
td.compatos {
width: 21%;
vertical-align: middle;
}
td.compatno {
background-color: #d0d0d0;
}
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Installation</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a class="current" href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
LuaJIT is only distributed as a source package. This page explains
how to build and install LuaJIT with different operating systems
and C&nbsp;compilers.
</p>
<p>
For the impatient (on POSIX systems):
</p>
<pre class="code">
make &amp;&amp; sudo make install
</pre>
<p>
LuaJIT currently builds out-of-the box on most systems.
Here's the compatibility matrix for the supported combinations of
operating systems, CPUs and compilers:
</p>
<table class="compat">
<tr class="compathead">
<td class="compatcpu">CPU / OS</td>
<td class="compatos"><a href="#posix">Linux</a> or<br><a href="#android">Android</a></td>
<td class="compatos"><a href="#posix">*BSD, Other</a></td>
<td class="compatos"><a href="#posix">OSX 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
<td class="compatos"><a href="#windows">Windows<br>XP/Vista/7</a></td>
</tr>
<tr class="odd separate">
<td class="compatcpu">x86 (32 bit)</td>
<td class="compatos">GCC 4.x<br>GCC 3.4</td>
<td class="compatos">GCC 4.x<br>GCC 3.4</td>
<td class="compatos">GCC 4.x<br>GCC 3.4</td>
<td class="compatos">MSVC, MSVC/EE<br>WinSDK<br>MinGW, Cygwin</td>
</tr>
<tr class="even">
<td class="compatcpu">x64 (64 bit)</td>
<td class="compatos">GCC 4.x</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos">GCC 4.x</td>
<td class="compatos">MSVC + SDK v7.0<br>WinSDK v7.0</td>
</tr>
<tr class="odd">
<td class="compatcpu"><a href="#cross2">ARMv5+<br>ARM9E+</a></td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos compatno">&nbsp;</td>
</tr>
<tr class="even">
<td class="compatcpu"><a href="#cross2">PPC</a></td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos">GCC 4.3+<br>GCC 4.1 (<a href="#ps3">PS3</a>)</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
</tr>
<tr class="odd">
<td class="compatcpu"><a href="#cross2">PPC/e500v2</a></td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos compatno">&nbsp;</td>
</tr>
<tr class="even">
<td class="compatcpu"><a href="#cross2">MIPS</a></td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos compatno">&nbsp;</td>
</tr>
</table>
<h2>Configuring LuaJIT</h2>
<p>
The standard configuration should work fine for most installations.
Usually there is no need to tweak the settings. The following files
hold all user-configurable settings:
</p>
<ul>
<li><tt>src/luaconf.h</tt> sets some configuration variables.</li>
<li><tt>Makefile</tt> has settings for <b>installing</b> LuaJIT (POSIX
only).</li>
<li><tt>src/Makefile</tt> has settings for <b>compiling</b> LuaJIT
under POSIX, MinGW or Cygwin.</li>
<li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with
MSVC or WinSDK.</li>
</ul>
<p>
Please read the instructions given in these files, before changing
any settings.
</p>
<h2 id="posix">POSIX Systems (Linux, OSX, *BSD etc.)</h2>
<h3>Prerequisites</h3>
<p>
Depending on your distribution, you may need to install a package for
GCC, the development headers and/or a complete SDK. E.g. on a current
Debian/Ubuntu, install <tt>libc6-dev</tt> with the package manager.
</p>
<p>
Download the current source package of LuaJIT (pick the .tar.gz),
if you haven't already done so. Move it to a directory of your choice,
open a terminal window and change to this directory. Now unpack the archive
and change to the newly created directory:
</p>
<pre class="code">
tar zxf LuaJIT-2.0.1.tar.gz
cd LuaJIT-2.0.1</pre>
<h3>Building LuaJIT</h3>
<p>
The supplied Makefiles try to auto-detect the settings needed for your
operating system and your compiler. They need to be run with GNU Make,
which is probably the default on your system, anyway. Simply run:
</p>
<pre class="code">
make
</pre>
<p>
This always builds a native x86, x64 or PPC binary, depending on the host OS
you're running this command on. Check the section on
<a href="#cross">cross-compilation</a> for more options.
</p>
<p>
By default, modules are only searched under the prefix <tt>/usr/local</tt>.
You can add an extra prefix to the search paths by appending the
<tt>PREFIX</tt> option, e.g.:
</p>
<pre class="code">
make PREFIX=/home/myself/lj2
</pre>
<p>
Note for OSX: if the <tt>MACOSX_DEPLOYMENT_TARGET</tt> environment
variable is not set, then it's forced to <tt>10.4</tt>.
</p>
<h3>Installing LuaJIT</h3>
<p>
The top-level Makefile installs LuaJIT by default under
<tt>/usr/local</tt>, i.e. the executable ends up in
<tt>/usr/local/bin</tt> and so on. You need root privileges
to write to this path. So, assuming sudo is installed on your system,
run the following command and enter your sudo password:
</p>
<pre class="code">
sudo make install
</pre>
<p>
Otherwise specify the directory prefix as an absolute path, e.g.:
</p>
<pre class="code">
make install PREFIX=/home/myself/lj2
</pre>
<p>
Obviously the prefixes given during build and installation need to be the same.
</p>
<h2 id="windows">Windows Systems</h2>
<h3>Prerequisites</h3>
<p>
Either install one of the open source SDKs
(<a href="http://mingw.org/"><span class="ext">&raquo;</span>&nbsp;MinGW</a> or
<a href="http://www.cygwin.com/"><span class="ext">&raquo;</span>&nbsp;Cygwin</a>), which come with a modified
GCC plus the required development headers.
</p>
<p>
Or install Microsoft's Visual C++ (MSVC). The freely downloadable
<a href="http://www.microsoft.com/Express/VC/"><span class="ext">&raquo;</span>&nbsp;Express Edition</a>
works just fine, but only contains an x86 compiler.
</p>
<p>
The freely downloadable
<a href="http://msdn.microsoft.com/en-us/windowsserver/bb980924.aspx"><span class="ext">&raquo;</span>&nbsp;Windows SDK</a>
only comes with command line tools, but this is all you need to build LuaJIT.
It contains x86 and x64 compilers.
</p>
<p>
Next, download the source package and unpack it using an archive manager
(e.g. the Windows Explorer) to a directory of your choice.
</p>
<h3>Building with MSVC</h3>
<p>
Open a "Visual Studio .NET Command Prompt", <tt>cd</tt> to the
directory where you've unpacked the sources and run these commands:
</p>
<pre class="code">
cd src
msvcbuild
</pre>
<p>
Then follow the installation instructions below.
</p>
<h3>Building with the Windows SDK</h3>
<p>
Open a "Windows SDK Command Shell" and select the x86 compiler:
</p>
<pre class="code">
setenv /release /x86
</pre>
<p>
Or select the x64 compiler:
</p>
<pre class="code">
setenv /release /x64
</pre>
<p>
Then <tt>cd</tt> to the directory where you've unpacked the sources
and run these commands:
</p>
<pre class="code">
cd src
msvcbuild
</pre>
<p>
Then follow the installation instructions below.
</p>
<h3>Building with MinGW or Cygwin</h3>
<p>
Open a command prompt window and make sure the MinGW or Cygwin programs
are in your path. Then <tt>cd</tt> to the directory where
you've unpacked the sources and run this command for MinGW:
</p>
<pre class="code">
mingw32-make
</pre>
<p>
Or this command for Cygwin:
</p>
<pre class="code">
make
</pre>
<p>
Then follow the installation instructions below.
</p>
<h3>Installing LuaJIT</h3>
<p>
Copy <tt>luajit.exe</tt> and <tt>lua51.dll</tt> (built in the <tt>src</tt>
directory) to a newly created directory (any location is ok).
Add <tt>lua</tt> and <tt>lua\jit</tt> directories below it and copy
all Lua files from the <tt>src\jit</tt> directory of the distribution
to the latter directory.
</p>
<p>
There are no hardcoded
absolute path names &mdash; all modules are loaded relative to the
directory where <tt>luajit.exe</tt> is installed
(see <tt>src/luaconf.h</tt>).
</p>
<h2 id="cross">Cross-compiling LuaJIT</h2>
<p>
The GNU Makefile-based build system allows cross-compiling on any host
for any supported target, as long as both architectures have the same
pointer size. If you want to cross-compile to any 32 bit target on an
x64 OS, you need to install the multilib development package (e.g.
<tt>libc6-dev-i386</tt> on Debian/Ubuntu) and build a 32 bit host part
(<tt>HOST_CC="gcc -m32"</tt>).
</p>
<p>
You need to specify <tt>TARGET_SYS</tt> whenever the host OS and the
target OS differ, or you'll get assembler or linker errors. E.g. if
you're compiling on a Windows or OSX host for embedded Linux or Android,
you need to add <tt>TARGET_SYS=Linux</tt> to the examples below. For a
minimal target OS, you may need to disable the built-in allocator in
<tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>. The examples
below only show some popular targets &mdash; please check the comments
in <tt>src/Makefile</tt> for more details.
</p>
<pre class="code">
# Cross-compile to a 32 bit binary on a multilib x64 OS
make CC="gcc -m32"
# Cross-compile on Debian/Ubuntu for Windows (mingw32 package)
make HOST_CC="gcc -m32" CROSS=i586-mingw32msvc- TARGET_SYS=Windows
</pre>
<p id="cross2">
The <tt>CROSS</tt> prefix allows specifying a standard GNU cross-compile
toolchain (Binutils, GCC and a matching libc). The prefix may vary
depending on the <tt>--target</tt> the toolchain was built for (note the
<tt>CROSS</tt> prefix has a trailing <tt>"-"</tt>). The examples below
use the canonical toolchain triplets for Linux.
</p>
<p>
Since there's often no easy way to detect CPU features at runtime, it's
important to compile with the proper CPU or architecture settings. You
can specify these when building the toolchain yourself. Or add
<tt>-mcpu=...</tt> or <tt>-march=...</tt> to <tt>TARGET_CFLAGS</tt>. For
ARM it's important to have the correct <tt>-mfloat-abi=...</tt> setting,
too. Otherwise LuaJIT may not run at the full performance of your target
CPU.
</p>
<pre class="code">
# ARM soft-float
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
TARGET_CFLAGS="-mfloat-abi=soft"
# ARM soft-float ABI with VFP (example for Cortex-A8)
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
TARGET_CFLAGS="-mcpu=cortex-a8 -mfloat-abi=softfp"
# ARM hard-float ABI with VFP (armhf, requires recent toolchain)
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabihf-
# PPC
make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
# PPC/e500v2 (fast interpreter only)
make HOST_CC="gcc -m32" CROSS=powerpc-e500v2-linux-gnuspe-
# MIPS big-endian
make HOST_CC="gcc -m32" CROSS=mips-linux-
# MIPS little-endian
make HOST_CC="gcc -m32" CROSS=mipsel-linux-
</pre>
<p>
You can cross-compile for <b id="android">Android</b> using the <a href="http://developer.android.com/sdk/ndk/index.html"><span class="ext">&raquo;</span>&nbsp;Android NDK</a>.
The environment variables need to match the install locations and the
desired target platform. E.g. Android&nbsp;4.0 corresponds to ABI level&nbsp;14.
For details check the folder <tt>docs</tt> in the NDK directory.
</p>
<p>
Only a few common variations for the different CPUs, ABIs and platforms
are listed. Please use your own judgement for which combination you want
to build/deploy or which lowest common denominator you want to pick:
</p>
<pre class="code">
# Android/ARM, armeabi (ARMv5TE soft-float), Android 2.2+ (Froyo)
NDK=/opt/android/ndk
NDKABI=8
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.6
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
NDK=/opt/android/ndk
NDKABI=14
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.6
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8"
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF $NDKARCH"
# Android/MIPS, mips (MIPS32R1 hard-float), Android 4.0+ (ICS)
NDK=/opt/android/ndk
NDKABI=14
NDKVER=$NDK/toolchains/mipsel-linux-android-4.6
NDKP=$NDKVER/prebuilt/linux-x86/bin/mipsel-linux-android-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-mips"
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
# Android/x86, x86 (i686 SSE3), Android 4.0+ (ICS)
NDK=/opt/android/ndk
NDKABI=14
NDKVER=$NDK/toolchains/x86-4.6
NDKP=$NDKVER/prebuilt/linux-x86/bin/i686-linux-android-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-x86"
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
</pre>
<p>
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="http://developer.apple.com/devcenter/ios/index.action"><span class="ext">&raquo;</span>&nbsp;iOS SDK</a>.
The environment variables need to match the iOS SDK version:
</p>
<p style="font-size: 8pt;">
Note: <b>the JIT compiler is disabled for iOS</b>, because regular iOS Apps
are not allowed to generate code at runtime. You'll only get the performance
of the LuaJIT interpreter on iOS. This is still faster than plain Lua, but
much slower than the JIT compiler. Please complain to Apple, not me.
Or use Android. :-p
</p>
<pre class="code">
IXCODE=`xcode-select -print-path`
ISDK=$IXCODE/Platforms/iPhoneOS.platform/Developer
ISDKVER=iPhoneOS6.0.sdk
ISDKP=$ISDK/usr/bin/
ISDKF="-arch armv7 -isysroot $ISDK/SDKs/$ISDKVER"
make HOST_CC="gcc -m32 -arch i386" CROSS=$ISDKP TARGET_FLAGS="$ISDKF" \
TARGET_SYS=iOS
</pre>
<p>
You can cross-compile for <b id="ps3">PS3</b> using the PS3&nbsp;SDK from
a Linux host or a Windows host (requires 32 bit MinGW (GCC) on the host,
too). Due to restrictions on consoles, the JIT compiler is disabled and
only the fast interpreter is built:
</p>
<pre class="code">
make HOST_CC="gcc -m32" CROSS=ppu-lv2-
</pre>
<p>
You can cross-compile for <b id="xbox360">Xbox 360</b> using the
Xbox&nbsp;360 SDK (MSVC + XEDK). Due to restrictions on consoles, the
JIT compiler is disabled and only the fast interpreter is built.
</p>
<p>
Open a "Visual Studio .NET Command Prompt" (32&nbsp;bit host compiler),
<tt>cd</tt> to the directory where you've unpacked the sources and run
the following commands. This builds a static library <tt>luajit20.lib</tt>,
which can be linked against your game, just like the Lua library.
</p>
<pre class="code">
cd src
xedkbuild
</pre>
<h2 id="embed">Embedding LuaJIT</h2>
<p>
LuaJIT is API-compatible with Lua 5.1. If you've already embedded Lua
into your application, you probably don't need to do anything to switch
to LuaJIT, except link with a different library:
</p>
<ul>
<li>It's strongly suggested to build LuaJIT separately using the supplied
build system. Please do <em>not</em> attempt to integrate the individual
source files into your build tree. You'll most likely get the internal build
dependencies wrong or mess up the compiler flags. Treat LuaJIT like any
other external library and link your application with either the dynamic
or static library, depending on your needs.</li>
<li>If you want to load C modules compiled for plain Lua
with <tt>require()</tt>, you need to make sure the public symbols
(e.g. <tt>lua_pushnumber</tt>) are exported, too:
<ul><li>On POSIX systems you can either link to the shared library
or link the static library into your application. In the latter case
you'll need to export all public symbols from your main executable
(e.g. <tt>-Wl,-E</tt> on Linux) and add the external dependencies
(e.g. <tt>-lm -ldl</tt> on Linux).</li>
<li>Since Windows symbols are bound to a specific DLL name, you need to
link to the <tt>lua51.dll</tt> created by the LuaJIT build (do not rename
the DLL). You may link LuaJIT statically on Windows only if you don't
intend to load Lua/C modules at runtime.
</li></ul>
</li>
<li>
If you're building a 64 bit application on OSX which links directly or
indirectly against LuaJIT, you need to link your main executable
with these flags:
<pre class="code">
-pagezero_size 10000 -image_base 100000000
</pre>
Also, it's recommended to <tt>rebase</tt> all (self-compiled) shared libraries
which are loaded at runtime on OSX/x64 (e.g. C extension modules for Lua).
See: <tt>man rebase</tt>
</li>
</ul>
<p>Additional hints for initializing LuaJIT using the C API functions:</p>
<ul>
<li>Here's a
<a href="http://lua-users.org/wiki/SimpleLuaApiExample"><span class="ext">&raquo;</span>&nbsp;simple example</a>
for embedding Lua or LuaJIT into your application.</li>
<li>Make sure you use <tt>luaL_newstate</tt>. Avoid using
<tt>lua_newstate</tt>, since this uses the (slower) default memory
allocator from your system (no support for this on x64).</li>
<li>Make sure you use <tt>luaL_openlibs</tt> and not the old Lua 5.0 style
of calling <tt>luaopen_base</tt> etc. directly.</li>
<li>To change or extend the list of standard libraries to load, copy
<tt>src/lib_init.c</tt> to your project and modify it accordingly.
Make sure the <tt>jit</tt> library is loaded or the JIT compiler
will not be activated.</li>
<li>The <tt>bit.*</tt> module for bitwise operations
is already built-in. There's no need to statically link
<a href="http://bitop.luajit.org/"><span class="ext">&raquo;</span>&nbsp;Lua BitOp</a> to your application.</li>
</ul>
<h2 id="distro">Hints for Distribution Maintainers</h2>
<p>
The LuaJIT build system has extra provisions for the needs of most
POSIX-based distributions. If you're a package maintainer for
a distribution, <em>please</em> make use of these features and
avoid patching, subverting, autotoolizing or messing up the build system
in unspeakable ways.
</p>
<p>
There should be absolutely no need to patch <tt>luaconf.h</tt> or any
of the Makefiles. And please do not hand-pick files for your packages &mdash;
simply use whatever <tt>make install</tt> creates. There's a reason
for all of the files <em>and</em> directories it creates.
</p>
<p>
The build system uses GNU make and auto-detects most settings based on
the host you're building it on. This should work fine for native builds,
even when sandboxed. You may need to pass some of the following flags to
<em>both</em> the <tt>make</tt> and the <tt>make install</tt> command lines
for a regular distribution build:
</p>
<ul>
<li><tt>PREFIX</tt> overrides the installation path and should usually
be set to <tt>/usr</tt>. Setting this also changes the module paths and
the <tt>-rpath</tt> of the shared library.</li>
<li><tt>DESTDIR</tt> is an absolute path which allows you to install
to a shadow tree instead of the root tree of the build system.</li>
<li>Have a look at the top-level <tt>Makefile</tt> and <tt>src/Makefile</tt>
for additional variables to tweak. The following variables <em>may</em> be
overridden, but it's <em>not</em> recommended, except for special needs
like cross-builds:
<tt>BUILDMODE, CC, HOST_CC, STATIC_CC, DYNAMIC_CC, CFLAGS, HOST_CFLAGS,
TARGET_CFLAGS, LDFLAGS, HOST_LDFLAGS, TARGET_LDFLAGS, TARGET_SHLDFLAGS,
TARGET_FLAGS, LIBS, HOST_LIBS, TARGET_LIBS, CROSS, HOST_SYS, TARGET_SYS
</tt></li>
</ul>
<p>
The build system has a special target for an amalgamated build, i.e.
<tt>make amalg</tt>. This compiles the LuaJIT core as one huge C file
and allows GCC to generate faster and shorter code. Alas, this requires
lots of memory during the build. This may be a problem for some users,
that's why it's not enabled by default. But it shouldn't be a problem for
most build farms. It's recommended that binary distributions use this
target for their LuaJIT builds.
</p>
<p>
The tl;dr version of the above:
</p>
<pre class="code">
make amalg PREFIX=/usr && \
make install PREFIX=/usr DESTDIR=/tmp/buildroot
</pre>
<p>
Finally, if you encounter any difficulties, please
<a href="contact.html">contact me</a> first, instead of releasing a broken
package onto unsuspecting users. Because they'll usually gonna complain
to me (the upstream) and not you (the package maintainer), anyway.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-228
View File
@@ -1,228 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>LuaJIT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<meta name="description" content="LuaJIT is a Just-In-Time (JIT) compiler for the Lua language.">
<style type="text/css">
table.feature {
width: inherit;
line-height: 1.2;
margin: 0;
}
table.feature td {
width: 80px;
height: 40px;
vertical-align: middle;
text-align: center;
font-weight: bold;
border: 4px solid #e6ecff;
border-radius: 12px;
}
table.os td {
background: #7080d0;
background-image: linear-gradient(#4060c0 10%, #b0b0ff 95%);
background-image: -moz-linear-gradient(#4060c0 10%, #b0b0ff 95%);
background-image: -webkit-linear-gradient(#4060c0 10%, #b0b0ff 95%);
background-image: -o-linear-gradient(#4060c0 10%, #b0b0ff 95%);
background-image: -ms-linear-gradient(#4060c0 10%, #b0b0ff 95%);
}
table.os1 td {
color: #ffff80;
}
table.os2 td {
color: #ffa040;
}
table.compiler td {
color: #2080ff;
background: #62bf41;
background-image: linear-gradient(#62bf41 10%, #b0ffb0 95%);
background-image: -moz-linear-gradient(#62bf41 10%, #b0ffb0 95%);
background-image: -webkit-linear-gradient(#62bf41 10%, #b0ffb0 95%);
background-image: -o-linear-gradient(#62bf41 10%, #b0ffb0 95%);
background-image: -ms-linear-gradient(#62bf41 10%, #b0ffb0 95%);
}
table.cpu td {
color: #ffff00;
background: #cf7251;
background-image: linear-gradient(#bf6241 10%, #ffb0b0 95%);
background-image: -moz-linear-gradient(#bf6241 10%, #ffb0b0 95%);
background-image: -webkit-linear-gradient(#bf6241 10%, #ffb0b0 95%);
background-image: -o-linear-gradient(#bf6241 10%, #ffb0b0 95%);
background-image: -ms-linear-gradient(#bf6241 10%, #ffb0b0 95%);
}
table.fcompat td {
color: #2060e0;
background: #61cfcf;
background-image: linear-gradient(#41bfbf 10%, #b0ffff 95%);
background-image: -moz-linear-gradient(#41bfbf 10%, #b0ffff 95%);
background-image: -webkit-linear-gradient(#41bfbf 10%, #b0ffff 95%);
background-image: -o-linear-gradient(#41bfbf 10%, #b0ffff 95%);
background-image: -ms-linear-gradient(#41bfbf 10%, #b0ffff 95%);
}
table.stats td {
color: #ffffff;
background: #a0a0a0;
background-image: linear-gradient(#808080 10%, #d0d0d0 95%);
background-image: -moz-linear-gradient(#808080 10%, #d0d0d0 95%);
background-image: -webkit-linear-gradient(#808080 10%, #d0d0d0 95%);
background-image: -o-linear-gradient(#808080 10%, #d0d0d0 95%);
background-image: -ms-linear-gradient(#808080 10%, #d0d0d0 95%);
}
table.stats td.speed {
color: #ff4020;
}
table.stats td.kb {
color: #ffff80;
background: #808080;
background-image: linear-gradient(#606060 10%, #c0c0c0 95%);
background-image: -moz-linear-gradient(#606060 10%, #c0c0c0 95%);
background-image: -webkit-linear-gradient(#606060 10%, #c0c0c0 95%);
background-image: -o-linear-gradient(#606060 10%, #c0c0c0 95%);
background-image: -ms-linear-gradient(#606060 10%, #c0c0c0 95%);
}
table.feature small {
font-size: 50%;
}
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>LuaJIT</h1>
</div>
<div id="nav">
<ul><li>
<a class="current" href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
LuaJIT is a <b>Just-In-Time Compiler</b> (JIT) for the
<a href="http://www.lua.org/"><span class="ext">&raquo;</span>&nbsp;Lua</a> programming language.
Lua is a powerful, dynamic and light-weight programming language.
It may be embedded or used as a general-purpose, stand-alone language.
</p>
<p>
LuaJIT is Copyright &copy; 2005-2013 Mike Pall, released under the
<a href="http://www.opensource.org/licenses/mit-license.php"><span class="ext">&raquo;</span>&nbsp;MIT open source license</a>.
</p>
<p>
</p>
<h2>Compatibility</h2>
<table class="feature os os1">
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr>
</table>
<table class="feature os os2">
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td><td>PS3</td><td>Xbox 360</td></tr>
</table>
<table class="feature compiler">
<tr><td>GCC</td><td>CLANG<br>LLVM</td><td>MSVC</td></tr>
</table>
<table class="feature cpu">
<tr><td>x86</td><td>x64</td><td>ARM</td><td>PPC</td><td>e500</td><td>MIPS</td></tr>
</table>
<table class="feature fcompat">
<tr><td>Lua&nbsp;5.1<br>API+ABI</td><td>+&nbsp;JIT</td><td>+&nbsp;BitOp</td><td>+&nbsp;FFI</td><td>Drop-in<br>DLL/.so</td></tr>
</table>
<h2>Overview</h2>
<table class="feature stats">
<tr>
<td class="speed">3x<br>-&nbsp;&nbsp;100x</td>
<td class="kb">115&nbsp;<small>KB</small><br>VM</td>
<td class="kb">90&nbsp;<small>KB</small><br>JIT</td>
<td class="kloc">63&nbsp;<small>KLOC</small><br>C</td>
<td class="kloc">24&nbsp;<small>KLOC</small><br>ASM</td>
<td class="kloc">11&nbsp;<small>KLOC</small><br>Lua</td>
</tr>
</table>
<p style="margin-top: 1em;">
LuaJIT has been successfully used as a <b>scripting middleware</b> in
games, appliances, network and graphics apps, numerical simulations,
trading platforms and many other specialty applications. It scales from
embedded devices, smartphones, desktops up to server farms. It combines
high flexibility with <a href="http://luajit.org/performance.html"><span class="ext">&raquo;</span>&nbsp;high performance</a>
and an unmatched <b>low memory footprint</b>.
</p>
<p>
LuaJIT has been in continuous development since 2005. It's widely
considered to be <b>one of the fastest dynamic language
implementations</b>. It has outperformed other dynamic languages on many
cross-language benchmarks since its first release &mdash; often by a
substantial margin.
</p>
<p>
For <b>LuaJIT 2.0</b>, the whole VM has been rewritten from the ground up
and relentlessly optimized for performance. It combines a <b>high-speed
interpreter</b>, written in assembler, with a <b>state-of-the-art JIT
compiler</b>.
</p>
<p>
An innovative <b>trace compiler</b> is integrated with advanced,
SSA-based optimizations and highly tuned code generation backends.
A substantial reduction of the overhead associated with dynamic languages
allows it to break into the performance range traditionally reserved for
offline, static language compilers.
</p>
<h2>More ...</h2>
<p>
Please select a sub-topic in the navigation bar to learn more about LuaJIT.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-306
View File
@@ -1,306 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Running LuaJIT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
table.opt {
line-height: 1.2;
}
tr.opthead td {
font-weight: bold;
}
td.flag_name {
width: 4em;
}
td.flag_level {
width: 2em;
text-align: center;
}
td.param_name {
width: 6em;
}
td.param_default {
width: 4em;
text-align: right;
}
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Running LuaJIT</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a class="current" href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
LuaJIT has only a single stand-alone executable, called <tt>luajit</tt> on
POSIX systems or <tt>luajit.exe</tt> on Windows. It can be used to run simple
Lua statements or whole Lua applications from the command line. It has an
interactive mode, too.
</p>
<h2 id="options">Command Line Options</h2>
<p>
The <tt>luajit</tt> stand-alone executable is just a slightly modified
version of the regular <tt>lua</tt> stand-alone executable.
It supports the same basic options, too. <tt>luajit&nbsp;-h</tt>
prints a short list of the available options. Please have a look at the
<a href="http://www.lua.org/manual/5.1/manual.html#6"><span class="ext">&raquo;</span>&nbsp;Lua manual</a>
for details.
</p>
<p>
LuaJIT has some additional options:
</p>
<h3 id="opt_b"><tt>-b[options] input output</tt></h3>
<p>
This option saves or lists bytecode. The following additional options
are accepted:
</p>
<ul>
<li><tt>-l</tt> &mdash; Only list bytecode.</li>
<li><tt>-s</tt> &mdash; Strip debug info (this is the default).</li>
<li><tt>-g</tt> &mdash; Keep debug info.</li>
<li><tt>-n name</tt> &mdash; Set module name (default: auto-detect from input name)</li>
<li><tt>-t type</tt> &mdash; Set output file type (default: auto-detect from output name).</li>
<li><tt>-a arch</tt> &mdash; Override architecture for object files (default: native).</li>
<li><tt>-o os</tt> &mdash; Override OS for object files (default: native).</li>
<li><tt>-e chunk</tt> &mdash; Use chunk string as input.</li>
<li><tt>-</tt> (a single minus sign) &mdash; Use stdin as input and/or stdout as output.</li>
</ul>
<p>
The output file type is auto-detected from the extension of the output
file name:
</p>
<ul>
<li><tt>c</tt> &mdash; C source file, exported bytecode data.</li>
<li><tt>h</tt> &mdash; C header file, static bytecode data.</li>
<li><tt>obj</tt> or <tt>o</tt> &mdash; Object file, exported bytecode data
(OS- and architecture-specific).</li>
<li><tt>raw</tt> or any other extension &mdash; Raw bytecode file (portable).
</ul>
<p>
Notes:
</p>
<ul>
<li>See also <a href="extensions.html#string_dump">string.dump()</a>
for information on bytecode portability and compatibility.</li>
<li>A file in raw bytecode format is auto-detected and can be loaded like
any Lua source file. E.g. directly from the command line or with
<tt>loadfile()</tt>, <tt>dofile()</tt> etc.</li>
<li>To statically embed the bytecode of a module in your application,
generate an object file and just link it with your application.</li>
<li>On most ELF-based systems (e.g. Linux) you need to explicitly export the
global symbols when linking your application, e.g. with: <tt>-Wl,-E</tt></li>
<li><tt>require()</tt> tries to load embedded bytecode data from exported
symbols (in <tt>*.exe</tt> or <tt>lua51.dll</tt> on Windows) and from
shared libraries in <tt>package.cpath</tt>.</li>
</ul>
<p>
Typical usage examples:
</p>
<pre class="code">
luajit -b test.lua test.out # Save bytecode to test.out
luajit -bg test.lua test.out # Keep debug info
luajit -be "print('hello world')" test.out # Save cmdline script
luajit -bl test.lua # List to stdout
luajit -bl test.lua test.txt # List to test.txt
luajit -ble "print('hello world')" # List cmdline script
luajit -b test.lua test.obj # Generate object file
# Link test.obj with your application and load it with require("test")
</pre>
<h3 id="opt_j"><tt>-j cmd[=arg[,arg...]]</tt></h3>
<p>
This option performs a LuaJIT control command or activates one of the
loadable extension modules. The command is first looked up in the
<tt>jit.*</tt> library. If no matching function is found, a module
named <tt>jit.&lt;cmd&gt;</tt> is loaded and the <tt>start()</tt>
function of the module is called with the specified arguments (if
any). The space between <tt>-j</tt> and <tt>cmd</tt> is optional.
</p>
<p>
Here are the available LuaJIT control commands:
</p>
<ul>
<li id="j_on"><tt>-jon</tt> &mdash; Turns the JIT compiler on (default).</li>
<li id="j_off"><tt>-joff</tt> &mdash; Turns the JIT compiler off (only use the interpreter).</li>
<li id="j_flush"><tt>-jflush</tt> &mdash; Flushes the whole cache of compiled code.</li>
<li id="j_v"><tt>-jv</tt> &mdash; Shows verbose information about the progress of the JIT compiler.</li>
<li id="j_dump"><tt>-jdump</tt> &mdash; Dumps the code and structures used in various compiler stages.</li>
</ul>
<p>
The <tt>-jv</tt> and <tt>-jdump</tt> commands are extension modules
written in Lua. They are mainly used for debugging the JIT compiler
itself. For a description of their options and output format, please
read the comment block at the start of their source.
They can be found in the <tt>lib</tt> directory of the source
distribution or installed under the <tt>jit</tt> directory. By default
this is <tt>/usr/local/share/luajit-2.0.1/jit</tt> on POSIX
systems.
</p>
<h3 id="opt_O"><tt>-O[level]</tt><br>
<tt>-O[+]flag</tt>&nbsp;&nbsp;&nbsp;<tt>-O-flag</tt><br>
<tt>-Oparam=value</tt></h3>
<p>
This options allows fine-tuned control of the optimizations used by
the JIT compiler. This is mainly intended for debugging LuaJIT itself.
Please note that the JIT compiler is extremely fast (we are talking
about the microsecond to millisecond range). Disabling optimizations
doesn't have any visible impact on its overhead, but usually generates
code that runs slower.
</p>
<p>
The first form sets an optimization level &mdash; this enables a
specific mix of optimization flags. <tt>-O0</tt> turns off all
optimizations and higher numbers enable more optimizations. Omitting
the level (i.e. just <tt>-O</tt>) sets the default optimization level,
which is <tt>-O3</tt> in the current version.
</p>
<p>
The second form adds or removes individual optimization flags.
The third form sets a parameter for the VM or the JIT compiler
to a specific value.
</p>
<p>
You can either use this option multiple times (like <tt>-Ocse
-O-dce -Ohotloop=10</tt>) or separate several settings with a comma
(like <tt>-O+cse,-dce,hotloop=10</tt>). The settings are applied from
left to right and later settings override earlier ones. You can freely
mix the three forms, but note that setting an optimization level
overrides all earlier flags.
</p>
<p>
Here are the available flags and at what optimization levels they
are enabled:
</p>
<table class="opt">
<tr class="opthead">
<td class="flag_name">Flag</td>
<td class="flag_level">-O1</td>
<td class="flag_level">-O2</td>
<td class="flag_level">-O3</td>
<td class="flag_desc">&nbsp;</td>
</tr>
<tr class="odd separate">
<td class="flag_name">fold</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_desc">Constant Folding, Simplifications and Reassociation</td></tr>
<tr class="even">
<td class="flag_name">cse</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_desc">Common-Subexpression Elimination</td></tr>
<tr class="odd">
<td class="flag_name">dce</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_desc">Dead-Code Elimination</td></tr>
<tr class="even">
<td class="flag_name">narrow</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_desc">Narrowing of numbers to integers</td></tr>
<tr class="odd">
<td class="flag_name">loop</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_level">&bull;</td><td class="flag_desc">Loop Optimizations (code hoisting)</td></tr>
<tr class="even">
<td class="flag_name">fwd</td><td class="flag_level">&nbsp;</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_desc">Load Forwarding (L2L) and Store Forwarding (S2L)</td></tr>
<tr class="odd">
<td class="flag_name">dse</td><td class="flag_level">&nbsp;</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_desc">Dead-Store Elimination</td></tr>
<tr class="even">
<td class="flag_name">abc</td><td class="flag_level">&nbsp;</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_desc">Array Bounds Check Elimination</td></tr>
<tr class="odd">
<td class="flag_name">sink</td><td class="flag_level">&nbsp;</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_desc">Allocation/Store Sinking</td></tr>
<tr class="even">
<td class="flag_name">fuse</td><td class="flag_level">&nbsp;</td><td class="flag_level">&nbsp;</td><td class="flag_level">&bull;</td><td class="flag_desc">Fusion of operands into instructions</td></tr>
</table>
<p>
Here are the parameters and their default settings:
</p>
<table class="opt">
<tr class="opthead">
<td class="param_name">Parameter</td>
<td class="param_default">Default</td>
<td class="param_desc">&nbsp;</td>
</tr>
<tr class="odd separate">
<td class="param_name">maxtrace</td><td class="param_default">1000</td><td class="param_desc">Max. number of traces in the cache</td></tr>
<tr class="even">
<td class="param_name">maxrecord</td><td class="param_default">4000</td><td class="param_desc">Max. number of recorded IR instructions</td></tr>
<tr class="odd">
<td class="param_name">maxirconst</td><td class="param_default">500</td><td class="param_desc">Max. number of IR constants of a trace</td></tr>
<tr class="even">
<td class="param_name">maxside</td><td class="param_default">100</td><td class="param_desc">Max. number of side traces of a root trace</td></tr>
<tr class="odd">
<td class="param_name">maxsnap</td><td class="param_default">500</td><td class="param_desc">Max. number of snapshots for a trace</td></tr>
<tr class="even separate">
<td class="param_name">hotloop</td><td class="param_default">56</td><td class="param_desc">Number of iterations to detect a hot loop or hot call</td></tr>
<tr class="odd">
<td class="param_name">hotexit</td><td class="param_default">10</td><td class="param_desc">Number of taken exits to start a side trace</td></tr>
<tr class="even">
<td class="param_name">tryside</td><td class="param_default">4</td><td class="param_desc">Number of attempts to compile a side trace</td></tr>
<tr class="odd separate">
<td class="param_name">instunroll</td><td class="param_default">4</td><td class="param_desc">Max. unroll factor for instable loops</td></tr>
<tr class="even">
<td class="param_name">loopunroll</td><td class="param_default">15</td><td class="param_desc">Max. unroll factor for loop ops in side traces</td></tr>
<tr class="odd">
<td class="param_name">callunroll</td><td class="param_default">3</td><td class="param_desc">Max. unroll factor for pseudo-recursive calls</td></tr>
<tr class="even">
<td class="param_name">recunroll</td><td class="param_default">2</td><td class="param_desc">Min. unroll factor for true recursion</td></tr>
<tr class="odd separate">
<td class="param_name">sizemcode</td><td class="param_default">32</td><td class="param_desc">Size of each machine code area in KBytes (Windows: 64K)</td></tr>
<tr class="even">
<td class="param_name">maxmcode</td><td class="param_default">512</td><td class="param_desc">Max. total size of all machine code areas in KBytes</td></tr>
</table>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-125
View File
@@ -1,125 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Status &amp; Roadmap</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
ul li { padding-bottom: 0.3em; }
</style>
</head>
<body>
<div id="site">
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>Status &amp; Roadmap</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li></ul>
</li><li>
<a class="current" href="status.html">Status</a>
<ul><li>
<a href="changes.html">Changes</a>
</li></ul>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
<span style="color: #0000c0;">LuaJIT&nbsp;2.0</span> is the current
<span style="color: #0000c0;">stable branch</span>. This branch is in
feature-freeze &mdash; new features will only be added to LuaJIT&nbsp;2.1.
</p>
<h2>Current Status</h2>
<p>
LuaJIT ought to run all Lua&nbsp;5.1-compatible source code just fine.
It's considered a serious bug if the VM crashes or produces unexpected
results &mdash; please report this.
</p>
<p>
Known incompatibilities and issues in LuaJIT&nbsp;2.0:
</p>
<ul>
<li>
There are some differences in <b>implementation-defined</b> behavior.
These either have a good reason, are arbitrary design choices
or are due to quirks in the VM. The latter cases may get fixed if a
demonstrable need is shown.
</li>
<li>
The Lua <b>debug API</b> is missing a couple of features (return
hooks for non-Lua functions) and shows slightly different behavior
in LuaJIT (no per-coroutine hooks, no tail call counting).
</li>
<li>
Some checks are missing in the JIT-compiled code for obscure situations
with <b>open upvalues aliasing</b> one of the SSA slots later on (or
vice versa). Bonus points, if you can find a real world test case for
this.
</li>
<li>
Currently some <b>out-of-memory</b> errors from <b>on-trace code</b> are not
handled correctly. The error may fall through an on-trace
<tt>pcall</tt> or it may be passed on to the function set with
<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
garbage collector.
</li>
</ul>
<h2>Roadmap</h2>
<p>
Please refer to the
<a href="http://www.freelists.org/post/luajit/LuaJIT-Roadmap-20122013"><span class="ext">&raquo;</span>&nbsp;LuaJIT Roadmap 2012/2013</a> and an
<a href="http://www.freelists.org/post/luajit/LuaJIT-Roadmap-20122013-UPDATE"><span class="ext">&raquo;</span>&nbsp;update on release planning</a> for details.
</p>
<p>
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2013 Mike Pall
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
-455
View File
@@ -1,455 +0,0 @@
/*
** DynASM ARM encoding engine.
** Copyright (C) 2005-2013 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "arm"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC,
DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
static int dasm_imm12(unsigned int n)
{
int i;
for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30))
if (n <= 255) return (int)(n + (i << 8));
return -1;
}
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
case DASM_IMM16:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
if ((ins & 0x8000))
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMMV8:
CK((n & 3) == 0, RANGE_I);
n >>= 2;
case DASM_IMML8:
case DASM_IMML12:
CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
(((-n)>>((ins>>5)&31)) == 0), RANGE_I);
b[pos++] = n;
break;
case DASM_IMM12:
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM12: case DASM_IMM16:
case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
patchrel:
if ((ins & 0x800) == 0) {
CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
cp[-1] |= ((n >> 2) & 0x00ffffff);
} else if ((ins & 0x1000)) {
CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
goto patchimml8;
} else if ((ins & 0x2000) == 0) {
CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
goto patchimml;
} else {
CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL);
n >>= 2;
goto patchimml;
}
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMM12:
cp[-1] |= dasm_imm12((unsigned int)n);
break;
case DASM_IMM16:
cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
break;
case DASM_IMML8: patchimml8:
cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
((-n & 0x0f) | ((-n & 0xf0) << 4));
break;
case DASM_IMML12: case DASM_IMMV8: patchimml:
cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif
File diff suppressed because it is too large Load Diff
-415
View File
@@ -1,415 +0,0 @@
/*
** DynASM MIPS encoding engine.
** Copyright (C) 2005-2013 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "mips"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
#endif
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if (ins & 0x8000)
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n);
if (ins & 2048)
n = n - (int)((char *)cp - base);
else
n = (n + (int)base) & 0x0fffffff;
patchrel:
CK((n & 3) == 0 &&
((n + ((ins & 2048) ? 0x00020000 : 0)) >>
((ins & 2048) ? 18 : 28)) == 0, RANGE_REL);
cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff));
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif
-953
View File
@@ -1,953 +0,0 @@
------------------------------------------------------------------------------
-- DynASM MIPS module.
--
-- Copyright (C) 2005-2013 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- Module information:
local _info = {
arch = "mips",
description = "DynASM MIPS module",
version = "1.3.0",
vernum = 10300,
release = "2012-01-23",
author = "Mike Pall",
license = "MIT",
}
-- Exported glue functions for the arch-specific module.
local _M = { _info = _info }
-- Cache library functions.
local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
local assert, setmetatable = assert, setmetatable
local _s = string
local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
local match, gmatch = _s.match, _s.gmatch
local concat, sort = table.concat, table.sort
local bit = bit or require("bit")
local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex
-- Inherited tables and callbacks.
local g_opt, g_arch
local wline, werror, wfatal, wwarn
-- Action name list.
-- CHECK: Keep this in sync with the C code!
local action_names = {
"STOP", "SECTION", "ESC", "REL_EXT",
"ALIGN", "REL_LG", "LABEL_LG",
"REL_PC", "LABEL_PC", "IMM",
}
-- Maximum number of section buffer positions for dasm_put().
-- CHECK: Keep this in sync with the C code!
local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
-- Action name -> action number.
local map_action = {}
for n,name in ipairs(action_names) do
map_action[name] = n-1
end
-- Action list buffer.
local actlist = {}
-- Argument list for next dasm_put(). Start with offset 0 into action list.
local actargs = { 0 }
-- Current number of section buffer positions for dasm_put().
local secpos = 1
------------------------------------------------------------------------------
-- Dump action names and numbers.
local function dumpactions(out)
out:write("DynASM encoding engine action codes:\n")
for n,name in ipairs(action_names) do
local num = map_action[name]
out:write(format(" %-10s %02X %d\n", name, num, num))
end
out:write("\n")
end
-- Write action list buffer as a huge static C array.
local function writeactions(out, name)
local nn = #actlist
if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
out:write("static const unsigned int ", name, "[", nn, "] = {\n")
for i = 1,nn-1 do
assert(out:write("0x", tohex(actlist[i]), ",\n"))
end
assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
end
------------------------------------------------------------------------------
-- Add word to action list.
local function wputxw(n)
assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
actlist[#actlist+1] = n
end
-- Add action to list with optional arg. Advance buffer pos, too.
local function waction(action, val, a, num)
local w = assert(map_action[action], "bad action name `"..action.."'")
wputxw(0xff000000 + w * 0x10000 + (val or 0))
if a then actargs[#actargs+1] = a end
if a or num then secpos = secpos + (num or 1) end
end
-- Flush action list (intervening C code or buffer pos overflow).
local function wflush(term)
if #actlist == actargs[1] then return end -- Nothing to flush.
if not term then waction("STOP") end -- Terminate action list.
wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
secpos = 1 -- The actionlist offset occupies a buffer position, too.
end
-- Put escaped word.
local function wputw(n)
if n >= 0xff000000 then waction("ESC") end
wputxw(n)
end
-- Reserve position for word.
local function wpos()
local pos = #actlist+1
actlist[pos] = ""
return pos
end
-- Store word to reserved position.
local function wputpos(pos, n)
assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
actlist[pos] = n
end
------------------------------------------------------------------------------
-- Global label name -> global label number. With auto assignment on 1st use.
local next_global = 20
local map_global = setmetatable({}, { __index = function(t, name)
if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
local n = next_global
if n > 2047 then werror("too many global labels") end
next_global = n + 1
t[name] = n
return n
end})
-- Dump global labels.
local function dumpglobals(out, lvl)
local t = {}
for name, n in pairs(map_global) do t[n] = name end
out:write("Global labels:\n")
for i=20,next_global-1 do
out:write(format(" %s\n", t[i]))
end
out:write("\n")
end
-- Write global label enum.
local function writeglobals(out, prefix)
local t = {}
for name, n in pairs(map_global) do t[n] = name end
out:write("enum {\n")
for i=20,next_global-1 do
out:write(" ", prefix, t[i], ",\n")
end
out:write(" ", prefix, "_MAX\n};\n")
end
-- Write global label names.
local function writeglobalnames(out, name)
local t = {}
for name, n in pairs(map_global) do t[n] = name end
out:write("static const char *const ", name, "[] = {\n")
for i=20,next_global-1 do
out:write(" \"", t[i], "\",\n")
end
out:write(" (const char *)0\n};\n")
end
------------------------------------------------------------------------------
-- Extern label name -> extern label number. With auto assignment on 1st use.
local next_extern = 0
local map_extern_ = {}
local map_extern = setmetatable({}, { __index = function(t, name)
-- No restrictions on the name for now.
local n = next_extern
if n > 2047 then werror("too many extern labels") end
next_extern = n + 1
t[name] = n
map_extern_[n] = name
return n
end})
-- Dump extern labels.
local function dumpexterns(out, lvl)
out:write("Extern labels:\n")
for i=0,next_extern-1 do
out:write(format(" %s\n", map_extern_[i]))
end
out:write("\n")
end
-- Write extern label names.
local function writeexternnames(out, name)
out:write("static const char *const ", name, "[] = {\n")
for i=0,next_extern-1 do
out:write(" \"", map_extern_[i], "\",\n")
end
out:write(" (const char *)0\n};\n")
end
------------------------------------------------------------------------------
-- Arch-specific maps.
local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
local map_type = {} -- Type name -> { ctype, reg }
local ctypenum = 0 -- Type number (for Dt... macros).
-- Reverse defines for registers.
function _M.revdef(s)
if s == "r29" then return "sp"
elseif s == "r31" then return "ra" end
return s
end
------------------------------------------------------------------------------
-- Template strings for MIPS instructions.
local map_op = {
-- First-level opcodes.
j_1 = "08000000J",
jal_1 = "0c000000J",
b_1 = "10000000B",
beqz_2 = "10000000SB",
beq_3 = "10000000STB",
bnez_2 = "14000000SB",
bne_3 = "14000000STB",
blez_2 = "18000000SB",
bgtz_2 = "1c000000SB",
addi_3 = "20000000TSI",
li_2 = "24000000TI",
addiu_3 = "24000000TSI",
slti_3 = "28000000TSI",
sltiu_3 = "2c000000TSI",
andi_3 = "30000000TSU",
lu_2 = "34000000TU",
ori_3 = "34000000TSU",
xori_3 = "38000000TSU",
lui_2 = "3c000000TU",
beqzl_2 = "50000000SB",
beql_3 = "50000000STB",
bnezl_2 = "54000000SB",
bnel_3 = "54000000STB",
blezl_2 = "58000000SB",
bgtzl_2 = "5c000000SB",
lb_2 = "80000000TO",
lh_2 = "84000000TO",
lwl_2 = "88000000TO",
lw_2 = "8c000000TO",
lbu_2 = "90000000TO",
lhu_2 = "94000000TO",
lwr_2 = "98000000TO",
sb_2 = "a0000000TO",
sh_2 = "a4000000TO",
swl_2 = "a8000000TO",
sw_2 = "ac000000TO",
swr_2 = "b8000000TO",
cache_2 = "bc000000NO",
ll_2 = "c0000000TO",
lwc1_2 = "c4000000HO",
pref_2 = "cc000000NO",
ldc1_2 = "d4000000HO",
sc_2 = "e0000000TO",
swc1_2 = "e4000000HO",
sdc1_2 = "f4000000HO",
-- Opcode SPECIAL.
nop_0 = "00000000",
sll_3 = "00000000DTA",
movf_2 = "00000001DS",
movf_3 = "00000001DSC",
movt_2 = "00010001DS",
movt_3 = "00010001DSC",
srl_3 = "00000002DTA",
rotr_3 = "00200002DTA",
sra_3 = "00000003DTA",
sllv_3 = "00000004DTS",
srlv_3 = "00000006DTS",
rotrv_3 = "00000046DTS",
srav_3 = "00000007DTS",
jr_1 = "00000008S",
jalr_1 = "0000f809S",
jalr_2 = "00000009DS",
movz_3 = "0000000aDST",
movn_3 = "0000000bDST",
syscall_0 = "0000000c",
syscall_1 = "0000000cY",
break_0 = "0000000d",
break_1 = "0000000dY",
sync_0 = "0000000f",
mfhi_1 = "00000010D",
mthi_1 = "00000011S",
mflo_1 = "00000012D",
mtlo_1 = "00000013S",
mult_2 = "00000018ST",
multu_2 = "00000019ST",
div_2 = "0000001aST",
divu_2 = "0000001bST",
add_3 = "00000020DST",
move_2 = "00000021DS",
addu_3 = "00000021DST",
sub_3 = "00000022DST",
negu_2 = "00000023DT",
subu_3 = "00000023DST",
and_3 = "00000024DST",
or_3 = "00000025DST",
xor_3 = "00000026DST",
not_2 = "00000027DS",
nor_3 = "00000027DST",
slt_3 = "0000002aDST",
sltu_3 = "0000002bDST",
tge_2 = "00000030ST",
tge_3 = "00000030STZ",
tgeu_2 = "00000031ST",
tgeu_3 = "00000031STZ",
tlt_2 = "00000032ST",
tlt_3 = "00000032STZ",
tltu_2 = "00000033ST",
tltu_3 = "00000033STZ",
teq_2 = "00000034ST",
teq_3 = "00000034STZ",
tne_2 = "00000036ST",
tne_3 = "00000036STZ",
-- Opcode REGIMM.
bltz_2 = "04000000SB",
bgez_2 = "04010000SB",
bltzl_2 = "04020000SB",
bgezl_2 = "04030000SB",
tgei_2 = "04080000SI",
tgeiu_2 = "04090000SI",
tlti_2 = "040a0000SI",
tltiu_2 = "040b0000SI",
teqi_2 = "040c0000SI",
tnei_2 = "040e0000SI",
bltzal_2 = "04100000SB",
bal_1 = "04110000B",
bgezal_2 = "04110000SB",
bltzall_2 = "04120000SB",
bgezall_2 = "04130000SB",
synci_1 = "041f0000O",
-- Opcode SPECIAL2.
madd_2 = "70000000ST",
maddu_2 = "70000001ST",
mul_3 = "70000002DST",
msub_2 = "70000004ST",
msubu_2 = "70000005ST",
clz_2 = "70000020DS=",
clo_2 = "70000021DS=",
sdbbp_0 = "7000003f",
sdbbp_1 = "7000003fY",
-- Opcode SPECIAL3.
ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1
wsbh_2 = "7c0000a0DT",
seb_2 = "7c000420DT",
seh_2 = "7c000620DT",
rdhwr_2 = "7c00003bTD",
-- Opcode COP0.
mfc0_2 = "40000000TD",
mfc0_3 = "40000000TDW",
mtc0_2 = "40800000TD",
mtc0_3 = "40800000TDW",
rdpgpr_2 = "41400000DT",
di_0 = "41606000",
di_1 = "41606000T",
ei_0 = "41606020",
ei_1 = "41606020T",
wrpgpr_2 = "41c00000DT",
tlbr_0 = "42000001",
tlbwi_0 = "42000002",
tlbwr_0 = "42000006",
tlbp_0 = "42000008",
eret_0 = "42000018",
deret_0 = "4200001f",
wait_0 = "42000020",
-- Opcode COP1.
mfc1_2 = "44000000TG",
cfc1_2 = "44400000TG",
mfhc1_2 = "44600000TG",
mtc1_2 = "44800000TG",
ctc1_2 = "44c00000TG",
mthc1_2 = "44e00000TG",
bc1f_1 = "45000000B",
bc1f_2 = "45000000CB",
bc1t_1 = "45010000B",
bc1t_2 = "45010000CB",
bc1fl_1 = "45020000B",
bc1fl_2 = "45020000CB",
bc1tl_1 = "45030000B",
bc1tl_2 = "45030000CB",
["add.s_3"] = "46000000FGH",
["sub.s_3"] = "46000001FGH",
["mul.s_3"] = "46000002FGH",
["div.s_3"] = "46000003FGH",
["sqrt.s_2"] = "46000004FG",
["abs.s_2"] = "46000005FG",
["mov.s_2"] = "46000006FG",
["neg.s_2"] = "46000007FG",
["round.l.s_2"] = "46000008FG",
["trunc.l.s_2"] = "46000009FG",
["ceil.l.s_2"] = "4600000aFG",
["floor.l.s_2"] = "4600000bFG",
["round.w.s_2"] = "4600000cFG",
["trunc.w.s_2"] = "4600000dFG",
["ceil.w.s_2"] = "4600000eFG",
["floor.w.s_2"] = "4600000fFG",
["movf.s_2"] = "46000011FG",
["movf.s_3"] = "46000011FGC",
["movt.s_2"] = "46010011FG",
["movt.s_3"] = "46010011FGC",
["movz.s_3"] = "46000012FGT",
["movn.s_3"] = "46000013FGT",
["recip.s_2"] = "46000015FG",
["rsqrt.s_2"] = "46000016FG",
["cvt.d.s_2"] = "46000021FG",
["cvt.w.s_2"] = "46000024FG",
["cvt.l.s_2"] = "46000025FG",
["cvt.ps.s_3"] = "46000026FGH",
["c.f.s_2"] = "46000030GH",
["c.f.s_3"] = "46000030VGH",
["c.un.s_2"] = "46000031GH",
["c.un.s_3"] = "46000031VGH",
["c.eq.s_2"] = "46000032GH",
["c.eq.s_3"] = "46000032VGH",
["c.ueq.s_2"] = "46000033GH",
["c.ueq.s_3"] = "46000033VGH",
["c.olt.s_2"] = "46000034GH",
["c.olt.s_3"] = "46000034VGH",
["c.ult.s_2"] = "46000035GH",
["c.ult.s_3"] = "46000035VGH",
["c.ole.s_2"] = "46000036GH",
["c.ole.s_3"] = "46000036VGH",
["c.ule.s_2"] = "46000037GH",
["c.ule.s_3"] = "46000037VGH",
["c.sf.s_2"] = "46000038GH",
["c.sf.s_3"] = "46000038VGH",
["c.ngle.s_2"] = "46000039GH",
["c.ngle.s_3"] = "46000039VGH",
["c.seq.s_2"] = "4600003aGH",
["c.seq.s_3"] = "4600003aVGH",
["c.ngl.s_2"] = "4600003bGH",
["c.ngl.s_3"] = "4600003bVGH",
["c.lt.s_2"] = "4600003cGH",
["c.lt.s_3"] = "4600003cVGH",
["c.nge.s_2"] = "4600003dGH",
["c.nge.s_3"] = "4600003dVGH",
["c.le.s_2"] = "4600003eGH",
["c.le.s_3"] = "4600003eVGH",
["c.ngt.s_2"] = "4600003fGH",
["c.ngt.s_3"] = "4600003fVGH",
["add.d_3"] = "46200000FGH",
["sub.d_3"] = "46200001FGH",
["mul.d_3"] = "46200002FGH",
["div.d_3"] = "46200003FGH",
["sqrt.d_2"] = "46200004FG",
["abs.d_2"] = "46200005FG",
["mov.d_2"] = "46200006FG",
["neg.d_2"] = "46200007FG",
["round.l.d_2"] = "46200008FG",
["trunc.l.d_2"] = "46200009FG",
["ceil.l.d_2"] = "4620000aFG",
["floor.l.d_2"] = "4620000bFG",
["round.w.d_2"] = "4620000cFG",
["trunc.w.d_2"] = "4620000dFG",
["ceil.w.d_2"] = "4620000eFG",
["floor.w.d_2"] = "4620000fFG",
["movf.d_2"] = "46200011FG",
["movf.d_3"] = "46200011FGC",
["movt.d_2"] = "46210011FG",
["movt.d_3"] = "46210011FGC",
["movz.d_3"] = "46200012FGT",
["movn.d_3"] = "46200013FGT",
["recip.d_2"] = "46200015FG",
["rsqrt.d_2"] = "46200016FG",
["cvt.s.d_2"] = "46200020FG",
["cvt.w.d_2"] = "46200024FG",
["cvt.l.d_2"] = "46200025FG",
["c.f.d_2"] = "46200030GH",
["c.f.d_3"] = "46200030VGH",
["c.un.d_2"] = "46200031GH",
["c.un.d_3"] = "46200031VGH",
["c.eq.d_2"] = "46200032GH",
["c.eq.d_3"] = "46200032VGH",
["c.ueq.d_2"] = "46200033GH",
["c.ueq.d_3"] = "46200033VGH",
["c.olt.d_2"] = "46200034GH",
["c.olt.d_3"] = "46200034VGH",
["c.ult.d_2"] = "46200035GH",
["c.ult.d_3"] = "46200035VGH",
["c.ole.d_2"] = "46200036GH",
["c.ole.d_3"] = "46200036VGH",
["c.ule.d_2"] = "46200037GH",
["c.ule.d_3"] = "46200037VGH",
["c.sf.d_2"] = "46200038GH",
["c.sf.d_3"] = "46200038VGH",
["c.ngle.d_2"] = "46200039GH",
["c.ngle.d_3"] = "46200039VGH",
["c.seq.d_2"] = "4620003aGH",
["c.seq.d_3"] = "4620003aVGH",
["c.ngl.d_2"] = "4620003bGH",
["c.ngl.d_3"] = "4620003bVGH",
["c.lt.d_2"] = "4620003cGH",
["c.lt.d_3"] = "4620003cVGH",
["c.nge.d_2"] = "4620003dGH",
["c.nge.d_3"] = "4620003dVGH",
["c.le.d_2"] = "4620003eGH",
["c.le.d_3"] = "4620003eVGH",
["c.ngt.d_2"] = "4620003fGH",
["c.ngt.d_3"] = "4620003fVGH",
["add.ps_3"] = "46c00000FGH",
["sub.ps_3"] = "46c00001FGH",
["mul.ps_3"] = "46c00002FGH",
["abs.ps_2"] = "46c00005FG",
["mov.ps_2"] = "46c00006FG",
["neg.ps_2"] = "46c00007FG",
["movf.ps_2"] = "46c00011FG",
["movf.ps_3"] = "46c00011FGC",
["movt.ps_2"] = "46c10011FG",
["movt.ps_3"] = "46c10011FGC",
["movz.ps_3"] = "46c00012FGT",
["movn.ps_3"] = "46c00013FGT",
["cvt.s.pu_2"] = "46c00020FG",
["cvt.s.pl_2"] = "46c00028FG",
["pll.ps_3"] = "46c0002cFGH",
["plu.ps_3"] = "46c0002dFGH",
["pul.ps_3"] = "46c0002eFGH",
["puu.ps_3"] = "46c0002fFGH",
["c.f.ps_2"] = "46c00030GH",
["c.f.ps_3"] = "46c00030VGH",
["c.un.ps_2"] = "46c00031GH",
["c.un.ps_3"] = "46c00031VGH",
["c.eq.ps_2"] = "46c00032GH",
["c.eq.ps_3"] = "46c00032VGH",
["c.ueq.ps_2"] = "46c00033GH",
["c.ueq.ps_3"] = "46c00033VGH",
["c.olt.ps_2"] = "46c00034GH",
["c.olt.ps_3"] = "46c00034VGH",
["c.ult.ps_2"] = "46c00035GH",
["c.ult.ps_3"] = "46c00035VGH",
["c.ole.ps_2"] = "46c00036GH",
["c.ole.ps_3"] = "46c00036VGH",
["c.ule.ps_2"] = "46c00037GH",
["c.ule.ps_3"] = "46c00037VGH",
["c.sf.ps_2"] = "46c00038GH",
["c.sf.ps_3"] = "46c00038VGH",
["c.ngle.ps_2"] = "46c00039GH",
["c.ngle.ps_3"] = "46c00039VGH",
["c.seq.ps_2"] = "46c0003aGH",
["c.seq.ps_3"] = "46c0003aVGH",
["c.ngl.ps_2"] = "46c0003bGH",
["c.ngl.ps_3"] = "46c0003bVGH",
["c.lt.ps_2"] = "46c0003cGH",
["c.lt.ps_3"] = "46c0003cVGH",
["c.nge.ps_2"] = "46c0003dGH",
["c.nge.ps_3"] = "46c0003dVGH",
["c.le.ps_2"] = "46c0003eGH",
["c.le.ps_3"] = "46c0003eVGH",
["c.ngt.ps_2"] = "46c0003fGH",
["c.ngt.ps_3"] = "46c0003fVGH",
["cvt.s.w_2"] = "46800020FG",
["cvt.d.w_2"] = "46800021FG",
["cvt.s.l_2"] = "46a00020FG",
["cvt.d.l_2"] = "46a00021FG",
-- Opcode COP1X.
lwxc1_2 = "4c000000FX",
ldxc1_2 = "4c000001FX",
luxc1_2 = "4c000005FX",
swxc1_2 = "4c000008FX",
sdxc1_2 = "4c000009FX",
suxc1_2 = "4c00000dFX",
prefx_2 = "4c00000fMX",
["alnv.ps_4"] = "4c00001eFGHS",
["madd.s_4"] = "4c000020FRGH",
["madd.d_4"] = "4c000021FRGH",
["madd.ps_4"] = "4c000026FRGH",
["msub.s_4"] = "4c000028FRGH",
["msub.d_4"] = "4c000029FRGH",
["msub.ps_4"] = "4c00002eFRGH",
["nmadd.s_4"] = "4c000030FRGH",
["nmadd.d_4"] = "4c000031FRGH",
["nmadd.ps_4"] = "4c000036FRGH",
["nmsub.s_4"] = "4c000038FRGH",
["nmsub.d_4"] = "4c000039FRGH",
["nmsub.ps_4"] = "4c00003eFRGH",
}
------------------------------------------------------------------------------
local function parse_gpr(expr)
local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
local tp = map_type[tname or expr]
if tp then
local reg = ovreg or tp.reg
if not reg then
werror("type `"..(tname or expr).."' needs a register override")
end
expr = reg
end
local r = match(expr, "^r([1-3]?[0-9])$")
if r then
r = tonumber(r)
if r <= 31 then return r, tp end
end
werror("bad register name `"..expr.."'")
end
local function parse_fpr(expr)
local r = match(expr, "^f([1-3]?[0-9])$")
if r then
r = tonumber(r)
if r <= 31 then return r end
end
werror("bad register name `"..expr.."'")
end
local function parse_imm(imm, bits, shift, scale, signed)
local n = tonumber(imm)
if n then
local m = sar(n, scale)
if shl(m, scale) == n then
if signed then
local s = sar(m, bits-1)
if s == 0 then return shl(m, shift)
elseif s == -1 then return shl(m + shl(1, bits), shift) end
else
if sar(m, bits) == 0 then return shl(m, shift) end
end
end
werror("out of range immediate `"..imm.."'")
elseif match(imm, "^[rf]([1-3]?[0-9])$") or
match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
werror("expected immediate operand, got register")
else
waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
return 0
end
end
local function parse_disp(disp)
local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
if imm then
local r = shl(parse_gpr(reg), 21)
local extname = match(imm, "^extern%s+(%S+)$")
if extname then
waction("REL_EXT", map_extern[extname], nil, 1)
return r
else
return r + parse_imm(imm, 16, 0, 0, true)
end
end
local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
if reg and tailr ~= "" then
local r, tp = parse_gpr(reg)
if tp then
waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
return shl(r, 21)
end
end
werror("bad displacement `"..disp.."'")
end
local function parse_index(idx)
local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$")
if rt then
rt = parse_gpr(rt)
rs = parse_gpr(rs)
return shl(rt, 16) + shl(rs, 21)
end
werror("bad index `"..idx.."'")
end
local function parse_label(label, def)
local prefix = sub(label, 1, 2)
-- =>label (pc label reference)
if prefix == "=>" then
return "PC", 0, sub(label, 3)
end
-- ->name (global label reference)
if prefix == "->" then
return "LG", map_global[sub(label, 3)]
end
if def then
-- [1-9] (local label definition)
if match(label, "^[1-9]$") then
return "LG", 10+tonumber(label)
end
else
-- [<>][1-9] (local label reference)
local dir, lnum = match(label, "^([<>])([1-9])$")
if dir then -- Fwd: 1-9, Bkwd: 11-19.
return "LG", lnum + (dir == ">" and 0 or 10)
end
-- extern label (extern label reference)
local extname = match(label, "^extern%s+(%S+)$")
if extname then
return "EXT", map_extern[extname]
end
end
werror("bad label `"..label.."'")
end
------------------------------------------------------------------------------
-- Handle opcodes defined with template strings.
map_op[".template__"] = function(params, template, nparams)
if not params then return sub(template, 9) end
local op = tonumber(sub(template, 1, 8), 16)
local n = 1
-- Limit number of section buffer positions used by a single dasm_put().
-- A single opcode needs a maximum of 2 positions (ins/ext).
if secpos+2 > maxsecpos then wflush() end
local pos = wpos()
-- Process each character.
for p in gmatch(sub(template, 9), ".") do
if p == "D" then
op = op + shl(parse_gpr(params[n]), 11); n = n + 1
elseif p == "T" then
op = op + shl(parse_gpr(params[n]), 16); n = n + 1
elseif p == "S" then
op = op + shl(parse_gpr(params[n]), 21); n = n + 1
elseif p == "F" then
op = op + shl(parse_fpr(params[n]), 6); n = n + 1
elseif p == "G" then
op = op + shl(parse_fpr(params[n]), 11); n = n + 1
elseif p == "H" then
op = op + shl(parse_fpr(params[n]), 16); n = n + 1
elseif p == "R" then
op = op + shl(parse_fpr(params[n]), 21); n = n + 1
elseif p == "I" then
op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
elseif p == "U" then
op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
elseif p == "O" then
op = op + parse_disp(params[n]); n = n + 1
elseif p == "X" then
op = op + parse_index(params[n]); n = n + 1
elseif p == "B" or p == "J" then
local mode, n, s = parse_label(params[n], false)
if p == "B" then n = n + 2048 end
waction("REL_"..mode, n, s, 1)
n = n + 1
elseif p == "A" then
op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
elseif p == "M" then
op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
elseif p == "N" then
op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
elseif p == "C" then
op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1
elseif p == "V" then
op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1
elseif p == "W" then
op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1
elseif p == "Y" then
op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1
elseif p == "Z" then
op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
elseif p == "=" then
op = op + shl(band(op, 0xf800), 5) -- Copy D to T for clz, clo.
else
assert(false)
end
end
wputpos(pos, op)
end
------------------------------------------------------------------------------
-- Pseudo-opcode to mark the position where the action list is to be emitted.
map_op[".actionlist_1"] = function(params)
if not params then return "cvar" end
local name = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeactions(out, name) end)
end
-- Pseudo-opcode to mark the position where the global enum is to be emitted.
map_op[".globals_1"] = function(params)
if not params then return "prefix" end
local prefix = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeglobals(out, prefix) end)
end
-- Pseudo-opcode to mark the position where the global names are to be emitted.
map_op[".globalnames_1"] = function(params)
if not params then return "cvar" end
local name = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeglobalnames(out, name) end)
end
-- Pseudo-opcode to mark the position where the extern names are to be emitted.
map_op[".externnames_1"] = function(params)
if not params then return "cvar" end
local name = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeexternnames(out, name) end)
end
------------------------------------------------------------------------------
-- Label pseudo-opcode (converted from trailing colon form).
map_op[".label_1"] = function(params)
if not params then return "[1-9] | ->global | =>pcexpr" end
if secpos+1 > maxsecpos then wflush() end
local mode, n, s = parse_label(params[1], true)
if mode == "EXT" then werror("bad label definition") end
waction("LABEL_"..mode, n, s, 1)
end
------------------------------------------------------------------------------
-- Pseudo-opcodes for data storage.
map_op[".long_*"] = function(params)
if not params then return "imm..." end
for _,p in ipairs(params) do
local n = tonumber(p)
if not n then werror("bad immediate `"..p.."'") end
if n < 0 then n = n + 2^32 end
wputw(n)
if secpos+2 > maxsecpos then wflush() end
end
end
-- Alignment pseudo-opcode.
map_op[".align_1"] = function(params)
if not params then return "numpow2" end
if secpos+1 > maxsecpos then wflush() end
local align = tonumber(params[1])
if align then
local x = align
-- Must be a power of 2 in the range (2 ... 256).
for i=1,8 do
x = x / 2
if x == 1 then
waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
return
end
end
end
werror("bad alignment")
end
------------------------------------------------------------------------------
-- Pseudo-opcode for (primitive) type definitions (map to C types).
map_op[".type_3"] = function(params, nparams)
if not params then
return nparams == 2 and "name, ctype" or "name, ctype, reg"
end
local name, ctype, reg = params[1], params[2], params[3]
if not match(name, "^[%a_][%w_]*$") then
werror("bad type name `"..name.."'")
end
local tp = map_type[name]
if tp then
werror("duplicate type `"..name.."'")
end
-- Add #type to defines. A bit unclean to put it in map_archdef.
map_archdef["#"..name] = "sizeof("..ctype..")"
-- Add new type and emit shortcut define.
local num = ctypenum + 1
map_type[name] = {
ctype = ctype,
ctypefmt = format("Dt%X(%%s)", num),
reg = reg,
}
wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
ctypenum = num
end
map_op[".type_2"] = map_op[".type_3"]
-- Dump type definitions.
local function dumptypes(out, lvl)
local t = {}
for name in pairs(map_type) do t[#t+1] = name end
sort(t)
out:write("Type definitions:\n")
for _,name in ipairs(t) do
local tp = map_type[name]
local reg = tp.reg or ""
out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
end
out:write("\n")
end
------------------------------------------------------------------------------
-- Set the current section.
function _M.section(num)
waction("SECTION", num)
wflush(true) -- SECTION is a terminal action.
end
------------------------------------------------------------------------------
-- Dump architecture description.
function _M.dumparch(out)
out:write(format("DynASM %s version %s, released %s\n\n",
_info.arch, _info.version, _info.release))
dumpactions(out)
end
-- Dump all user defined elements.
function _M.dumpdef(out, lvl)
dumptypes(out, lvl)
dumpglobals(out, lvl)
dumpexterns(out, lvl)
end
------------------------------------------------------------------------------
-- Pass callbacks from/to the DynASM core.
function _M.passcb(wl, we, wf, ww)
wline, werror, wfatal, wwarn = wl, we, wf, ww
return wflush
end
-- Setup the arch-specific module.
function _M.setup(arch, opt)
g_arch, g_opt = arch, opt
end
-- Merge the core maps and the arch-specific maps.
function _M.mergemaps(map_coreop, map_def)
setmetatable(map_op, { __index = map_coreop })
setmetatable(map_def, { __index = map_archdef })
return map_op, map_def
end
return _M
------------------------------------------------------------------------------
-411
View File
@@ -1,411 +0,0 @@
/*
** DynASM PPC encoding engine.
** Copyright (C) 2005-2013 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "ppc"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
#endif
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if (ins & 0x8000)
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4;
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
patchrel:
CK((n & 3) == 0 &&
(((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >>
((ins & 2048) ? 16 : 26)) == 0, RANGE_REL);
cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc));
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif
File diff suppressed because it is too large Load Diff
-83
View File
@@ -1,83 +0,0 @@
/*
** DynASM encoding engine prototypes.
** Copyright (C) 2005-2013 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#ifndef _DASM_PROTO_H
#define _DASM_PROTO_H
#include <stddef.h>
#include <stdarg.h>
#define DASM_IDENT "DynASM 1.3.0"
#define DASM_VERSION 10300 /* 1.3.0 */
#ifndef Dst_DECL
#define Dst_DECL dasm_State **Dst
#endif
#ifndef Dst_REF
#define Dst_REF (*Dst)
#endif
#ifndef DASM_FDEF
#define DASM_FDEF extern
#endif
#ifndef DASM_M_GROW
#define DASM_M_GROW(ctx, t, p, sz, need) \
do { \
size_t _sz = (sz), _need = (need); \
if (_sz < _need) { \
if (_sz < 16) _sz = 16; \
while (_sz < _need) _sz += _sz; \
(p) = (t *)realloc((p), _sz); \
if ((p) == NULL) exit(1); \
(sz) = _sz; \
} \
} while(0)
#endif
#ifndef DASM_M_FREE
#define DASM_M_FREE(ctx, p, sz) free(p)
#endif
/* Internal DynASM encoder state. */
typedef struct dasm_State dasm_State;
/* Initialize and free DynASM state. */
DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
DASM_FDEF void dasm_free(Dst_DECL);
/* Setup global array. Must be called before dasm_setup(). */
DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
/* Grow PC label array. Can be called after dasm_setup(), too. */
DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
/* Setup encoder. */
DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
/* Feed encoder with actions. Calls are generated by pre-processor. */
DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
/* Link sections and return the resulting size. */
DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
/* Encode sections into buffer. */
DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
/* Get PC label offset. */
DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
#else
#define dasm_checkstep(a, b) 0
#endif
#endif /* _DASM_PROTO_H */
-12
View File
@@ -1,12 +0,0 @@
------------------------------------------------------------------------------
-- DynASM x64 module.
--
-- Copyright (C) 2005-2013 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined x86/x64 module.
-- All the interesting stuff is there.
------------------------------------------------------------------------------
x64 = true -- Using a global is an ugly, but effective solution.
return require("dasm_x86")
-470
View File
@@ -1,470 +0,0 @@
/*
** DynASM x86 encoding engine.
** Copyright (C) 2005-2013 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "x86"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. DASM_STOP must be 255. */
enum {
DASM_DISP = 233,
DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC,
DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN,
DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_VREG 0x15000000
#define DASM_S_UNDEF_L 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned char *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs, mrm = 4;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
int action = *p++;
if (action < DASM_DISP) {
ofs++;
} else if (action <= DASM_REL_A) {
int n = va_arg(ap, int);
b[pos++] = n;
switch (action) {
case DASM_DISP:
if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; }
case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
case DASM_IMM_D: ofs += 4; break;
case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob;
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
case DASM_SPACE: p++; ofs += n; break;
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG);
if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue;
}
mrm = 4;
} else {
int *pl, n;
switch (action) {
case DASM_REL_LG:
case DASM_IMM_LG:
n = *p++; pl = D->lglabels + n;
if (n <= 246) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */
pl -= 246; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
ofs += 4; /* Maximum offset needed. */
if (action == DASM_REL_LG || action == DASM_REL_PC)
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_ALIGN:
ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_EXTERN: p += 2; ofs += 4; break;
case DASM_ESC: p++; ofs++; break;
case DASM_MARK: mrm = p[-2]; break;
case DASM_SECTION:
n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
case DASM_STOP: goto stop;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
int op, action = *p++;
switch (action) {
case DASM_REL_LG: p++; op = p[-3]; goto rel_pc;
case DASM_REL_PC: op = p[-2]; rel_pc: {
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
if (shrink) { /* Shrinkable branch opcode? */
int lofs, lpos = b[pos];
if (lpos < 0) goto noshrink; /* Ext global? */
lofs = *DASM_POS2PTR(D, lpos);
if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
int i;
for (i = secnum; i < DASM_POS2SEC(lpos); i++)
lofs += D->sections[i].ofs;
} else {
lofs -= ofs; /* Bkwd label: unfix offset. */
}
lofs -= b[pos+1]; /* Short branch ok? */
if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
else { noshrink: shrink = 0; } /* No, cannot shrink op. */
}
b[pos+1] = shrink;
pos += 2;
break;
}
case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
case DASM_LABEL_LG: p++;
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
case DASM_EXTERN: p += 2; break;
case DASM_ESC: p++; break;
case DASM_MARK: break;
case DASM_SECTION: case DASM_STOP: goto stop;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#define dasmb(x) *cp++ = (unsigned char)(x)
#ifndef DASM_ALIGNED_WRITES
#define dasmw(x) \
do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
#define dasmd(x) \
do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
#else
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
unsigned char *base = (unsigned char *)buffer;
unsigned char *cp = base;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
unsigned char *mark = NULL;
while (1) {
int action = *p++;
int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
switch (action) {
case DASM_DISP: if (!mark) mark = cp; {
unsigned char *mm = mark;
if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
if (mrm != 5) { mm[-1] -= 0x80; break; } }
if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
}
case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
case DASM_IMM_DB: if (((n+128)&-256) == 0) {
db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
} else mark = NULL;
case DASM_IMM_D: wd: dasmd(n); break;
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
case DASM_IMM_W: dasmw(n); break;
case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; }
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
b++; n = (int)(ptrdiff_t)D->globals[-n];
case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
case DASM_REL_PC: rel_pc: {
int shrink = *b++;
int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
n = *pb - ((int)(cp-base) + 4-shrink);
if (shrink == 0) goto wd;
if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
goto wb;
}
case DASM_IMM_LG:
p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; }
case DASM_IMM_PC: {
int *pb = DASM_POS2PTR(D, n);
n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base);
goto wd;
}
case DASM_LABEL_LG: {
int idx = *p++;
if (idx >= 10)
D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
break;
}
case DASM_LABEL_PC: case DASM_SETLABEL: break;
case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
case DASM_ALIGN:
n = *p++;
while (((cp-base) & n)) *cp++ = 0x90; /* nop */
break;
case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
case DASM_MARK: mark = cp; break;
case DASM_ESC: action = *p++;
default: *cp++ = action; break;
case DASM_SECTION: case DASM_STOP: goto stop;
}
}
stop: (void)0;
}
}
if (base + D->codesize != cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
return D->status;
}
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-88
View File
@@ -1,88 +0,0 @@
.TH luajit 1 "" "" "LuaJIT documentation"
.SH NAME
luajit \- Just-In-Time Compiler for the Lua Language
\fB
.SH SYNOPSIS
.B luajit
[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
.SH "WEB SITE"
.IR http://luajit.org
.SH DESCRIPTION
.PP
This is the command-line program to run Lua programs with \fBLuaJIT\fR.
.PP
\fBLuaJIT\fR is a just-in-time (JIT) compiler for the Lua language.
The virtual machine (VM) is based on a fast interpreter combined with
a trace compiler. It can significantly improve the performance of Lua programs.
.PP
\fBLuaJIT\fR is API\- and ABI-compatible with the VM of the standard
Lua\ 5.1 interpreter. When embedding the VM into an application,
the built library can be used as a drop-in replacement.
.SH OPTIONS
.TP
.BI "\-e " chunk
Run the given chunk of Lua code.
.TP
.BI "\-l " library
Load the named library, just like \fBrequire("\fR\fIlibrary\fR\fB")\fR.
.TP
.BI "\-b " ...
Save or list bytecode. Run without arguments to get help on options.
.TP
.BI "\-j " command
Perform LuaJIT control command (optional space after \fB\-j\fR).
.TP
.BI "\-O" [opt]
Control LuaJIT optimizations.
.TP
.B "\-i"
Run in interactive mode.
.TP
.B "\-v"
Show \fBLuaJIT\fR version.
.TP
.B "\-E"
Ignore environment variables.
.TP
.B "\-\-"
Stop processing options.
.TP
.B "\-"
Read script from stdin instead.
.PP
After all options are processed, the given \fIscript\fR is run.
The arguments are passed in the global \fIarg\fR table.
.PP
Interactive mode is only entered, if no \fIscript\fR and no \fB\-e\fR
option is given. Interactive mode can be left with EOF (\fICtrl\-Z\fB).
.SH EXAMPLES
.TP
luajit hello.lua world
Prints "Hello world", assuming \fIhello.lua\fR contains:
.br
print("Hello", arg[1])
.TP
luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)"
Calculates the sum of the numbers from 1 to 1000000000.
.br
And finishes in a reasonable amount of time, too.
.TP
luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end"
Runs some nested loops and shows the resulting traces.
.SH COPYRIGHT
.PP
\fBLuaJIT\fR is Copyright \(co 2005-2013 Mike Pall.
.br
\fBLuaJIT\fR is open source software, released under the MIT license.
.SH SEE ALSO
.PP
More details in the provided HTML docs or at:
.IR http://luajit.org
.br
More about the Lua language can be found at:
.IR http://lua.org/docs.html
.PP
lua(1)
-24
View File
@@ -1,24 +0,0 @@
# Package information for LuaJIT to be used by pkg-config.
majver=2
minver=0
relver=1
version=${majver}.${minver}.${relver}
abiver=5.1
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
libname=luajit-${abiver}
includedir=${prefix}/include/luajit-${majver}.${minver}
INSTALL_LMOD=${prefix}/share/lua/${abiver}
INSTALL_CMOD=${prefix}/lib/lua/${abiver}
Name: LuaJIT
Description: Just-in-time compiler for Lua
URL: http://luajit.org
Version: ${version}
Requires:
Libs: -L${libdir} -l${libname}
Libs.private: -Wl,-E -lm -ldl
Cflags: -I${includedir}
-676
View File
@@ -1,676 +0,0 @@
##############################################################################
# LuaJIT Makefile. Requires GNU Make.
#
# Please read doc/install.html before changing any variables!
#
# Suitable for POSIX platforms (Linux, *BSD, OSX etc.).
# Also works with MinGW and Cygwin on Windows.
# Please check msvcbuild.bat for building with MSVC on Windows.
#
# Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
##############################################################################
MAJVER= 2
MINVER= 0
RELVER= 0
ABIVER= 5.1
NODOTABIVER= 51
##############################################################################
############################# COMPILER OPTIONS #############################
##############################################################################
# These options mainly affect the speed of the JIT compiler itself, not the
# speed of the JIT-compiled code. Turn any of the optional settings on by
# removing the '#' in front of them. Make sure you force a full recompile
# with "make clean", followed by "make" if you change any options.
#
# LuaJIT builds as a native 32 or 64 bit binary by default.
CC= gcc
#
# Use this if you want to force a 32 bit build on a 64 bit multilib OS.
#CC= gcc -m32
#
# Since the assembler part does NOT maintain a frame pointer, it's pointless
# to slow down the C part by not omitting it. Debugging, tracebacks and
# unwinding are not affected -- the assembler part has frame unwind
# information and GCC emits it where needed (x64) or with -g (see CCDEBUG).
CCOPT= -O2 -fomit-frame-pointer
# Use this if you want to generate a smaller binary (but it's slower):
#CCOPT= -Os -fomit-frame-pointer
# Note: it's no longer recommended to use -O3 with GCC 4.x.
# The I-Cache bloat usually outweighs the benefits from aggressive inlining.
#
# Target-specific compiler options:
#
# x86 only: it's recommended to compile at least for i686. Better yet,
# compile for an architecture that has SSE2, too (-msse -msse2).
#
# x86/x64 only: For GCC 4.2 or higher and if you don't intend to distribute
# the binaries to a different machine you could also use: -march=native
#
CCOPT_x86= -march=i686
CCOPT_x64=
CCOPT_arm=
CCOPT_ppc=
CCOPT_ppcspe=
CCOPT_mips=
#
CCDEBUG=
# Uncomment the next line to generate debug information:
#CCDEBUG= -g
#
CCWARN= -Wall
# Uncomment the next line to enable more warnings:
#CCWARN+= -Wextra -Wdeclaration-after-statement -Wredundant-decls -Wshadow -Wpointer-arith
#
##############################################################################
##############################################################################
################################ BUILD MODE ################################
##############################################################################
# The default build mode is mixed mode on POSIX. On Windows this is the same
# as dynamic mode.
#
# Mixed mode creates a static + dynamic library and a statically linked luajit.
BUILDMODE= mixed
#
# Static mode creates a static library and a statically linked luajit.
#BUILDMODE= static
#
# Dynamic mode creates a dynamic library and a dynamically linked luajit.
# Note: this executable will only run when the library is installed!
#BUILDMODE= dynamic
#
##############################################################################
##############################################################################
################################# FEATURES #################################
##############################################################################
# Enable/disable these features as needed, but make sure you force a full
# recompile with "make clean", followed by "make".
XCFLAGS=
#
# Permanently disable the FFI extension to reduce the size of the LuaJIT
# executable. But please consider that the FFI library is compiled-in,
# but NOT loaded by default. It only allocates any memory, if you actually
# make use of it.
#XCFLAGS+= -DLUAJIT_DISABLE_FFI
#
# Features from Lua 5.2 that are unlikely to break existing code are
# enabled by default. Some other features that *might* break some existing
# code (e.g. __pairs or os.execute() return values) can be enabled here.
# Note: this does not provide full compatibility with Lua 5.2 at this time.
#XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
#
# Disable the JIT compiler, i.e. turn LuaJIT into a pure interpreter.
#XCFLAGS+= -DLUAJIT_DISABLE_JIT
#
# Some architectures (e.g. PPC) can use either single-number (1) or
# dual-number (2) mode. Uncomment one of these lines to override the
# default mode. Please see LJ_ARCH_NUMMODE in lj_arch.h for details.
#XCFLAGS+= -DLUAJIT_NUMMODE=1
#XCFLAGS+= -DLUAJIT_NUMMODE=2
#
##############################################################################
##############################################################################
############################ DEBUGGING SUPPORT #############################
##############################################################################
# Enable these options as needed, but make sure you force a full recompile
# with "make clean", followed by "make".
# Note that most of these are NOT suitable for benchmarking or release mode!
#
# Use the system provided memory allocator (realloc) instead of the
# bundled memory allocator. This is slower, but sometimes helpful for
# debugging. It's helpful for Valgrind's memcheck tool, too. This option
# cannot be enabled on x64, since the built-in allocator is mandatory.
#XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
#
# This define is required to run LuaJIT under Valgrind. The Valgrind
# header files must be installed. You should enable debug information, too.
# Use --suppressions=lj.supp to avoid some false positives.
#XCFLAGS+= -DLUAJIT_USE_VALGRIND
#
# This is the client for the GDB JIT API. GDB 7.0 or higher is required
# to make use of it. See lj_gdbjit.c for details. Enabling this causes
# a non-negligible overhead, even when not running under GDB.
#XCFLAGS+= -DLUAJIT_USE_GDBJIT
#
# Turn on assertions for the Lua/C API to debug problems with lua_* calls.
# This is rather slow -- use only while developing C libraries/embeddings.
#XCFLAGS+= -DLUA_USE_APICHECK
#
# Turn on assertions for the whole LuaJIT VM. This significantly slows down
# everything. Use only if you suspect a problem with LuaJIT itself.
#XCFLAGS+= -DLUA_USE_ASSERT
#
##############################################################################
# You probably don't need to change anything below this line!
##############################################################################
##############################################################################
# Flags and options for host and target.
##############################################################################
# You can override the following variables at the make command line:
# CC HOST_CC STATIC_CC DYNAMIC_CC
# CFLAGS HOST_CFLAGS TARGET_CFLAGS
# LDFLAGS HOST_LDFLAGS TARGET_LDFLAGS TARGET_SHLDFLAGS
# LIBS HOST_LIBS TARGET_LIBS
# CROSS HOST_SYS TARGET_SYS TARGET_FLAGS
#
# Cross-compilation examples:
# make HOST_CC="gcc -m32" CROSS=i586-mingw32msvc- TARGET_SYS=Windows
# make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(XCFLAGS) $(CFLAGS)
LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
HOST_CC= $(CC)
HOST_RM= rm -f
# If left blank, minilua is built and used. You can supply an installed
# copy of (plain) Lua 5.1 or 5.2, plus Lua BitOp. E.g. with: HOST_LUA=lua
HOST_LUA=
HOST_XCFLAGS= -I.
HOST_XLDFLAGS=
HOST_XLIBS=
HOST_ACFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH) $(HOST_CFLAGS)
HOST_ALDFLAGS= $(LDOPTIONS) $(HOST_XLDFLAGS) $(HOST_LDFLAGS)
HOST_ALIBS= $(HOST_XLIBS) $(LIBS) $(HOST_LIBS)
STATIC_CC = $(CROSS)$(CC)
DYNAMIC_CC = $(CROSS)$(CC) -fPIC
TARGET_CC= $(STATIC_CC)
TARGET_STCC= $(STATIC_CC)
TARGET_DYNCC= $(DYNAMIC_CC)
TARGET_LD= $(CROSS)$(CC)
TARGET_AR= $(CROSS)ar rcus
TARGET_STRIP= $(CROSS)strip
TARGET_SONAME= libluajit.so
TARGET_DYLIBNAME= libluajit-$(ABIVER).$(MAJVER).dylib
TARGET_DYLIBPATH= $(or $(PREFIX),/usr/local)/lib/$(TARGET_DYLIBNAME)
TARGET_DLLNAME= lua$(NODOTABIVER).dll
TARGET_XSHLDFLAGS= -shared -fPIC -Wl,-soname,$(TARGET_SONAME)
TARGET_DYNXLDOPTS=
TARGET_LFSFLAGS= -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
TARGET_XCFLAGS= $(TARGET_LFSFLAGS) -U_FORTIFY_SOURCE
TARGET_XLDFLAGS=
TARGET_XLIBS= -lm
TARGET_TCFLAGS= $(CCOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS) $(TARGET_CFLAGS)
TARGET_ACFLAGS= $(CCOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS) $(TARGET_CFLAGS)
TARGET_ALDFLAGS= $(LDOPTIONS) $(TARGET_XLDFLAGS) $(TARGET_FLAGS) $(TARGET_LDFLAGS)
TARGET_ASHLDFLAGS= $(LDOPTIONS) $(TARGET_XSHLDFLAGS) $(TARGET_FLAGS) $(TARGET_SHLDFLAGS)
TARGET_ALIBS= $(TARGET_XLIBS) $(LIBS) $(TARGET_LIBS)
TARGET_TESTARCH=$(shell $(TARGET_CC) $(TARGET_TCFLAGS) -E lj_arch.h -dM)
ifneq (,$(findstring LJ_TARGET_X64 ,$(TARGET_TESTARCH)))
TARGET_LJARCH= x64
else
ifneq (,$(findstring LJ_TARGET_X86 ,$(TARGET_TESTARCH)))
TARGET_LJARCH= x86
else
ifneq (,$(findstring LJ_TARGET_ARM ,$(TARGET_TESTARCH)))
TARGET_LJARCH= arm
else
ifneq (,$(findstring LJ_TARGET_PPC ,$(TARGET_TESTARCH)))
TARGET_LJARCH= ppc
else
ifneq (,$(findstring LJ_TARGET_PPCSPE ,$(TARGET_TESTARCH)))
TARGET_LJARCH= ppcspe
else
ifneq (,$(findstring LJ_TARGET_MIPS ,$(TARGET_TESTARCH)))
ifneq (,$(findstring MIPSEL ,$(TARGET_TESTARCH)))
TARGET_ARCH= -D__MIPSEL__=1
endif
TARGET_LJARCH= mips
else
$(error Unsupported target architecture)
endif
endif
endif
endif
endif
endif
ifneq (,$(findstring LJ_TARGET_PS3 1,$(TARGET_TESTARCH)))
TARGET_SYS= PS3
TARGET_ARCH+= -D__CELLOS_LV2__
TARGET_XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
endif
ifneq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
TARGET_ARCH+= -DLUAJIT_NO_UNWIND
endif
TARGET_XCFLAGS+= $(CCOPT_$(TARGET_LJARCH))
TARGET_ARCH+= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET_LJARCH))
ifneq (,$(PREFIX))
ifneq (/usr/local,$(PREFIX))
TARGET_XCFLAGS+= -DLUA_XROOT=\"$(PREFIX)/\"
ifneq (/usr,$(PREFIX))
TARGET_DYNXLDOPTS= -Wl,-rpath,$(PREFIX)/lib
endif
endif
endif
##############################################################################
# System detection.
##############################################################################
ifeq (Windows,$(findstring Windows,$(OS))$(MSYSTEM)$(TERM))
HOST_SYS= Windows
HOST_RM= del
else
HOST_SYS:= $(shell uname -s)
ifneq (,$(findstring MINGW,$(HOST_SYS)))
HOST_SYS= Windows
HOST_MSYS= mingw
endif
ifneq (,$(findstring CYGWIN,$(HOST_SYS)))
HOST_SYS= Windows
HOST_MSYS= cygwin
endif
endif
TARGET_SYS?= $(HOST_SYS)
ifeq (Windows,$(TARGET_SYS))
TARGET_STRIP+= --strip-unneeded
TARGET_XSHLDFLAGS= -shared
TARGET_DYNXLDOPTS=
else
ifeq (Darwin,$(TARGET_SYS))
ifeq (,$(MACOSX_DEPLOYMENT_TARGET))
export MACOSX_DEPLOYMENT_TARGET=10.4
endif
TARGET_STRIP+= -x
TARGET_AR+= 2>/dev/null
TARGET_XCFLAGS+= -fno-stack-protector
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
TARGET_DYNXLDOPTS=
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
ifeq (x64,$(TARGET_LJARCH))
TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000
TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000
endif
else
ifeq (iOS,$(TARGET_SYS))
TARGET_STRIP+= -x
TARGET_AR+= 2>/dev/null
TARGET_XCFLAGS+= -fno-stack-protector
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
TARGET_DYNXLDOPTS=
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
else
ifneq (,$(findstring stack-protector,$(shell $(TARGET_CC) -dumpspecs)))
TARGET_XCFLAGS+= -fno-stack-protector
endif
ifneq (SunOS,$(TARGET_SYS))
ifneq (PS3,$(TARGET_SYS))
TARGET_XLDFLAGS+= -Wl,-E
endif
endif
ifeq (Linux,$(TARGET_SYS))
TARGET_XLIBS+= -ldl
endif
ifeq (GNU/kFreeBSD,$(TARGET_SYS))
TARGET_XLIBS+= -ldl
endif
endif
endif
endif
ifneq ($(HOST_SYS),$(TARGET_SYS))
ifeq (Windows,$(TARGET_SYS))
HOST_XCFLAGS+= -malign-double -DLUAJIT_OS=LUAJIT_OS_WINDOWS
else
ifeq (Linux,$(TARGET_SYS))
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_LINUX
else
ifeq (Darwin,$(TARGET_SYS))
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
else
ifeq (iOS,$(TARGET_SYS))
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
else
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OTHER
endif
endif
endif
endif
endif
ifneq (,$(CCDEBUG))
TARGET_STRIP= @:
endif
##############################################################################
# Files and pathnames.
##############################################################################
MINILUA_O= host/minilua.o
MINILUA_LIBS= -lm
MINILUA_T= host/minilua
MINILUA_X= $(MINILUA_T)
ifeq (,$(HOST_LUA))
HOST_LUA= $(MINILUA_X)
DASM_DEP= $(MINILUA_T)
endif
DASM_DIR= ../dynasm
DASM= $(HOST_LUA) $(DASM_DIR)/dynasm.lua
DASM_XFLAGS=
DASM_AFLAGS=
DASM_ARCH= $(TARGET_LJARCH)
ifneq (,$(findstring LJ_ARCH_BITS 64,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D P64
endif
ifneq (,$(findstring LJ_HASJIT 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D JIT
endif
ifneq (,$(findstring LJ_HASFFI 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D FFI
endif
ifneq (,$(findstring LJ_DUALNUM 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D DUALNUM
endif
ifneq (,$(findstring LJ_ARCH_HASFPU 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D FPU
TARGET_ARCH+= -DLJ_ARCH_HASFPU=1
else
TARGET_ARCH+= -DLJ_ARCH_HASFPU=0
endif
ifeq (,$(findstring LJ_ABI_SOFTFP 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D HFABI
TARGET_ARCH+= -DLJ_ABI_SOFTFP=0
else
TARGET_ARCH+= -DLJ_ABI_SOFTFP=1
endif
DASM_AFLAGS+= -D VER=$(subst LJ_ARCH_VERSION_,,$(filter LJ_ARCH_VERSION_%,$(subst LJ_ARCH_VERSION ,LJ_ARCH_VERSION_,$(TARGET_TESTARCH))))
ifeq (Windows,$(TARGET_SYS))
DASM_AFLAGS+= -D WIN
endif
ifeq (x86,$(TARGET_LJARCH))
ifneq (,$(findstring __SSE2__ 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D SSE
endif
else
ifeq (x64,$(TARGET_LJARCH))
DASM_ARCH= x86
else
ifeq (arm,$(TARGET_LJARCH))
ifeq (iOS,$(TARGET_SYS))
DASM_AFLAGS+= -D IOS
endif
else
ifeq (ppc,$(TARGET_LJARCH))
ifneq (,$(findstring LJ_ARCH_SQRT 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D SQRT
endif
ifneq (,$(findstring LJ_ARCH_ROUND 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D ROUND
endif
ifneq (,$(findstring LJ_ARCH_PPC64 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D GPR64
endif
ifeq (PS3,$(TARGET_SYS))
DASM_AFLAGS+= -D PPE -D TOC
endif
endif
endif
endif
endif
DASM_FLAGS= $(DASM_XFLAGS) $(DASM_AFLAGS)
DASM_DASC= vm_$(DASM_ARCH).dasc
BUILDVM_O= host/buildvm.o host/buildvm_asm.o host/buildvm_peobj.o \
host/buildvm_lib.o host/buildvm_fold.o
BUILDVM_T= host/buildvm
BUILDVM_X= $(BUILDVM_T)
HOST_O= $(MINILUA_O) $(BUILDVM_O)
HOST_T= $(MINILUA_T) $(BUILDVM_T)
LJVM_S= lj_vm.s
LJVM_O= lj_vm.o
LJVM_BOUT= $(LJVM_S)
LJVM_MODE= elfasm
LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o
LJLIB_C= $(LJLIB_O:.o=.c)
LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \
lj_api.o lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \
lj_asm.o lj_trace.o lj_gdbjit.o \
lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_ccallback.o \
lj_carith.o lj_clib.o lj_cparse.o \
lj_lib.o lj_alloc.o lib_aux.o \
$(LJLIB_O) lib_init.o
LJVMCORE_O= $(LJVM_O) $(LJCORE_O)
LJVMCORE_DYNO= $(LJVMCORE_O:.o=_dyn.o)
LIB_VMDEF= jit/vmdef.lua
LIB_VMDEFP= $(LIB_VMDEF)
LUAJIT_O= luajit.o
LUAJIT_A= libluajit.a
LUAJIT_SO= libluajit.so
LUAJIT_T= luajit
ALL_T= $(LUAJIT_T) $(LUAJIT_A) $(LUAJIT_SO) $(HOST_T)
ALL_HDRGEN= lj_bcdef.h lj_ffdef.h lj_libdef.h lj_recdef.h lj_folddef.h \
host/buildvm_arch.h
ALL_GEN= $(LJVM_S) $(ALL_HDRGEN) $(LIB_VMDEFP)
WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk
ALL_RM= $(ALL_T) $(ALL_GEN) *.o host/*.o $(WIN_RM)
##############################################################################
# Build mode handling.
##############################################################################
# Mixed mode defaults.
TARGET_O= $(LUAJIT_A)
TARGET_T= $(LUAJIT_T) $(LUAJIT_SO)
TARGET_DEP= $(LIB_VMDEF) $(LUAJIT_SO)
ifeq (Windows,$(TARGET_SYS))
TARGET_DYNCC= $(STATIC_CC)
LJVM_MODE= coffasm
LUAJIT_T= luajit.exe
ifeq (cygwin,$(HOST_MSYS))
LUAJIT_SO= cyg$(TARGET_DLLNAME)
else
LUAJIT_SO= $(TARGET_DLLNAME)
endif
# Mixed mode is not supported on Windows. And static mode doesn't work well.
# C modules cannot be loaded, because they bind to lua51.dll.
ifneq (static,$(BUILDMODE))
BUILDMODE= dynamic
TARGET_XCFLAGS+= -DLUA_BUILD_AS_DLL
endif
endif
ifeq (Darwin,$(TARGET_SYS))
LJVM_MODE= machasm
endif
ifeq (iOS,$(TARGET_SYS))
LJVM_MODE= machasm
endif
ifeq (SunOS,$(TARGET_SYS))
BUILDMODE= static
endif
ifeq (PS3,$(TARGET_SYS))
BUILDMODE= static
endif
ifeq (Windows,$(HOST_SYS))
MINILUA_T= host/minilua.exe
BUILDVM_T= host/buildvm.exe
ifeq (,$(HOST_MSYS))
MINILUA_X= host\minilua
BUILDVM_X= host\buildvm
ALL_RM:= $(subst /,\,$(ALL_RM))
endif
endif
ifeq (static,$(BUILDMODE))
TARGET_DYNCC= @:
TARGET_T= $(LUAJIT_T)
TARGET_DEP= $(LIB_VMDEF)
else
ifeq (dynamic,$(BUILDMODE))
ifneq (Windows,$(TARGET_SYS))
TARGET_CC= $(DYNAMIC_CC)
endif
TARGET_DYNCC= @:
LJVMCORE_DYNO= $(LJVMCORE_O)
TARGET_O= $(LUAJIT_SO)
TARGET_XLDFLAGS+= $(TARGET_DYNXLDOPTS)
else
ifeq (Darwin,$(TARGET_SYS))
TARGET_DYNCC= @:
LJVMCORE_DYNO= $(LJVMCORE_O)
endif
ifeq (iOS,$(TARGET_SYS))
TARGET_DYNCC= @:
LJVMCORE_DYNO= $(LJVMCORE_O)
endif
endif
endif
Q= @
E= @echo
#Q=
#E= @:
##############################################################################
# Make targets.
##############################################################################
default all: $(TARGET_T)
amalg:
@grep "^[+|]" ljamalg.c
$(MAKE) all "LJCORE_O=ljamalg.o"
clean:
$(HOST_RM) $(ALL_RM)
depend:
@for file in $(ALL_HDRGEN); do \
test -f $$file || touch $$file; \
done
@$(HOST_CC) $(HOST_ACFLAGS) -MM *.c host/*.c | \
sed -e "s| [^ ]*/dasm_\S*\.h||g" \
-e "s|^\([^l ]\)|host/\1|" \
-e "s| lj_target_\S*\.h| lj_target_*.h|g" \
-e "s| lj_emit_\S*\.h| lj_emit_*.h|g" \
-e "s| lj_asm_\S*\.h| lj_asm_*.h|g" >Makefile.dep
@for file in $(ALL_HDRGEN); do \
test -s $$file || $(HOST_RM) $$file; \
done
.PHONY: default all amalg clean depend
##############################################################################
# Rules for generated files.
##############################################################################
$(MINILUA_T): $(MINILUA_O)
$(E) "HOSTLINK $@"
$(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(MINILUA_O) $(MINILUA_LIBS) $(HOST_ALIBS)
host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP)
$(E) "DYNASM $@"
$(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC)
host/buildvm.o: $(DASM_DIR)/dasm_*.h
$(BUILDVM_T): $(BUILDVM_O)
$(E) "HOSTLINK $@"
$(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(BUILDVM_O) $(HOST_ALIBS)
$(LJVM_BOUT): $(BUILDVM_T)
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@
lj_bcdef.h: $(BUILDVM_T) $(LJLIB_C)
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m bcdef -o $@ $(LJLIB_C)
lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m ffdef -o $@ $(LJLIB_C)
lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m libdef -o $@ $(LJLIB_C)
lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C)
$(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m vmdef -o $(LIB_VMDEFP) $(LJLIB_C)
lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
$(E) "BUILDVM $@"
$(Q)$(BUILDVM_X) -m folddef -o $@ lj_opt_fold.c
##############################################################################
# Object file rules.
##############################################################################
%.o: %.c
$(E) "CC $@"
$(Q)$(TARGET_DYNCC) $(TARGET_ACFLAGS) -c -o $(@:.o=_dyn.o) $<
$(Q)$(TARGET_CC) $(TARGET_ACFLAGS) -c -o $@ $<
%.o: %.s
$(E) "ASM $@"
$(Q)$(TARGET_DYNCC) $(TARGET_ACFLAGS) -c -o $(@:.o=_dyn.o) $<
$(Q)$(TARGET_CC) $(TARGET_ACFLAGS) -c -o $@ $<
$(LUAJIT_O):
$(E) "CC $@"
$(Q)$(TARGET_STCC) $(TARGET_ACFLAGS) -c -o $@ $<
$(HOST_O): %.o: %.c
$(E) "HOSTCC $@"
$(Q)$(HOST_CC) $(HOST_ACFLAGS) -c -o $@ $<
include Makefile.dep
##############################################################################
# Target file rules.
##############################################################################
$(LUAJIT_A): $(LJVMCORE_O)
$(E) "AR $@"
$(Q)$(TARGET_AR) $@ $(LJVMCORE_O)
# The dependency on _O, but linking with _DYNO is intentional.
$(LUAJIT_SO): $(LJVMCORE_O)
$(E) "DYNLINK $@"
$(Q)$(TARGET_LD) $(TARGET_ASHLDFLAGS) -o $@ $(LJVMCORE_DYNO) $(TARGET_ALIBS)
$(Q)$(TARGET_STRIP) $@
$(LUAJIT_T): $(TARGET_O) $(LUAJIT_O) $(TARGET_DEP)
$(E) "LINK $@"
$(Q)$(TARGET_LD) $(TARGET_ALDFLAGS) -o $@ $(LUAJIT_O) $(TARGET_O) $(TARGET_ALIBS)
$(Q)$(TARGET_STRIP) $@
$(E) "OK Successfully built LuaJIT"
##############################################################################

Some files were not shown because too many files have changed in this diff Show More