A 'lazy' compilation mode to make writting multiplatform code easier without having to clutter the project
ryuukk_
ryuukk.dev at gmail.com
Wed Feb 22 14:23:09 UTC 2023
Hello,
My project is kinda special, i am targeting all 3 major desktop
OS's as well as the web with WebAssembly
So my code is full of ``version(WASM) / version(Windows)``, i
wish i didn't need to do that because it clutters the code for no
real benefits, makes things harder to follow/read as i constantly
need to readjust to the indentation level and need to process
version() despite my function named properly
It's kinda repeating the C/C++ mistake with
unreadable/unfollowable ``#ifdef`` everywhere
I try to structure my code so that i put platform specific code
is in their own module when it's too big
But for 3-4 simple functions it gets annoying real quick
When i separate platform specific code into their own modules, i
have then to do a lot of maintenance to then include the proper
modules when i compile for the specific target, or when i
refactor my code, i need to make sure my ``dub.json`` is in sync
This is kinda annoying..
So what if the compiler would follow the code path and only
compile what is used from the module, so there is no longer a
need to be overly noisy with bunches of ``version`` code blocks
and extra indentation everywhere
One benefit of that mode would be faster builds when importing
modules from phobos when one need just few functions from it
Because right now it is very ugly, and my ``dub.json`` gets quite
large that it becomes painful to read/edit (yeah, i'm also not a
fan of json, it's too noisy/verbose)
```json
{
"name": "game",
"targetType": "executable",
"targetName": "game",
"targetPath": "../../bin",
"workingDirectory": "../../bin",
"sourcePaths": [ "src" ],
"importPaths": [ "src" ],
"stringImportPaths": [
"../../bin/"
],
"buildTypes": {
"prod": {
"buildOptions": [ "releaseMode" ],
"versions": [ "PROD" ],
"dflags": [
"-preview=rvaluerefparam",
],
"dflags-ldc": [
"-O3",
],
"dflags-windows-ldc": [
"-O3",
],
},
"prod-debug": {
"buildOptions": [ "debugMode", "debugInfo" ],
"versions": [ "PROD" ]
},
},
"configurations": [
{
"name": "desktop",
"mainSourceFile": "src/app.d",
"versions": [ "GAME", "DESKTOP", "MONGOOSE", "GL_30",
"GLFW_33", "FT_211", "BindFT_Static"],
"sourcePaths": [
"../../better_d/rt",
"../../better_d/network",
"../../better_d/mongoose",
"../../better_d/glfw",
"../dawn",
"../kshared/",
],
"importPaths": [
"../../better_d/",
"../../better_d/rt",
"../",
],
"libs-windows": [
"ws2_32",
"Winmm",
"USER32",
"GDI32",
"ADVAPI32",
"CRYPT32",
"Shell32"
],
"libs-linux": ["freetype", "z", "ssl", "crypto",
"x11"],
"sourceFiles-windows": [
"../../better_d/glfw/bin/windows/glfw3.lib",
"../../better_d/freetype/bin/windows/freetype.lib",
"../../better_d/mongoose/bin/windows/libcrypto.lib",
"../../better_d/mongoose/bin/windows/libssl.lib",
"../../better_d/mongoose/bin/windows/mongoose.lib",
"../../better_d/zlib/bin/windows/zlib.lib",
],
"sourceFiles-linux": [
"../../better_d/glfw/bin/linux/libglfw3.a",
"../../better_d/mongoose/bin/linux/mongoose.a",
],
"dflags": [
"-preview=rvaluerefparam",
"-betterC"
],
"dflags-dmd": [
"-preview=bitfields",
],
"lflags-windows-dmd": [ "/OPT:REF"],
"lflags-windows": [
"/NODEFAULTLIB:libcmt.lib"
],
},
{
"name": "dll",
"versions": [ "GAME", "DESKTOP", "MONGOOSE", "GL_30",
"GLFW_33", "FT_211", "BindFT_Static"],
"targetType": "dynamicLibrary",
"targetName": "gamed",
"sourcePaths": [
"../../better_d/rt",
"../../better_d/network",
"../../better_d/mongoose",
"../../better_d/glfw",
"../dawn",
"../kshared/",
],
"importPaths": [
"../../better_d/",
"../../better_d/rt",
"../",
],
"libs-windows": [
"ws2_32",
"Winmm",
"USER32",
"GDI32",
"ADVAPI32",
"CRYPT32",
"Shell32"
],
"libs-linux": ["freetype", "z", "ssl", "crypto",
"x11"],
"sourceFiles-windows": [
"../../better_d/glfw/bin/windows/glfw3.lib",
"../../better_d/freetype/bin/windows/freetype.lib",
"../../better_d/mongoose/bin/windows/libcrypto.lib",
"../../better_d/mongoose/bin/windows/libssl.lib",
"../../better_d/mongoose/bin/windows/mongoose.lib",
"../../better_d/zlib/bin/windows/zlib.lib",
],
"sourceFiles-linux": [
"../../better_d/glfw/bin/linux/libglfw3.a",
"../../better_d/mongoose/bin/linux/mongoose.a",
],
"dflags": [
"-preview=rvaluerefparam",
"-betterC"
],
"dflags-dmd": [
"-preview=bitfields",
],
"lflags-windows-dmd": [ "/OPT:REF" ],
"lflags-windows": [
"/NODEFAULTLIB:libcmt.lib"
],
},
{
"name": "wasm",
"targetName": "game",
"mainSourceFile": "src/app.d",
"versions": [ "GAME", "WASM"],
"sourcePaths": [
"../../better_d/rt",
"../dawn",
"../kshared/"
],
"importPaths": [
"../../better_d",
"../",
],
"dflags-ldc": [
"--fvisibility=hidden",
"-linkonce-templates",
"-preview=rvaluerefparam",
"-O3",
"-flto=thin",
],
"lflags-ldc": [
"-z","stack-size=1048576",
"--stack-first",
"-allow-undefined"
],
"sourceFiles": [
"../../better_d/zlib/bin/wasm32/zlib.a",
]
}
]
}
```
Example of module:
```D
module rt.event;
version(Windows)
{
enum OK = true;
// windows specific imports/aliases
}
else version(Posix)
{
enum OK = true;
// posix specific imports/aliases
}
else version(WASM)
{
enum OK = false;
}
static if(OK)
{
// common code
version(Windows)
{
// windows specific common code
}
else version(Posix)
{
// posix specific common code
}
}
```
What if:
```D
module rt.event;
// import windows specific
import windows = ..;
// import posix specific
import posix = ..;
void poll()
{
version (Windows)
poll_windows();
else version(Posix)
poll_posix();
}
void poll_posix()
{
posix.___();
}
void poll_windows()
{
windows.___();
}
```
Compiler should know that if i am on windows, when i call
``poll()`` it'll only ever call ``poll_windows()``, why fetch
``import posix = ..;``and compile ``poll_posix()``?
``version`` is nice when i want to separate code path within a
function, but everything outside doesn't make much sense as it
clutters code
If a ``lazy`` compilation mode is not possible, then what about
something that would allow something like that:
```D
module rt.event;
version(WASM)
{
return; // no event in WASM target
}
(..)
```
or
```D
module rt.event; // exclude: WASM
(..)
```
More information about the Digitalmars-d
mailing list