ellraiser / love-build

zero-dependency cross-platform builder for LÖVE to export games to Windows, MacOS, and Linux
https://love2d.org
20 stars 4 forks source link

Relative location of libs differs between operating systems #2

Closed Endaris closed 5 months ago

Endaris commented 5 months ago

Using the following build.lua:

return {
  name = 'Panel Attack', -- name of the game for your executable
  developer = 'Panel Attack Devs', -- dev name used in metadata of the file
  version = '1.0', -- 'version' of your game, used to make a version folder in output
  love = '11.5', -- version of LÖVE to use, must match github releases
  ignore = {'updater/tests', '.DS_Store', '.gitignore', '.vscode', 'https'}, -- folders/files to ignore in your project
  icon = 'icon.png', -- 256x256px PNG icon for game, will be converted for you

  libs = { -- files to place in output directly rather than fuse
    windows = {'https/win64/https.dll'}, -- can specify per platform or "all"
    macos = {'https/macos/https.so'},
    linux = {'https/linux/https.so'}
  }
}

The structure is indicated as by the files in libs with the files taken from here. In code I have been requiring https directly with local https = require("https"). After running that configuration through love-build and starting the linux build, I get a module not found error for the https module: grafik https.so is being placed in the lib folder next to AppRun in the love-build output. I have verified that the https.so in the specified location is functional by copying it to the root directory of the project. I also tried compressing the build with the appimagetool before starting again with the same result.

When starting the windows build through wine, https is found and the app starts correctly with the above configuration.

Endaris commented 5 months ago

macos seems to behave the same as linux in this scenario, except that manually placing https.so at the root level and treating it as a regular file does not seem to resolve the issue (I don't have a mac so I had to have someone else test)

ellraiser commented 5 months ago

For MacOS - putting in Contents/Resources/ or (Contents/MacOS/) is the 'expected' location for mac libs, I've tried putting your https.so in all locations possible inside the .app (I use MacOS) and none work correctly.

It seems to be todo with that specific library file and how it's expected to be loaded in it's own code. Looking at the forums, one recommendation is to copy the .so file to the save directory first which will then be read from: https://love2d.org/forums/viewtopic.php?t=65946&start=10 This does work, example code to do so would be like:

-- only on mac
if love.system.getOS() == 'OS X' then
  -- mount the game source to the filesystem as /gamefiles/
  local dir = love.filesystem.getSourceBaseDirectory()
  local success = love.filesystem.mount(dir, "gamefiles")
  print(dir, success)
  -- copy so from game files to the save directory
  local https_so = love.filesystem.read('gamefiles/https.so')
  local copied = love.filesystem.write('https.so', https_so)
  print(copied)
end

-- now require will find the file as its in the save dir
local https = require('https')
print(https)

The above code also works for Linux too, so will ask the love team about expected path finding for require for unix, as that seems a weird workaround

ellraiser commented 5 months ago

Okay - apparently this is due to the default way lua looks for stuff with require() https://www.lua.org/manual/5.1/manual.html#pdf-package.cpath https://love2d.org/wiki/love.filesystem.setCRequirePath

So recommended way would be to add to that with the paths you want to include, however on the docs page, it mentions: "The paths are relative to the game's source and save directories, as well as any paths mounted with love.filesystem.mount"

So, as a nicer workaround we could just mount the source base directory - this works on both MacOS and Linux:

love.filesystem.mount(love.filesystem.getSourceBaseDirectory(), "gamefiles")
local https = require('https')
print(https)

As its not something love-build is specifically responsible for there isn't anything I can change in the code, however I will change the example project to use the https module specifically for all 3 platforms, and include the line above at the top of the main.lua

Endaris commented 5 months ago

Many many thanks for looking into that so quickly and even providing me with a solution even though the problem wasn't with love-build in the end. Appreciate it a lot!

Endaris commented 5 months ago

however I will change the example project to use the https module specifically for all 3 platforms, and include the line above at the top of the main.lua

If I run example-project through the 0.4 release, the generated linux build still crashes with the https error.

ellraiser commented 5 months ago

Oh actually - seems like you might need to still copy the file over to the save directory as an extra step, just mounting the source might not be enough?

Try doing this before your require() call

if love.filesystem.isFused() and (love.system.getOS() == "Linux" or love.system.getOS() == "OS X") then
  love.filesystem.mount(love.filesystem.getSourceBaseDirectory(), "gamefiles")
  local file = love.filesystem.read('gamefiles/https.so')
  love.filesystem.write('https.so', file)
end

This would write the https.so file to your games save directory, which then should get picked up - you have to have the fused check version cos of the path being different when dev

Maybe it is worth looking into you setting the package.cpath directly instead, as this doesn't seem like the nicest work around :')

Endaris commented 5 months ago

If I add the respective code in place of the current mount, I get

Error

main.lua:6: bad argument #2 to 'write' (string or Data expected)

Traceback

[love "callbacks.lua"]:228: in function 'handler'
[C]: in function 'write'
main.lua:6: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'

indicating that it still cannot find https.so somehow. I think at this point it makes more sense to bring this directly to the lua-https repo because as you mentioned, there's only so much you can do with tooling when love does not find the library despite trying to serve it on a silver platter.

ellraiser commented 5 months ago

It'll depend on the path you from the source so might be a bit different to what I wrote above - however I've got a better solution, works for MacOS but need to test for Linux still:

package.cpath = package.cpath .. ';' .. love.filesystem.getSourceBaseDirectory() .. '/?.so'
local https = require('https')
assert(https ~= nil)

This modifies the cpath for lua (initially set by the LUA_CPATH env) to add our source destination too, wildcard for .so files - might work for linux too?

ellraiser commented 5 months ago

Going to close this as even with editing the CPATH for AppRun on Linux, MacOS will still need the above line which will be put in the example project