Skip to content

Commit 868d2e2

Browse files
committed
Initial waf integration. Add integration tests. Improve cmake integration.
1 parent b6bc89b commit 868d2e2

7 files changed

Lines changed: 244 additions & 7 deletions

File tree

src/sw/client/inserts/SWConfig.cmake

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,29 @@ set(SW_DEPS_FILE ${SW_DEPS_DIR}/sw.txt CACHE STRING "SW local deps file.")
1313

1414
file(WRITE ${SW_DEPS_FILE} "")
1515

16+
########################################
17+
# FUNCTION find_flag
18+
########################################
19+
20+
function(find_flag in_flags f out)
21+
if (NOT "${${out}}" STREQUAL "")
22+
return()
23+
endif()
24+
if ("${in_flags}" STREQUAL "")
25+
set(${out} 0 PARENT_SCOPE)
26+
return()
27+
endif()
28+
set(flags ${in_flags})
29+
string(TOLOWER ${f} f)
30+
string(TOLOWER ${flags} flags)
31+
string(FIND "${flags}" "${f}" flags)
32+
if (NOT ${flags} EQUAL -1)
33+
set(${out} 1 PARENT_SCOPE)
34+
else()
35+
set(${out} 0 PARENT_SCOPE)
36+
endif()
37+
endfunction(find_flag)
38+
1639
########################################
1740
# FUNCTION sw_add_dependency
1841
########################################
@@ -46,9 +69,27 @@ function(sw_execute)
4669
set(platform x86)
4770
endif()
4871

72+
set(mt_flag)
73+
if (MSVC)
74+
find_flag("${CMAKE_C_FLAGS_RELEASE}" /MT C_MTR )
75+
find_flag("${CMAKE_C_FLAGS_RELWITHDEBINFO}" /MT C_MTRWDI )
76+
find_flag("${CMAKE_C_FLAGS_MINSIZEREL}" /MT C_MTMSR )
77+
find_flag("${CMAKE_C_FLAGS_DEBUG}" /MTd C_MTD )
78+
find_flag("${CMAKE_CXX_FLAGS_RELEASE}" /MT CXX_MTR )
79+
find_flag("${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" /MT CXX_MTRWDI )
80+
find_flag("${CMAKE_CXX_FLAGS_MINSIZEREL}" /MT CXX_MTMSR )
81+
find_flag("${CMAKE_CXX_FLAGS_DEBUG}" /MTd CXX_MTD )
82+
83+
if ( C_MTR OR C_MTRWDI OR C_MTMSR OR C_MTD OR
84+
CXX_MTR OR CXX_MTRWDI OR CXX_MTMSR OR CXX_MTD)
85+
set(mt_flag -mt)
86+
endif()
87+
endif()
88+
4989
set(sw_platform_args
5090
${stsh}
5191
-platform ${platform}
92+
${mt_flag}
5293
#-compiler msvc
5394
)
5495

@@ -86,6 +127,7 @@ function(sw_execute)
86127
COMMAND
87128
sw
88129
${sw_platform_args}
130+
-d "${SW_DEPS_DIR}"
89131
-config
90132
$<$<CONFIG:Debug>:d>
91133
$<$<CONFIG:MinSizeRel>:msr>
Lines changed: 122 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <sw/driver/target/native.h>
77

88
static ::cl::opt<path> integrate_cmake_deps("cmake-deps", ::cl::sub(subcommand_integrate));
9+
static ::cl::opt<path> integrate_waf_deps("waf-deps", ::cl::sub(subcommand_integrate));
910

1011
struct CMakeEmitter : primitives::Emitter
1112
{
@@ -80,12 +81,14 @@ SUBCOMMAND_DECL(integrate)
8081
ctx.addLine("# sw autogenerated file");
8182
ctx.addLine("#");
8283
ctx.emptyLines();
84+
85+
// targets
86+
ctx.addLine("# targets");
8387
for (auto &s : b.solutions)
8488
{
8589
for (auto &[pkg, t] : s.getChildren())
8690
{
8791
auto &nt = *t->as<sw::NativeExecutedTarget>();
88-
8992
if (t->getType() == sw::TargetType::NativeExecutable)
9093
continue;
9194

@@ -158,8 +161,13 @@ SUBCOMMAND_DECL(integrate)
158161
// props2
159162
ctx.increaseIndent("set_target_properties(" + pkg.toString() + " PROPERTIES");
160163

161-
ctx.addLine("IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG \"CXX\"");
162-
ctx.addLine("IMPORTED_LOCATION_" + toCmakeString(s.Settings.Native.ConfigurationType) + " \"" + normalize_path(nt.getImportLibrary()) + "\"");
164+
// TODO: detect C/CXX language from target files
165+
ctx.addLine("IMPORTED_LINK_INTERFACE_LANGUAGES_" + toCmakeString(s.Settings.Native.ConfigurationType) + " \"CXX\"");
166+
167+
// IMPORTED_LOCATION = path to .dll/.so or static .lib/.a
168+
ctx.addLine("IMPORTED_LOCATION_" + toCmakeString(s.Settings.Native.ConfigurationType) + " \"" + normalize_path(nt.getOutputFile()) + "\"");
169+
// IMPORTED_IMPLIB = path to .lib (import)
170+
ctx.addLine("IMPORTED_IMPLIB_" + toCmakeString(s.Settings.Native.ConfigurationType) + " \"" + normalize_path(nt.getImportLibrary()) + "\"");
163171

164172
ctx.decreaseIndent(")");
165173
ctx.emptyLines();
@@ -184,13 +192,14 @@ SUBCOMMAND_DECL(integrate)
184192
}
185193
break;
186194
}
195+
187196
// deps
197+
ctx.addLine("# dependencies");
188198
for (auto &s : b.solutions)
189199
{
190200
for (auto &[pkg, t] : s.getChildren())
191201
{
192202
auto &nt = *t->as<sw::NativeExecutedTarget>();
193-
194203
if (t->getType() == sw::TargetType::NativeExecutable)
195204
continue;
196205

@@ -200,5 +209,114 @@ SUBCOMMAND_DECL(integrate)
200209
break;
201210
}
202211
write_file_if_different(integrate_cmake_deps.parent_path() / "CMakeLists.txt", ctx.getText());
212+
213+
return;
214+
}
215+
216+
if (!integrate_waf_deps.empty())
217+
{
218+
auto lines = read_lines(integrate_waf_deps);
219+
220+
auto swctx = createSwContext();
221+
sw::Build b(swctx);
222+
b.Local = false;
223+
b.load_packages(StringSet(lines.begin(), lines.end()));
224+
b.prepare(); // or step?
225+
226+
// https://waf.io/apidocs/_modules/waflib/Tools/c_config.html#parse_flags
227+
primitives::Emitter ctx;
228+
229+
ctx.increaseIndent("def configure(ctx):");
230+
231+
for (auto &s : b.solutions)
232+
{
233+
for (auto &[pkg, t] : s.getChildren())
234+
{
235+
auto &nt = *t->as<sw::NativeExecutedTarget>();
236+
if (t->getType() == sw::TargetType::NativeExecutable)
237+
continue;
238+
239+
ctx.addLine("# " + pkg.toString());
240+
ctx.increaseIndent("for lib in [");
241+
for (auto i = pkg.version.getLevel(); i >= 0; i--)
242+
{
243+
if (i)
244+
ctx.addLine("'" + pkg.ppath.toString() + "-" + pkg.version.toString(i) + "',");
245+
else
246+
ctx.addLine("'" + pkg.ppath.toString() + "',");
247+
}
248+
ctx.decreaseIndent("]:");
249+
ctx.increaseIndent();
250+
251+
auto remove_ext = [](const auto &p)
252+
{
253+
return p.parent_path() / p.stem();
254+
};
255+
256+
ctx.addLine("ctx.parse_flags('-l" + normalize_path(remove_ext(nt.getImportLibrary())) + "', lib)");
257+
258+
std::function<void(sw::NativeExecutedTarget&)> process;
259+
std::unordered_set<sw::NativeExecutedTarget *> visited;
260+
process = [&process, &s, &ctx, &remove_ext, &visited](auto &nt)
261+
{
262+
if (visited.find(&nt) != visited.end())
263+
return;
264+
visited.insert(&nt);
265+
266+
// defs
267+
for (auto &[k,v] : nt.Public.Definitions)
268+
{
269+
if (v.empty())
270+
ctx.addLine("ctx.parse_flags('-D" + k + "', lib)");
271+
else
272+
ctx.addLine("ctx.parse_flags('-D" + k + "=" + v.toString() + "', lib)");
273+
}
274+
for (auto &[k,v] : nt.Interface.Definitions)
275+
{
276+
if (v.empty())
277+
ctx.addLine("ctx.parse_flags('-D" + k + "', lib)");
278+
else
279+
ctx.addLine("ctx.parse_flags('-D" + k + "=" + v.toString() + "', lib)");
280+
}
281+
282+
// idirs
283+
for (auto &d : nt.Public.IncludeDirectories)
284+
ctx.addLine("ctx.parse_flags('-I" + normalize_path(d) + "', lib)");
285+
for (auto &d : nt.Interface.IncludeDirectories)
286+
ctx.addLine("ctx.parse_flags('-I" + normalize_path(d) + "', lib)");
287+
288+
// libs
289+
for (auto &d : nt.Public.LinkLibraries)
290+
ctx.addLine("ctx.parse_flags('-l" + normalize_path(remove_ext(d)) + "', lib)");
291+
for (auto &d : nt.Interface.LinkLibraries)
292+
ctx.addLine("ctx.parse_flags('-l" + normalize_path(remove_ext(d)) + "', lib)");
293+
294+
// deps
295+
for (auto &d : nt.Dependencies)
296+
{
297+
auto t = s.children[d->getResolvedPackage()];
298+
if (t->getType() == sw::TargetType::NativeExecutable)
299+
continue;
300+
301+
auto &nt = *s.getChildren().find(d->getResolvedPackage())->second->as<sw::NativeExecutedTarget>();
302+
ctx.addLine("ctx.parse_flags('-l" + normalize_path(remove_ext(nt.getImportLibrary())) + "', lib)");
303+
304+
process(nt);
305+
}
306+
};
307+
process(nt);
308+
309+
ctx.decreaseIndent();
310+
ctx.emptyLines();
311+
//
312+
}
313+
break;
314+
}
315+
316+
write_file_if_different("wscript", ctx.getText());
317+
318+
return;
203319
}
320+
321+
SW_UNIMPLEMENTED;
204322
}

src/sw/driver/solution_build.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,11 +1609,11 @@ void Build::build_packages(const StringSet &pkgs)
16091609
// at the moment we have one solution here
16101610
Files files;
16111611
Commands cmds;
1612-
for (auto &p : pkgs)
1612+
for (auto &[u, p] : pkgs2)
16131613
{
1614-
auto i = solutions[0].children.find(pkgs2.find(p)->second);
1614+
auto i = solutions[0].children.find(p);
16151615
if (i == solutions[0].children.end())
1616-
throw SW_RUNTIME_ERROR("No such target in fast path: " + p);
1616+
throw SW_RUNTIME_ERROR("No such target in fast path: " + p.toString());
16171617
if (auto nt = i->second->as<NativeExecutedTarget>())
16181618
{
16191619
if (auto c = nt->getCommand())

test/integrations/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
cmake_minimum_required(VERSION 3.14)
2+
3+
# Use solution folders.
4+
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
5+
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake Targets")
6+
7+
project(my C CXX)
8+
9+
set(SW_BUILD_SHARED_LIBS 1)
10+
find_package(SW REQUIRED)
11+
sw_add_package(
12+
org.sw.demo.sqlite3
13+
org.sw.demo.glennrp.png
14+
)
15+
sw_execute()
16+
17+
add_executable(png png.cpp)
18+
target_link_libraries(png
19+
org.sw.demo.glennrp.png
20+
)
21+
22+
add_executable(sqlite3 sqlite3.cpp)
23+
target_link_libraries(sqlite3
24+
org.sw.demo.sqlite3
25+
)

test/integrations/png.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <png.h>
2+
#include <zlib.h>
3+
4+
int main()
5+
{
6+
png_access_version_number();
7+
zlibVersion();
8+
return 0;
9+
}

test/integrations/sqlite3.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <sqlite3.h>
2+
3+
int main()
4+
{
5+
sqlite3_libversion();
6+
return 0;
7+
}

test/integrations/wscript

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
top = '.'
2+
out = 'build_waf'
3+
4+
import subprocess
5+
swdir = out + '/.sw'
6+
swdeps = swdir + '/deps.txt'
7+
def sw_configure(ctx):
8+
deps = [
9+
'org.sw.demo.sqlite3',
10+
'org.sw.demo.glennrp.png',
11+
]
12+
13+
f = open(swdeps, 'w')
14+
for d in deps:
15+
f.write(d + '\n')
16+
f.close()
17+
p = subprocess.Popen(['sw', '-mt', '-d', swdir, 'integrate', '-waf-deps', 'deps.txt'])
18+
if p.wait():
19+
ctx.fatal("Error during sw call")
20+
21+
def sw_build(ctx):
22+
p = subprocess.Popen(['sw', '-mt', '-d', swdir, 'build', '@' + swdeps,
23+
'-ide-copy-to-dir', '..', '-ide-fast-path', 'fp.txt'])
24+
if p.wait():
25+
ctx.fatal("Error during sw call")
26+
27+
def options(opt):
28+
opt.load('compiler_cxx')
29+
30+
def configure(ctx):
31+
ctx.load('compiler_cxx')
32+
ctx.recurse(swdir)
33+
34+
def build(bld):
35+
bld.program(source='sqlite3.cpp', target='sqlite3', use='org.sw.demo.sqlite3')
36+
bld.program(source='png.cpp', target='png', use='org.sw.demo.glennrp.png')

0 commit comments

Comments
 (0)