Libraries can be helpful. But at the baseline, what you have to solve is the problem of adjusting your dependency load such that adding new target platforms is a matter of rewriting small details, which means taking a language-designer's view of your system and saying "OK, if I need to automate the rewrite, then I need a compilation mechanism". Sometimes you have to change asset formats or runtime I/O mechanisms, but you can select what layer of the design you are aiming to standardize and go from there. e.g. records of chess games have a few defined formats. They don't need to track the assets used to draw the board, or the account information of the players.
If what you want is all of it: every pixel and frame of output the same, all input devices treated identically across all environments, then you'll gravitate towards a VM type of design, like Another World, Z-Machine or SCUMM, to name three well-known examples of such a design.
https://prog21.dadgum.com/66.html
Libraries can be helpful. But at the baseline, what you have to solve is the problem of adjusting your dependency load such that adding new target platforms is a matter of rewriting small details, which means taking a language-designer's view of your system and saying "OK, if I need to automate the rewrite, then I need a compilation mechanism". Sometimes you have to change asset formats or runtime I/O mechanisms, but you can select what layer of the design you are aiming to standardize and go from there. e.g. records of chess games have a few defined formats. They don't need to track the assets used to draw the board, or the account information of the players.
If what you want is all of it: every pixel and frame of output the same, all input devices treated identically across all environments, then you'll gravitate towards a VM type of design, like Another World, Z-Machine or SCUMM, to name three well-known examples of such a design.