Skip to content

Commit 543e189

Browse files
Adding cross platform defines
1 parent 76fa887 commit 543e189

File tree

10 files changed

+213
-0
lines changed

10 files changed

+213
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ add_executable(runcpp2
8484
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/ProfilesCompilesFiles.cpp"
8585
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/FilesTypesInfo.cpp"
8686
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/StageInfo.cpp"
87+
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/ProfilesDefines.cpp"
8788
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/ProfileHelper.cpp"
8889
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/CompilingLinking.cpp"
8990
"${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/ConfigParsing.cpp"

DefaultYAMLs/DefaultScriptInfo.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# NOTE: All command substitutions are passed directly to the shell.
2+
# Be cautious when using user-provided input in your build commands to avoid potential security risks.
3+
14
# NOTE: All the options here are defaulted to empty.
25
# You can uncomment different sections to set what you want.
36

@@ -52,6 +55,16 @@
5255
# All:
5356
# - "./AnotherSourceFile.cpp"
5457

58+
# # (Optional) Define cross-compiler defines for each platform and profile.
59+
# # Defines can be specified as just a name or as a name-value pair.
60+
# Defines:
61+
# # Target Platform (All, Windows, Linux, MacOS, or Unix)
62+
# All:
63+
# # Profile name (e.g., "g++", "clang++", "msvc", or "All" for any profile)
64+
# "All":
65+
# - "EXAMPLE_DEFINE" # Define without a value
66+
# - "VERSION_MAJOR=1" # Define with a value
67+
5568
# # (Optional) The list of dependencies needed by the script
5669
# Dependencies:
5770
# # Dependency name

DefaultYAMLs/DefaultUserConfig.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Templates:
66
"g++_CompileRunParts": &g++_CompileRunParts
77
- Type: Once
88
CommandPart: "{Executable} -c {CompileFlags}"
9+
- Type: Repeats
10+
CommandPart: " -D{DefineNameOnly}="
11+
- Type: Repeats
12+
CommandPart: " \"-D{DefineName}={DefineValue}\""
913
- Type: Repeats
1014
CommandPart: " -I\"{IncludeDirectoryPath}\""
1115
- Type: Once
@@ -20,6 +24,10 @@ Templates:
2024
"vs2022_v17+_CompileRunParts": &vs2022_v17+_CompileRunParts
2125
- Type: Once
2226
CommandPart: "{Executable} /c {CompileFlags}"
27+
- Type: Repeats
28+
CommandPart: " /D{DefineNameOnly}="
29+
- Type: Repeats
30+
CommandPart: " \"/D{DefineName}={DefineValue}\""
2331
- Type: Repeats
2432
CommandPart: " /I\"{IncludeDirectoryPath}\""
2533
- Type: Once
@@ -91,6 +99,10 @@ Templates:
9199
Windows: ""
92100
Unix: ""
93101

102+
# WARNING: All command substitutions in this file are passed directly to the shell.
103+
# Exercise caution when using variables or user-provided input in your build commands
104+
# to prevent potential security vulnerabilities.
105+
94106
# A profile to be used if not specified while running the build script
95107
PreferredProfile: "g++"
96108

@@ -136,6 +148,9 @@ Profiles:
136148
# {Executable}: Compiler executable
137149
# {CompileFlags}: Compile flags from config and override
138150
# {IncludeDirectoryPath}: Path to include directories for both the script and dependencies
151+
# {DefineNameOnly}: Name of a macro to be defined without a value (equivalent to #define X)
152+
# {DefineName}: Name of a macro to be defined with a value
153+
# {DefineValue}: Value of a macro to be defined (used with {DefineName})
139154

140155
# {InputFileName}: Name of the input file (without directory path and extension)
141156
# {InputFileExtension}: Extension of the input file

Examples/test.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
- "./AnotherSourceFile.cpp"
1515
- "./AnotherSourceFile2.cpp"
1616
17+
Defines:
18+
All:
19+
# Turns into `TEST_DEF=\"Test Define Working\"` in shell
20+
"All": ["TEST_DEF=\\\"Test Define Working\\\""]
21+
1722
Dependencies:
1823
- Name: ssLogger
1924
Platforms: [Windows, Linux, MacOS]
@@ -52,6 +57,7 @@
5257
int main(int argc, char* argv[])
5358
{
5459
std::cout << "Hello World" << std::endl;
60+
std::cout << TEST_DEF << std::endl;
5561

5662
for(int i = 0; i < argc; ++i)
5763
std::cout << "Arg" << i << ": " << argv[i] << std::endl;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef RUNCPP2_DATA_PROFILES_DEFINES_HPP
2+
#define RUNCPP2_DATA_PROFILES_DEFINES_HPP
3+
4+
#include "runcpp2/Data/ParseCommon.hpp"
5+
#include "ryml.hpp"
6+
#include <unordered_map>
7+
#include <vector>
8+
#include <string>
9+
10+
namespace runcpp2
11+
{
12+
namespace Data
13+
{
14+
struct Define
15+
{
16+
std::string Name;
17+
std::string Value;
18+
bool HasValue;
19+
};
20+
21+
class ProfilesDefines
22+
{
23+
public:
24+
std::unordered_map<ProfileName, std::vector<Define>> Defines;
25+
26+
bool ParseYAML_Node(ryml::ConstNodeRef& node);
27+
std::string ToString(std::string indentation) const;
28+
};
29+
}
30+
}
31+
32+
#endif

Include/runcpp2/Data/ScriptInfo.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "runcpp2/Data/ProfilesFlagsOverride.hpp"
66
#include "runcpp2/Data/ParseCommon.hpp"
77
#include "runcpp2/Data/ProfilesCompilesFiles.hpp"
8+
#include "runcpp2/Data/ProfilesDefines.hpp"
89

910
#include <string>
1011
#include <vector>
@@ -27,6 +28,7 @@ namespace runcpp2
2728

2829
std::vector<DependencyInfo> Dependencies;
2930

31+
std::unordered_map<PlatformName, ProfilesDefines> Defines;
3032

3133
bool Populated = false;
3234

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ Everything is documented as comment in the template but here's a quick summary.
7171
- `OtherFilesToBeCompiled`: Other source files you wish to be compiled.
7272
- `Dependencies`: Any external libraries you wish to use. See next section.
7373

74+
> [!NOTE]
75+
> Settings in the script info are passed directly to the shell. Be cautious when using user-provided input in your build commands.
76+
7477
#### 4. Using External Libraries
7578

7679
To use any external libraries, you need to specify them in the Dependencies section.

Src/runcpp2/CompilingLinking.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,44 @@ namespace
126126
}
127127
}
128128

129+
// Add defines
130+
if(runcpp2::HasValueFromPlatformMap(scriptInfo.Defines))
131+
{
132+
const runcpp2::Data::ProfilesDefines& platformDefines =
133+
*runcpp2::GetValueFromPlatformMap(scriptInfo.Defines);
134+
135+
std::vector<std::string> profileNames;
136+
profile.GetNames(profileNames);
137+
138+
std::string validProfileName;
139+
for(int i = 0; i < profileNames.size(); ++i)
140+
{
141+
if(platformDefines.Defines.count(profileNames[i]) > 0)
142+
{
143+
validProfileName = profileNames.at(i);
144+
break;
145+
}
146+
}
147+
148+
if(!validProfileName.empty())
149+
{
150+
const std::vector<runcpp2::Data::Define>& profileDefines =
151+
platformDefines.Defines.at(validProfileName);
152+
153+
for(int i = 0; i < profileDefines.size(); ++i)
154+
{
155+
const runcpp2::Data::Define& define = profileDefines.at(i);
156+
if(define.HasValue)
157+
{
158+
substitutionMapTemplate["{DefineName}"].push_back(define.Name);
159+
substitutionMapTemplate["{DefineValue}"].push_back(define.Value);
160+
}
161+
else
162+
substitutionMapTemplate["{DefineNameOnly}"].push_back(define.Name);
163+
}
164+
}
165+
}
166+
129167
std::unordered_map<std::string, std::vector<std::string>> substitutionMap;
130168
substitutionMap = substitutionMapTemplate;
131169

@@ -717,6 +755,7 @@ bool runcpp2::CompileAndLinkScript( const ghc::filesystem::path& buildDir,
717755
availableDependencies.at(i)->LinkProperties.end())
718756
{
719757
targetProfileName = currentProfileNames.at(j);
758+
break;
720759
}
721760
}
722761

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "runcpp2/Data/ProfilesDefines.hpp"
2+
#include "runcpp2/ParseUtil.hpp"
3+
#include "ssLogger/ssLog.hpp"
4+
#include <string>
5+
6+
bool runcpp2::Data::ProfilesDefines::ParseYAML_Node(ryml::ConstNodeRef& node)
7+
{
8+
ssLOG_FUNC_DEBUG();
9+
10+
INTERNAL_RUNCPP2_SAFE_START();
11+
12+
if(!node.is_map())
13+
{
14+
ssLOG_ERROR("ProfilesDefines: Not a map type");
15+
return false;
16+
}
17+
18+
for(int i = 0; i < node.num_children(); ++i)
19+
{
20+
if(!INTERNAL_RUNCPP2_BIT_CONTANTS(node[i].type().type, ryml::NodeType_e::SEQ))
21+
{
22+
ssLOG_ERROR("ProfilesDefines: Defines type requires a list");
23+
return false;
24+
}
25+
26+
ryml::ConstNodeRef currentProfileDefinesNode = node[i];
27+
ProfileName profile = GetKey(currentProfileDefinesNode);
28+
29+
for(int j = 0; j < currentProfileDefinesNode.num_children(); ++j)
30+
{
31+
std::string defineStr = GetValue(currentProfileDefinesNode[j]);
32+
Define define;
33+
34+
size_t equalPos = defineStr.find('=');
35+
if(equalPos != std::string::npos)
36+
{
37+
define.Name = defineStr.substr(0, equalPos);
38+
define.Value = defineStr.substr(equalPos + 1);
39+
define.HasValue = true;
40+
}
41+
else
42+
{
43+
define.Name = defineStr;
44+
define.Value = "";
45+
define.HasValue = false;
46+
}
47+
48+
Defines[profile].push_back(define);
49+
}
50+
}
51+
52+
return true;
53+
54+
INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false);
55+
}
56+
57+
std::string runcpp2::Data::ProfilesDefines::ToString(std::string indentation) const
58+
{
59+
std::string result;
60+
61+
for(const auto& profileDefines : Defines)
62+
{
63+
result += indentation + profileDefines.first + ":\n";
64+
for(const auto& define : profileDefines.second)
65+
{
66+
result += indentation + "- ";
67+
if(define.Value.empty())
68+
result += define.Name + "\n";
69+
else
70+
result += define.Name + "=" + define.Value + "\n";
71+
}
72+
}
73+
74+
return result;
75+
}

Src/runcpp2/Data/ScriptInfo.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ bool runcpp2::Data::ScriptInfo::ParseYAML_Node(ryml::ConstNodeRef& node)
1717
NodeRequirement("OverrideLinkFlags", ryml::NodeType_e::MAP, false, true),
1818
NodeRequirement("OtherFilesToBeCompiled", ryml::NodeType_e::MAP, false, true),
1919
NodeRequirement("Dependencies", ryml::NodeType_e::SEQ, false, true),
20+
NodeRequirement("Defines", ryml::NodeType_e::MAP, false, true)
2021
};
2122

2223
if(!CheckNodeRequirements(node, requirements))
@@ -120,6 +121,25 @@ bool runcpp2::Data::ScriptInfo::ParseYAML_Node(ryml::ConstNodeRef& node)
120121
}
121122
}
122123

124+
if(ExistAndHasChild(node, "Defines"))
125+
{
126+
ryml::ConstNodeRef definesNode = node["Defines"];
127+
128+
for(int i = 0; i < definesNode.num_children(); ++i)
129+
{
130+
PlatformName platform = GetKey(definesNode[i]);
131+
ProfilesDefines profilesDefines;
132+
ryml::ConstNodeRef currentDefinesNode = definesNode[i];
133+
134+
if(!profilesDefines.ParseYAML_Node(currentDefinesNode))
135+
{
136+
ssLOG_ERROR("ScriptInfo: Failed to parse Defines.");
137+
return false;
138+
}
139+
Defines[platform] = profilesDefines;
140+
}
141+
}
142+
123143
return true;
124144

125145
INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false);
@@ -166,5 +186,12 @@ std::string runcpp2::Data::ScriptInfo::ToString(std::string indentation) const
166186
for(int i = 0; i < Dependencies.size(); ++i)
167187
out += Dependencies[i].ToString(indentation + " ");
168188

189+
out += indentation + " Defines:\n";
190+
for(auto it = Defines.begin(); it != Defines.end(); ++it)
191+
{
192+
out += indentation + " " + it->first + ":\n";
193+
out += it->second.ToString(indentation + " ");
194+
}
195+
169196
return out;
170197
}

0 commit comments

Comments
 (0)