Skip to content

Commit 9cd1a5a

Browse files
committedAug 6, 2019
Merge #9: Invoke capnp compile from mpgen
f89e4b3 Invoke capnp compile from mpgen (Russell Yanofsky) Pull request description: This simplifies multiprocess build code somewhat (bitcoin/bitcoin#16367) so it only has to invoke one code generator instead of two, and is probably a little more future proof in that is should make it possible to change capnp options without any requiring changes outside libmultiprocess. Top commit has no ACKs. Tree-SHA512: 64534ec8d020eaf6a2dd351e4e48bf3a7a9897c126db1585c259950070b513aa9a416204e64ad1ab16717f41c534b9aafced4844039ed1f9037550946533445e
2 parents dee0711 + f89e4b3 commit 9cd1a5a

File tree

3 files changed

+105
-48
lines changed

3 files changed

+105
-48
lines changed
 

‎CMakeLists.txt

+10-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ capnp_generate_cpp(MP_PROXY_SRCS MP_PROXY_HDRS include/mp/proxy.capnp)
1212

1313
set(MP_PUBLIC_HEADERS
1414
${MP_PROXY_HDRS}
15-
include/mp/proxy.h
1615
include/mp/proxy-io.h
1716
include/mp/proxy-types.h
1817
include/mp/proxy.capnp
@@ -38,41 +37,40 @@ set_target_properties(multiprocess PROPERTIES
3837
install(TARGETS multiprocess EXPORT Multiprocess ARCHIVE DESTINATION lib PUBLIC_HEADER DESTINATION include/mp)
3938

4039
add_executable(mpgen src/mp/gen.cpp)
41-
target_include_directories(mpgen PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
40+
target_include_directories(mpgen PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>)
4241
target_include_directories(mpgen PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
4342
target_link_libraries(mpgen PRIVATE CapnProto::capnp-rpc)
4443
target_link_libraries(mpgen PRIVATE -L${capnp_LIBRARY_DIRS} capnpc)
44+
target_link_libraries(mpgen PRIVATE multiprocess)
4545
set_target_properties(mpgen PROPERTIES
4646
INSTALL_RPATH_USE_LINK_PATH TRUE
4747
CXX_STANDARD 14
4848
CXX_STANDARD_REQUIRED YES)
4949
install(TARGETS mpgen EXPORT Multiprocess RUNTIME DESTINATION bin)
5050

51-
configure_file(pkgconfig/libmultiprocess.pc.in "${CMAKE_CURRENT_BINARY_DIR}/libmultiprocess.pc" @ONLY)
52-
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libmultiprocess.pc" DESTINATION "lib/pkgconfig")
51+
configure_file(include/mp/config.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/mp/config.h")
52+
configure_file(pkgconfig/libmultiprocess.pc.in "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/libmultiprocess.pc" @ONLY)
53+
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/libmultiprocess.pc" DESTINATION "lib/pkgconfig")
5354

5455
install(EXPORT Multiprocess DESTINATION lib/cmake/Multiprocess)
5556

56-
set(CAPNPC_IMPORT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include")
57-
capnp_generate_cpp(FOO_PROXY_SRCS FOO_PROXY_HDRS src/mp/test/foo.capnp)
58-
59-
6057
if(BUILD_TESTING)
6158
add_custom_command(
6259
OUTPUT
60+
src/mp/test/foo.capnp.h
61+
src/mp/test/foo.capnp.c++
6362
src/mp/test/foo.capnp.proxy.h
6463
src/mp/test/foo.capnp.proxy-server.c++
6564
src/mp/test/foo.capnp.proxy-client.c++
6665
src/mp/test/foo.capnp.proxy-types.c++
6766
src/mp/test/foo.capnp.proxy-types.h
68-
PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory src/mp/test
69-
COMMAND ${CMAKE_COMMAND} -E chdir src "${CMAKE_CURRENT_BINARY_DIR}/mpgen" mp/test/foo "${CMAKE_CURRENT_SOURCE_DIR}/src/mp/test/foo.capnp" "${CMAKE_CURRENT_SOURCE_DIR}/include" "${capnp_PREFIX}/include"
67+
COMMAND mpgen "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/mp/test/foo.capnp" "${CMAKE_CURRENT_SOURCE_DIR}/include" "${capnp_PREFIX}/include"
7068
DEPENDS src/mp/test/foo.capnp mpgen
7169
)
7270
add_executable(mptest EXCLUDE_FROM_ALL
73-
${FOO_PROXY_HDRS}
74-
${FOO_PROXY_SRCS}
7571
${MP_PROXY_HDRS}
72+
src/mp/test/foo.capnp.h
73+
src/mp/test/foo.capnp.c++
7674
src/mp/test/foo.capnp.proxy.h
7775
src/mp/test/foo.capnp.proxy-server.c++
7876
src/mp/test/foo.capnp.proxy-client.c++

‎include/mp/config.h.in

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2019 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef MP_CONFIG_H
6+
#define MP_CONFIG_H
7+
8+
#cmakedefine capnp_PREFIX "@capnp_PREFIX@"
9+
10+
#endif // MP_CONFIG_H

‎src/mp/gen.cpp

+85-36
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <mp/config.h>
6+
#include <mp/util.h>
7+
58
#include <boost/optional.hpp>
69
#include <capnp/schema-parser.h>
710
#include <fstream>
@@ -66,49 +69,95 @@ bool BoxedType(const ::capnp::Type& type)
6669
type.isFloat64() || type.isEnum());
6770
}
6871

69-
void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPtr<const kj::StringPtr> import_paths)
72+
void Generate(kj::StringPtr src_prefix,
73+
kj::StringPtr include_prefix,
74+
kj::StringPtr src_file,
75+
kj::ArrayPtr<const kj::StringPtr> import_paths)
7076
{
77+
std::string output_path;
78+
if (src_prefix == ".") {
79+
output_path = src_file;
80+
} else if (!src_file.startsWith(src_prefix) || src_file.size() <= src_prefix.size() ||
81+
src_file[src_prefix.size()] != '/') {
82+
throw std::runtime_error("src_prefix is not src_file prefix");
83+
} else {
84+
output_path = src_file.slice(src_prefix.size() + 1);
85+
}
86+
87+
std::string include_path;
88+
if (include_prefix == ".") {
89+
include_path = src_file;
90+
} else if (!src_file.startsWith(include_prefix) || src_file.size() <= include_prefix.size() ||
91+
src_file[include_prefix.size()] != '/') {
92+
throw std::runtime_error("include_prefix is not src_file prefix");
93+
} else {
94+
include_path = src_file.slice(include_prefix.size() + 1);
95+
}
96+
97+
std::string include_base = include_path;
98+
std::string::size_type p = include_base.rfind(".");
99+
if (p != std::string::npos) include_base.erase(p);
100+
101+
std::vector<std::string> args;
102+
args.emplace_back(capnp_PREFIX "/bin/capnp");
103+
args.emplace_back("compile");
104+
args.emplace_back("--src-prefix=");
105+
args.back().append(src_prefix.cStr(), src_prefix.size());
106+
for (const auto& import_path : import_paths) {
107+
args.emplace_back("--import-path=");
108+
args.back().append(import_path.cStr(), import_path.size());
109+
}
110+
args.emplace_back("--output=" capnp_PREFIX "/bin/capnpc-c++");
111+
args.emplace_back(src_file);
112+
int pid = fork();
113+
if (!pid) {
114+
mp::ExecProcess(args);
115+
}
116+
int status = mp::WaitProcess(pid);
117+
if (status) {
118+
throw std::runtime_error("Invoking " capnp_PREFIX "/bin/capnp failed");
119+
}
120+
71121
capnp::SchemaParser parser;
72-
auto file_schema = parser.parseDiskFile(input_schema, input_schema, import_paths);
122+
auto file_schema = parser.parseDiskFile(src_file, src_file, import_paths);
73123

74-
const std::string stem = output_stem;
75-
std::ofstream cpp_server(stem + ".capnp.proxy-server.c++");
76-
cpp_server << "// Generated by " PROXY_BIN " from " << input_schema << "\n\n";
77-
cpp_server << "#include <" << stem << ".capnp.proxy-types.h>\n";
124+
std::ofstream cpp_server(output_path + ".proxy-server.c++");
125+
cpp_server << "// Generated by " PROXY_BIN " from " << src_file << "\n\n";
126+
cpp_server << "#include <" << include_path << ".proxy-types.h>\n";
78127
cpp_server << "#include <" << PROXY_TYPES << ">\n\n";
79128
cpp_server << "namespace mp {\n";
80129

81-
std::ofstream cpp_client(stem + ".capnp.proxy-client.c++");
82-
cpp_client << "// Generated by " PROXY_BIN " from " << input_schema << "\n\n";
83-
cpp_client << "#include <" << stem << ".capnp.proxy-types.h>\n";
130+
std::ofstream cpp_client(output_path + ".proxy-client.c++");
131+
cpp_client << "// Generated by " PROXY_BIN " from " << src_file << "\n\n";
132+
cpp_client << "#include <" << include_path << ".proxy-types.h>\n";
84133
cpp_client << "#include <" << PROXY_TYPES << ">\n\n";
85134
cpp_client << "namespace mp {\n";
86135

87-
std::ofstream cpp_types(stem + ".capnp.proxy-types.c++");
88-
cpp_types << "// Generated by " PROXY_BIN " from " << input_schema << "\n\n";
89-
cpp_types << "#include <" << stem << ".capnp.proxy-types.h>\n";
136+
std::ofstream cpp_types(output_path + ".proxy-types.c++");
137+
cpp_types << "// Generated by " PROXY_BIN " from " << src_file << "\n\n";
138+
cpp_types << "#include <" << include_path << ".proxy-types.h>\n";
90139
cpp_types << "#include <" << PROXY_TYPES << ">\n\n";
91140
cpp_types << "namespace mp {\n";
92141

93-
std::string guard = stem;
142+
std::string guard = output_path;
94143
std::transform(guard.begin(), guard.end(), guard.begin(), [](unsigned char c) {
95144
return ('0' <= c && c <= '9') ? c : ('A' <= c && c <= 'Z') ? c : ('a' <= c && c <= 'z') ? c - 'a' + 'A' : '_';
96145
});
97146

98-
std::ofstream inl(stem + ".capnp.proxy-types.h");
99-
inl << "// Generated by " PROXY_BIN " from " << input_schema << "\n\n";
100-
inl << "#ifndef " << guard << "_CAPNP_PROXY_TYPES_H\n";
101-
inl << "#define " << guard << "_CAPNP_PROXY_TYPES_H\n\n";
102-
inl << "#include <" << stem << ".capnp.proxy.h>\n";
103-
inl << "#include <" << stem << "-types.h>\n\n";
147+
std::ofstream inl(output_path + ".proxy-types.h");
148+
inl << "// Generated by " PROXY_BIN " from " << src_file << "\n\n";
149+
inl << "#ifndef " << guard << "_PROXY_TYPES_H\n";
150+
inl << "#define " << guard << "_PROXY_TYPES_H\n\n";
151+
inl << "#include <" << include_path << ".proxy.h>\n";
152+
inl << "#include <" << include_base << "-types.h>\n\n";
104153
inl << "namespace mp {\n";
105154

106-
std::ofstream h(stem + ".capnp.proxy.h");
107-
h << "// Generated by " PROXY_BIN " from " << input_schema << "\n\n";
108-
h << "#ifndef " << guard << "_CAPNP_PROXY_H\n";
109-
h << "#define " << guard << "_CAPNP_PROXY_H\n\n";
110-
h << "#include <" << stem << ".h>\n";
111-
h << "#include <" << stem << ".capnp.h>\n";
155+
std::ofstream h(output_path + ".proxy.h");
156+
h << "// Generated by " PROXY_BIN " from " << src_file << "\n\n";
157+
h << "#ifndef " << guard << "_PROXY_H\n";
158+
h << "#define " << guard << "_PROXY_H\n\n";
159+
h << "#include <" << include_path << ".h>\n";
160+
h << "#include <" << include_base << ".h>\n";
112161
h << "#include <" << PROXY_DECL << ">\n\n";
113162
h << "namespace mp {\n";
114163

@@ -117,10 +166,10 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
117166
message_namespace = value->getText();
118167
}
119168

120-
std::string output_name = output_stem;
121-
size_t output_slash = output_name.rfind("/");
169+
std::string base_name = include_base;
170+
size_t output_slash = base_name.rfind("/");
122171
if (output_slash != std::string::npos) {
123-
output_name.erase(0, output_slash + 1);
172+
base_name.erase(0, output_slash + 1);
124173
}
125174

126175
std::ostringstream methods;
@@ -182,7 +231,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
182231
for (const auto field : struc.getFields()) {
183232
auto field_name = field.getProto().getName();
184233
add_accessor(field_name);
185-
dec << " using " << Cap(field_name) << "Accessor = Accessor<" << output_name
234+
dec << " using " << Cap(field_name) << "Accessor = Accessor<" << base_name
186235
<< "_fields::" << Cap(field_name) << ", FIELD_IN | FIELD_OUT";
187236
if (BoxedType(field.getType())) dec << " | FIELD_BOXED";
188237
dec << ">;\n";
@@ -385,7 +434,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
385434
client_invoke << "MakeClientParam<";
386435
}
387436

388-
client_invoke << "Accessor<" << output_name << "_fields::" << Cap(field_name) << ", "
437+
client_invoke << "Accessor<" << base_name << "_fields::" << Cap(field_name) << ", "
389438
<< field_flags.str() << ">>(";
390439

391440
if (field.retval || field.args == 1) {
@@ -405,7 +454,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
405454
} else {
406455
server_invoke_start << "MakeServerField<" << field.args;
407456
}
408-
server_invoke_start << ", Accessor<" << output_name << "_fields::" << Cap(field_name) << ", "
457+
server_invoke_start << ", Accessor<" << base_name << "_fields::" << Cap(field_name) << ", "
409458
<< field_flags.str() << ">>(";
410459
server_invoke_end << ")";
411460
}
@@ -452,8 +501,8 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
452501
}
453502
}
454503

455-
h << methods.str() << "namespace " << output_name << "_fields {\n"
456-
<< accessors.str() << "} // namespace " << output_name << "_fields\n"
504+
h << methods.str() << "namespace " << base_name << "_fields {\n"
505+
<< accessors.str() << "} // namespace " << base_name << "_fields\n"
457506
<< dec.str();
458507

459508
cpp_server << def_server.str();
@@ -475,13 +524,13 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
475524
int main(int argc, char** argv)
476525
{
477526
if (argc < 3) {
478-
fprintf(stderr, "Usage: " PROXY_BIN " OUTPUT_STEM INPUT_SCHEMA [IMPORT_PATH...]\n");
527+
fprintf(stderr, "Usage: " PROXY_BIN " SRC_PREFIX SRC_FILE [IMPORT_PATH...]\n");
479528
exit(1);
480529
}
481530
std::vector<kj::StringPtr> import_paths;
482-
for (size_t i = 3; i < argc; ++i) {
531+
for (size_t i = 4; i < argc; ++i) {
483532
import_paths.push_back(argv[i]);
484533
}
485-
Generate(argv[1], argv[2], {import_paths.data(), import_paths.size()});
534+
Generate(argv[1], argv[2], argv[3], {import_paths.data(), import_paths.size()});
486535
return 0;
487536
}

0 commit comments

Comments
 (0)
Please sign in to comment.