Skip to content

Commit 39f75de

Browse files
committed
Added: Redub cross compile target support
1 parent 19e94b0 commit 39f75de

15 files changed

Lines changed: 251 additions & 81 deletions

File tree

README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Those are the additions I've made over dub
2121
- [**Library API**](#using-its-library-api) - Integrate redub directly in your application
2222
- **Watching Directories** - `redub watch`- Builds dependents automatically on changes. Add `--run` to run the program after building.
2323
- **MacOS Universal Builds** - `redub build-universal` - Generates a single binary containing arm64 and x86_64 architectures on MacOS
24+
- [**Redub Executable Icons**](#redub-executable-icons) - Adds inside the recipe file a way to define how your program icon will look
25+
- [**Linker Diagnostics**](#redub-linker-diagnostics) - Experimental support to improve linker message errors.
26+
- [**Cross Compilation Targets**](#redub-cross-compile) - Adds support to build targets, selecting a compiler, architecture and other configuration by just calling `redub --target=PSVita`
2427

2528

2629
## Redub Help
@@ -123,6 +126,59 @@ You can also control the bundle configurations by using. Failing to use a valid
123126
}
124127
```
125128

129+
130+
## Redub Linker Diagnostics
131+
- **1.29.0**: Added Windows Linker Diagnostics.
132+
133+
Sometimes people may get cryptic error messages regarding anundefined __ModuleInitZ symbol. Since Redub already had information on how each module imports each other, I've ended up adding support to improve the linker messages as that may reduce by a lot iteration time. Example:
134+
135+
```
136+
hipreme_engine.obj : error LNK2001: unresolved external symbol _D3hip3api12__ModuleInfoZ
137+
C:\Users\Hipreme\AppData\Local\.dub\.redub\1AB9D53797DC3516\1AB9D53797DC3516\hipreme_engine.exe : fatal error LNK1120: 1 unresolved external symbol
138+
Error: C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\link.exe failed
139+
with status: 1120
140+
```
141+
This gets one additional message
142+
143+
```
144+
Redub Help Message: Module hip.api is imported by:
145+
hip.view.load_scene (C:\Users\Hipreme\Documents\D\HipremeEngine\source\hip\view\load_scene.d)
146+
```
147+
148+
## Redub Cross Compile
149+
- **1.30.0**: Added cross compilation definition support via the `--target` flag.
150+
151+
Ever wanted to configure a default compiler/arch based on the configuration? Now you can (mostly). This is an example on how a `target` will look in your recipe JSON:
152+
153+
```json
154+
{
155+
"name": "my-project",
156+
"targets": {
157+
"wasm": {
158+
"compiler": "ldc2",
159+
"arch": "wasm32-unknown-unknown-wasm"
160+
},
161+
"PSVita": {
162+
"compiler": "ldc2",
163+
"arch": "armv7a-unknown-unknown-eabi",
164+
"dflags": [
165+
"--revert=dtorfields",
166+
"-mcpu=cortex-a9",
167+
"-mattr=+neon,+neonfp,+thumb-mode",
168+
"-fvisibility=hidden",
169+
"-gcc=$VITASDK/bin/arm-vita-eabi-gcc",
170+
"--relocation-model=static"
171+
],
172+
"versions": ["PSVita"],
173+
"dependencies": {
174+
"custom-rt": {"path": "my/custom/runtime"}
175+
}
176+
}
177+
}
178+
}
179+
```
180+
Now you can just call `redub --target=wasm` or `redub --target=PSVita` and every dependency will inherit this configuration.
181+
126182
## Multi language
127183

128184
Redub has also an experimental support for building and linking C/C++ code together with D code. For that, you need to define a dub.json:

dub.selections.json

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
{
22
"fileVersion": 1,
33
"versions": {
4-
"adv_diff": {"path": "adv_diff"},
5-
"hipjson": "1.1.2",
4+
"adv_diff": {"path":"adv_diff"},
5+
"arsd-official": "12.1.2",
6+
"asdf": "0.7.17",
7+
"colorize": {"path":"colorize"},
68
"d-segmented-hashmap": "1.1.0",
7-
"murmurhash-d": "1.0.0",
9+
"d_dependencies": {"path":"d_dependencies"},
10+
"d_downloader": {"path":"d_downloader"},
11+
"dub_sdl_to_json": {"path":"dub_sdl_to_json"},
12+
"fswatch": "0.6.1",
13+
"hipjson": "1.1.2",
814
"intel-intrinsics": "1.14.7",
9-
"arsd-official": "12.1.2",
10-
"colorize": {"path": "colorize"},
11-
"d_dependencies": {"path": "d_dependencies"},
12-
"d_downloader": {"path": "d_downloader"},
13-
"dub_sdl_to_json": {"path": "dub_sdl_to_json"},
15+
"iopipe": "0.2.5",
16+
"jsoniopipe": "0.1.4",
17+
"mir-algorithm": "3.22.4",
18+
"mir-core": "1.7.4",
19+
"mir-cpuid": "1.2.11",
20+
"mir-ion": "2.3.5",
21+
"murmurhash-d": "1.0.0",
22+
"package_suppliers": {"path":"package_suppliers"},
1423
"sdlite": "1.3.4",
24+
"semver": {"path":"semver"},
25+
"silly": "1.1.1",
1526
"taggedalgebraic": "1.0.1",
16-
"fswatch": "0.6.1",
17-
"package_suppliers": {"path": "package_suppliers"},
18-
"semver": {"path": "semver"},
1927
"xxhash3": "0.0.5"
2028
}
21-
}
29+
}

source/redub/api.d

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct ArgsDetails
132132
ProjectToParse proj;
133133
InitialDubVariables dubVars;
134134
string buildType;
135+
string target;
135136

136137
ResolveInfo resolveInfo() const { return ResolveInfo.fromArgs(this); }
137138
}
@@ -741,7 +742,7 @@ ArgsDetails resolveArguments(string[] args, bool isDescribeOnly = false)
741742
CompilationDetails(bArgs.compiler, bArgs.cCompiler, bArgs.arch, bArgs.compilerAssumption, bArgs.build.incremental, bArgs.build.useExistingObj, bArgs.build.combined, bArgs.build.parallel),
742743
ProjectToParse(bArgs.config, workingDir, subPackage, recipe, bArgs.single.length != 0, isDescribeOnly),
743744
getInitialDubVariablesFromArguments(bArgs, DubBuildArguments.init, os, args),
744-
bt
745+
bt, bArgs.target
745746
);
746747
}
747748

@@ -761,7 +762,8 @@ ProjectDetails resolveDependencies(
761762
CompilationDetails cDetails = CompilationDetails.init,
762763
ProjectToParse proj = ProjectToParse.init,
763764
InitialDubVariables dubVars = InitialDubVariables.init,
764-
string buildType = BuildType.debug_
765+
string buildType = BuildType.debug_,
766+
string target = null
765767
)
766768
{
767769
import std.datetime.stopwatch;
@@ -799,35 +801,40 @@ ProjectDetails resolveDependencies(
799801
proj.workingDir = std.file.getcwd;
800802
}
801803

802-
BuildRequirements req;
804+
RootParseResult res;
803805
if(proj.isSingle)
804-
req = redub.parsers.single.parseProject(
806+
res = redub.parsers.single.parseProject(
805807
proj.workingDir,
806808
cInfo,
807809
BuildRequirements.Configuration(proj.configuration, false),
808810
proj.subPackage,
809811
proj.recipe,
812+
target,
810813
cDetails.useExistingObj
811814
);
812815
else
813-
req = redub.parsers.automatic.parseProject(
816+
res = redub.parsers.automatic.parseProject(
814817
proj.workingDir,
815818
cInfo,
816819
BuildRequirements.Configuration(proj.configuration, false),
817820
proj.subPackage,
818821
proj.recipe,
822+
target,
819823
cDetails.useExistingObj,
820824
proj.isDescribeOnly
821825
);
826+
827+
///Change the compiler to use the possibly new cInfo.compiler
828+
compiler = res.targetCompilationInfo.compilers;
822829

823-
CompilerBinary cBin = req.cfg.getCompiler(compiler);
824-
redub.parsers.environment.setupEnvironmentVariablesForRootPackage(req);
830+
CompilerBinary cBin = res.mainRequirement.cfg.getCompiler(compiler);
831+
redub.parsers.environment.setupEnvironmentVariablesForRootPackage(res.mainRequirement);
825832
if(cDetails.includeEnvironmentVariables)
826-
req.cfg = req.cfg.merge(redub.parsers.environment.parse());
833+
res.mainRequirement.cfg = res.mainRequirement.cfg.merge(redub.parsers.environment.parse());
827834

828-
req.cfg = req.cfg.merge(redub.parsers.build_type.parse(buildType, cBin));
835+
res.mainRequirement.cfg = res.mainRequirement.cfg.merge(redub.parsers.build_type.parse(buildType, cBin));
829836

830-
ProjectNode tree = getProjectTree(req, cInfo);
837+
ProjectNode tree = getProjectTree(res);
831838

832839
if(cDetails.combinedBuild)
833840
tree.combine();

source/redub/buildapi.d

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import redub.package_searching.api;
77

88

99
///vX.X.X
10-
enum RedubVersionOnly = "v1.29.2";
10+
enum RedubVersionOnly = "v1.30.0";
1111
///Redub vX.X.X
1212
enum RedubVersionShort = "Redub "~RedubVersionOnly;
1313
///Redub vX.X.X - Description
@@ -59,6 +59,29 @@ struct CompilingSession
5959
}
6060
}
6161

62+
struct CompilationInfo
63+
{
64+
Compiler compilers;
65+
string compiler() const {return compilers.d.getCompilerString; }
66+
string c_compiler() const {return compilers.c.getCompilerString; }
67+
string binPath() const {return compilers.d.bin; }
68+
///Where the actual compiler is. Used for plugin building
69+
string arch;
70+
71+
OS targetOS() const
72+
{
73+
import redub.command_generators.commons;
74+
return osFromArch(arch);
75+
}
76+
///Target Instruction Set Architecture
77+
ISA isa() const
78+
{
79+
import redub.command_generators.commons;
80+
return isaFromArch(arch);
81+
}
82+
}
83+
84+
6285
enum BundleCategories : string
6386
{
6487
audioVideo = "AudioVideo",
@@ -736,6 +759,13 @@ string getVisibilityString(Visibility vis)
736759
}
737760
}
738761

762+
struct RootParseResult
763+
{
764+
BuildRequirements mainRequirement;
765+
BuildRequirements targetRequirement;
766+
CompilationInfo targetCompilationInfo;
767+
}
768+
739769
struct Dependency
740770
{
741771
string name;
@@ -966,8 +996,10 @@ class ProjectNode
966996
);
967997
}
968998

969-
this(BuildRequirements req, bool isOptional)
999+
this(BuildRequirements req, bool isOptional, BuildRequirements targetRequirement)
9701000
{
1001+
if(targetRequirement != BuildRequirements.init)
1002+
req = req.merge(targetRequirement);
9711003
this.requirements = req;
9721004
this._isOptional = isOptional;
9731005
}

source/redub/cli/dub.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ struct DubArguments
218218

219219
@("If a dub.selections.json is present, all non-path based packages are prefetched. Best for action runners.")
220220
bool prefetch;
221+
222+
@("Set which target to build. target json example definition: \"targets\": {\"windmd\": {\"compiler\": \"dmd\"}}")
223+
string target;
221224
}
222225

223226

source/redub/extensions/cli.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ ProjectDetails resolveDependencies(string[] args, bool isDescribeOnly = false)
2424
argsD.cDetails,
2525
argsD.proj,
2626
argsD.dubVars,
27-
argsD.buildType
27+
argsD.buildType,
28+
argsD.target
2829
);
2930

3031
if(argsD.args.targetPath)

source/redub/parsers/automatic.d

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ import hip.data.json;
2424
* isDescribeOnly = Do not execute preGenerate commands when true
2525
* Returns: The build requirements to the project. Not recursive.
2626
*/
27-
BuildRequirements parseProject(
27+
RootParseResult parseProject(
2828
string projectWorkingDir,
2929
ref CompilationInfo cInfo,
3030
BuildRequirements.Configuration subConfiguration,
3131
string subPackage,
3232
string recipe,
33+
string target,
3334
bool useExistingObj = false,
3435
bool isDescribeOnly = false
3536
)
@@ -56,7 +57,7 @@ BuildRequirements parseProject(
5657
}
5758

5859
JSONValue projectJSON = getProjectJSON(projectFile, projectWorkingDir);
59-
return parseProject(projectJSON, projectWorkingDir, cInfo, subConfiguration, subPackage, useExistingObj, isDescribeOnly);
60+
return parseProject(projectJSON, projectWorkingDir, cInfo, subConfiguration, subPackage, target, useExistingObj, isDescribeOnly);
6061
}
6162

6263
/**
@@ -73,25 +74,37 @@ BuildRequirements parseProject(
7374
* isDescribeOnly = Do not execute preGenerate commands when true
7475
* Returns: The build requirements to the project. Not recursive.
7576
*/
76-
BuildRequirements parseProject(
77+
RootParseResult parseProject(
7778
JSONValue projectJSON,
7879
string projectWorkingDir,
79-
ref CompilationInfo cInfo,
80+
CompilationInfo cInfo,
8081
BuildRequirements.Configuration subConfiguration,
8182
string subPackage,
83+
string target,
8284
bool useExistingObj = false,
8385
bool isDescribeOnly = false
8486
)
8587
{
8688
import redub.parsers.base;
8789

90+
RootParseResult result;
91+
8892
ParseConfig cfg = getParseConfig(projectWorkingDir, cInfo, null, null, subConfiguration, subPackage, null, isDescribeOnly);
89-
//Get target
9093

91-
// cfg = redub.parsers.json.getTarget(projectJSON, null, cfg);
94+
if(target.length)
95+
{
96+
import redub.parsers.json;
97+
TargetInfo targetInfo = redub.parsers.json.getTarget(projectJSON, target, cfg);
98+
cfg = targetInfo.parseConfig;
99+
cInfo = cfg.cInfo;
100+
result.targetRequirement = postProcessBuildRequirements(targetInfo.targetRequirement, targetInfo.pending, cInfo, false, useExistingObj);
101+
}
102+
result.targetCompilationInfo = cInfo;
92103
BuildConfiguration pending;
93-
BuildRequirements req = redub.parsers.json.parse(projectJSON, cfg, pending, true);
94-
return postProcessBuildRequirements(req, pending, cInfo, true, useExistingObj);
104+
result.mainRequirement = redub.parsers.json.parse(projectJSON, cfg, pending, true);
105+
result.mainRequirement= postProcessBuildRequirements(result.mainRequirement, pending, cInfo, true, useExistingObj);
106+
107+
return result;
95108
}
96109

97110

source/redub/parsers/json.d

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import std.file;
88
import redub.command_generators.commons;
99
import core.runtime;
1010
import redub.tree_generators.dub;
11+
import core.stdcpp.type_traits;
1112

1213
/**
1314
* Those commands are independent of the selected target OS.
@@ -27,8 +28,22 @@ string getPackageName(JSONValue packageJSON)
2728
return packageJSON["name"].str;
2829
}
2930

31+
struct TargetInfo
32+
{
33+
ParseConfig parseConfig;
34+
BuildConfiguration pending;
35+
BuildRequirements targetRequirement;
36+
}
3037

31-
ParseConfig getTarget(JSONValue value, string target, ParseConfig cfg)
38+
/**
39+
* Gets target information from the place setup. Used mostly for crosscompilation, auto compiler/arch setup.
40+
* Params:
41+
* value = The "targets" JSONValue
42+
* target = The actual target to get
43+
* cfg = Base ParseConfig containing compiler/arch. Might be unused
44+
* Returns: TargetInfo with the pending buildconfiguration, a new valid parseConfig to use instead of the `cfg` argument and the targetRequirement
45+
*/
46+
TargetInfo getTarget(JSONValue value, string target, ParseConfig cfg)
3247
{
3348
JSONValue* targets = "targets" in value;
3449
if(targets is null)
@@ -42,11 +57,18 @@ ParseConfig getTarget(JSONValue value, string target, ParseConfig cfg)
4257
availableTargets~= "\n\t"~key;
4358
throw new Exception(availableTargets);
4459
}
45-
ParseConfig ret = cfg;
46-
// ret.cInfo.
47-
48-
49-
return cfg;
60+
TargetInfo ret;
61+
ret.parseConfig = cfg;
62+
63+
string compiler = tryGetStr(*actualTarget, "compiler");
64+
string arch = tryGetStr(*actualTarget, "arch");
65+
if(compiler) ret.parseConfig.cInfo.compilers = getCompiler(compiler);
66+
if(arch) ret.parseConfig.cInfo.arch = arch;
67+
68+
///This line is necessary as it errors if no requiredBy is pressent and no name is present.
69+
cfg.extra.requiredBy = target;
70+
ret.targetRequirement = parse(*actualTarget, cfg, ret.pending, false);
71+
return ret;
5072
}
5173

5274

0 commit comments

Comments
 (0)