30#include "osl/process.h"
31#include "osl/file.hxx"
32#include "osl/thread.h"
33#include "rtl/ustrbuf.hxx"
35#include "com/sun/star/lang/XComponent.hpp"
36#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
37#include "com/sun/star/container/XSet.hpp"
38#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp"
39#include "com/sun/star/uno/XComponentContext.hpp"
42using namespace ::System::Reflection;
55"using: climaker <switches> [registry-file-1 registry-file-2 ...]\n"
58" -O, --out <output-file> output assembly file;\n"
59" defaults to cli_unotypes.dll if more than one\n"
60" registry-file is given, else <registry-file>.dll\n"
61" -T, --types types to be generated (if none is given,\n"
62" <type1[;type2;...]> then all types of given registries are emitted\n"
63" -X, --extra <rdb-file> additional rdb to saturate referenced types in\n"
64" given registry file(s); these types will not be\n"
65" emitted into the output assembly file\n"
66" -r, --reference reference metadata from assembly file\n"
68" -k, --keyfile keyfile needed for strong name\n"
69" --assembly-version <version> sets assembly version\n"
70" --assembly-description <text> sets assembly description text\n"
71" --assembly-product <text> sets assembly product name\n"
72" --assembly-company <text> sets assembly company\n"
73" --assembly-copyright <text> sets assembly copyright\n"
74" --assembly-trademark <text> sets assembly trademark\n"
75" -v, --verbose verbose output to stdout\n"
76" -h, --help this message\n"
78"example: climaker --out cli_mytypes.dll \\\n"
79" --reference cli_uretypes.dll \\\n"
80" --extra types.rdb \\\n"
96 { RTL_CONSTASCII_STRINGPARAM(
"out"),
'O',
true },
97 { RTL_CONSTASCII_STRINGPARAM(
"types"),
'T',
true },
98 { RTL_CONSTASCII_STRINGPARAM(
"extra"),
'X',
true },
99 { RTL_CONSTASCII_STRINGPARAM(
"reference"),
'r',
true },
100 { RTL_CONSTASCII_STRINGPARAM(
"keyfile"),
'k',
true },
101 { RTL_CONSTASCII_STRINGPARAM(
"delaySign"),
'd',
true },
102 { RTL_CONSTASCII_STRINGPARAM(
"assembly-version"),
'\0',
true },
103 { RTL_CONSTASCII_STRINGPARAM(
"assembly-description"),
'\0',
true },
104 { RTL_CONSTASCII_STRINGPARAM(
"assembly-product"),
'\0',
true },
105 { RTL_CONSTASCII_STRINGPARAM(
"assembly-company"),
'\0',
true },
106 { RTL_CONSTASCII_STRINGPARAM(
"assembly-copyright"),
'\0',
true },
107 { RTL_CONSTASCII_STRINGPARAM(
"assembly-trademark"),
'\0',
true },
108 { RTL_CONSTASCII_STRINGPARAM(
"verbose"),
'v',
false },
109 { RTL_CONSTASCII_STRINGPARAM(
"help"),
'h',
false }
116 for ( sal_Int32
pos = 0;
122 if (opt.getLength() > 0)
124 if (opt.equalsAsciiL(
133 OSL_ASSERT( copt !=
'\0' );
147 OptionInfo const * option_info, sal_uInt32 * pIndex )
149 OSL_ASSERT( option_info != 0 );
150 if (osl_getCommandArgCount() <= *pIndex)
154 osl_getCommandArg( *pIndex, &arg.pData );
155 sal_Int32 len = arg.getLength();
157 if (len < 2 || arg[ 0 ] !=
'-')
165 if (arg[ 1 ] ==
'-' && rtl_ustr_ascii_compare(
166 arg.pData->buffer + 2, option_info->
m_name ) == 0)
176 bool * flag,
OptionInfo const * option_info, sal_uInt32 * pIndex )
178 bool ret =
is_option( option_info, pIndex );
186 OUString * pValue,
OptionInfo const * option_info, sal_uInt32 * pIndex )
190 if (*pIndex < osl_getCommandArgCount())
192 osl_getCommandArg( *pIndex, &pValue->pData );
204 static OUString s_workingDir;
205 if (! s_workingDir.getLength())
206 osl_getProcessWorkingDir( &s_workingDir.pData );
214 oslFileError rc = osl_getFileURLFromSystemPath(
215 path.pData, &file_url.pData );
216 if (osl_File_E_None == rc)
219 rc = osl_getAbsoluteFileURL(
221 if (osl_File_E_None == rc)
228 "cannot make absolute: " + file_url );
234 "cannot get file url from system path: " + path );
245 sal_uInt32
nCount = osl_getCommandArgCount();
253 css::uno::Reference< XComponentContext > xContext;
257 OptionInfo
const * info_help =
259 OptionInfo
const * info_verbose =
261 OptionInfo
const * info_out =
263 OptionInfo
const * info_types =
265 OptionInfo
const * info_reference =
267 OptionInfo
const * info_extra =
269 OptionInfo
const * info_keyfile =
271 OptionInfo
const * info_delaySign =
273 OptionInfo
const * info_version =
275 OptionInfo
const * info_product =
277 OptionInfo
const * info_description =
279 OptionInfo
const * info_company =
281 OptionInfo
const * info_copyright =
283 OptionInfo
const * info_trademark =
287 std::vector< OUString > mandatory_registries;
288 std::vector< OUString > extra_registries;
289 std::vector< OUString > extra_assemblies;
290 std::vector< OUString > explicit_types;
291 OUString version, product, description, company, copyright, trademark,
308 explicit_types.push_back(
309 cmd_arg.getToken( 0,
';',
index ) );
315 extra_registries.push_back(
320 extra_assemblies.push_back(
334 osl_getCommandArg(
nPos, &cmd_arg.pData );
336 cmd_arg = cmd_arg.trim();
337 if (cmd_arg.getLength() > 0)
339 if (cmd_arg[ 0 ] ==
'-')
341 OptionInfo
const * option_info = 0;
342 if (cmd_arg.getLength() > 2 &&
347 cmd_arg.copy( 2 ),
'\0' );
349 else if (cmd_arg.getLength() == 2 &&
354 OUString(), cmd_arg[ 1 ] );
356 if (option_info == 0)
358 throw RuntimeException(
"unknown option " + cmd_arg +
"! Use climaker --help to print all options.");
362 OSL_FAIL(
"unhandled valid option?!" );
363 if (option_info->m_has_argument)
369 mandatory_registries.push_back(
377 xContext = ::cppu::defaultBootstrap_InitialComponentContext();
378 css::uno::Reference< container::XHierarchicalNameAccess > xTDmgr(
379 xContext->getValueByName(
380 "/singletons/com.sun.star.reflection."
381 "theTypeDescriptionManager" ),
392 css::uno::Reference< container::XSet > xSet( xTDmgr, UNO_QUERY_THROW );
394 std::vector< rtl::Reference< unoidl::Provider > > unoidlMandatoryProvs;
395 for (
auto& rRegistry : extra_registries)
397 xSet->insert(
Any(rRegistry));
398 unoidlMgr->addProvider(rRegistry);
400 for (
auto& rRegistry : mandatory_registries)
402 xSet->insert(
Any(rRegistry));
404 unoidlMandatoryProvs.push_back(prov);
407 if (0 == output.getLength())
410 if (1 == mandatory_registries.size())
412 output = mandatory_registries[ 0 ];
413 output = output.copy( output.lastIndexOf(
'/' ) +1 );
414 sal_Int32 dot = output.lastIndexOf(
'.' );
416 output = output.copy( 0, dot );
420 output =
"cli_unotypes";
424 sal_Int32 slash = output.lastIndexOf(
'/' );
425 OUString sys_output_dir;
426 if (FileBase::E_None != FileBase::getSystemPathFromFileURL(
427 output.copy( 0, slash ), sys_output_dir ))
430 "cannot get system path from file url " +
431 output.copy( 0, slash ) );
433 OUString filename( output.copy( slash +1 ) );
434 sal_Int32 dot = filename.lastIndexOf(
'.' );
435 OUString
name( filename );
444 StrongNameKeyPair^ kp =
nullptr;
445 if (keyfile.getLength() > 0)
449 System::IO::FileStream^
fs = gcnew System::IO::FileStream(
450 sKeyFile, System::IO::FileMode::Open,
451 System::IO::FileAccess::Read, System::IO::FileShare::Read);
452 kp = gcnew StrongNameKeyPair(
fs);
455 catch (System::IO::FileNotFoundException ^ )
457 throw Exception(
"Could not find the keyfile. Verify the --keyfile argument!", 0);
464 ::System::Console::Write(
465 "> no key file specified. Cannot create strong name!\n");
469 AssemblyName ^ assembly_name = gcnew AssemblyName();
470 assembly_name->CodeBase = output_dir;
471 assembly_name->Name = gcnew ::System::String(
472 reinterpret_cast<wchar_t const *
>(
name.getStr()));
474 assembly_name->KeyPair= kp;
476 if (version.getLength() != 0)
478 assembly_name->Version=
483 ::System::AppDomain ^ current_appdomain =
484 ::System::AppDomain::CurrentDomain;
489#pragma warning (push)
490#pragma warning (disable: 4538)
492 Emit::AssemblyBuilder ^ assembly_builder =
493 current_appdomain->DefineDynamicAssembly(
494 assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir );
497 if (product.getLength() != 0)
499 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^> (1);
500 cli::array< ::System::Object^>^
args = gcnew cli::array< ::System::Object^>(1);
501 params[ 0 ] = ::System::String::typeid;
503 assembly_builder->SetCustomAttribute(
504 gcnew Emit::CustomAttributeBuilder(
505 (AssemblyProductAttribute::typeid)->GetConstructor(
508 if (description.getLength() != 0)
510 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
511 cli::array< ::System::Object^>^
args = gcnew cli::array< ::System::Object^>(1);
512 params[ 0 ] = ::System::String::typeid;
514 assembly_builder->SetCustomAttribute(
515 gcnew Emit::CustomAttributeBuilder(
516 (AssemblyDescriptionAttribute::typeid)->GetConstructor(
519 if (company.getLength() != 0)
521 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
522 cli::array< ::System::Object^>^
args = gcnew cli::array< ::System::Object^>(1);
523 params[ 0 ] = ::System::String::typeid;
525 assembly_builder->SetCustomAttribute(
526 gcnew Emit::CustomAttributeBuilder(
527 (AssemblyCompanyAttribute::typeid)->GetConstructor(
530 if (copyright.getLength() != 0)
532 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
533 cli::array< ::System::Object^>^
args = gcnew cli::array< ::System::Object^>(1);
534 params[ 0 ] = ::System::String::typeid;
536 assembly_builder->SetCustomAttribute(
537 gcnew Emit::CustomAttributeBuilder(
538 (AssemblyCopyrightAttribute::typeid)->GetConstructor(
541 if (trademark.getLength() != 0)
543 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
544 cli::array< ::System::Object^>^
args = gcnew cli::array< ::System::Object^>(1);
545 params[ 0 ] = ::System::String::typeid;
547 assembly_builder->SetCustomAttribute(
548 gcnew Emit::CustomAttributeBuilder(
549 (AssemblyTrademarkAttribute::typeid)->GetConstructor(
554 cli::array<Assembly^>^ assemblies =
555 gcnew cli::array<Assembly^>(extra_assemblies.size());
556 for (
size_t pos = 0;
pos < extra_assemblies.size(); ++
pos )
558 assemblies[
pos ] = Assembly::LoadFrom(
563 TypeEmitter ^ type_emitter = gcnew TypeEmitter(
564 assembly_builder->DefineDynamicModule( output_file ), assemblies );
566 ::System::ResolveEventHandler ^ type_resolver =
567 gcnew ::System::ResolveEventHandler(
568 type_emitter, &TypeEmitter::type_resolve );
569 current_appdomain->TypeResolve += type_resolver;
572 if (explicit_types.empty())
574 css::uno::Reference< reflection::XTypeDescriptionEnumeration > xTD_enum(
575 css::uno::Reference< reflection::XTypeDescriptionEnumerationAccess >(
576 xTDmgr, UNO_QUERY_THROW )
577 ->createTypeDescriptionEnumeration(
579 Sequence< TypeClass >() ,
580 reflection::TypeDescriptionSearchDepth_INFINITE ) );
581 while (xTD_enum->hasMoreElements())
583 css::uno::Reference< reflection::XTypeDescription > td(
584 xTD_enum->nextTypeDescription());
585 OUString
name(td->getName());
586 bool bEmit = std::any_of(unoidlMandatoryProvs.begin(), unoidlMandatoryProvs.end(),
589 type_emitter->get_type(td);
595 for (
size_t nPos = explicit_types.size();
nPos--; )
597 type_emitter->get_type(
598 css::uno::Reference< reflection::XTypeDescription >(
599 xTDmgr->getByHierarchicalName( explicit_types[
nPos ] ),
603 type_emitter->finish();
607 ::System::Console::Write(
608 "> saving assembly {0}{1}{2}...",
610 gcnew ::System::String(
611 ::System::IO::Path::DirectorySeparatorChar, 1 ),
614 assembly_builder->Save( output_file );
617 ::System::Console::WriteLine(
"ok." );
619 current_appdomain->TypeResolve -= type_resolver;
623 std::cerr <<
"ERROR: No such file <" << e.
getUri() <<
">\n";
629 <<
"ERROR: Bad format of <" << e.
getUri() <<
">, \""
630 << e.getDetail() <<
"\"\n";
638 stderr,
"\n> error: %s\n> dying abnormally...\n", msg.getStr() );
641 catch (::System::Exception ^ exc)
645 osl_getThreadTextEncoding() ) );
648 "\n> error: .NET exception occurred: %s\n> dying abnormally...",
655 css::uno::Reference< lang::XComponent > xComp( xContext, UNO_QUERY );
665 "\n> error disposing component context: %s\n"
666 "> dying abnormally...\n",
const OUString & getUri() const
std::unique_ptr< sal_Int32[]> pData
inline ::System::String ustring_to_String(OUString const &ustr)
static char const s_usingText[]
static const OptionInfo s_option_infos[]
static bool is_option(OptionInfo const *option_info, sal_uInt32 *pIndex)
static OUString const & path_get_working_dir()
OUString String_to_ustring(::System::String ^ str)
static OUString path_make_absolute_file_url(OUString const &path)
static bool read_argument(OUString *pValue, OptionInfo const *option_info, sal_uInt32 *pIndex)
static OptionInfo const * get_option_info(OUString const &opt, sal_Unicode copt='\0')
static bool read_option(bool *flag, OptionInfo const *option_info, sal_uInt32 *pIndex)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
SwNodeOffset abs(const SwNodeOffset &a)
sal_Unicode m_short_option