Use cmake variable in xsd file [duplicate] - xsd

In my CMake-based project I have some XML files used to generate code (using the typical add_custom_command & add_custom_target pattern).
This XML file includes other files as follows:
<?xml version="1.0" encoding="utf-8"?>
<definition
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../MyComponent/schema.xsd">
<include href="../../../MyComponent/another.xml" />
</definition>
Now I want to make ../../../MyComponent dependent on a CMake variable. What would definitely would work is to write a generator that takes an XML template and replaces the paths with the content of a CMake variable using, here also, the add_custom_command & add_custom_target pattern.
Is there a solution that would make use of simple CMake and/or XML mechanisms to patch or generate the correct path?

Turning my comment into an answer
I've used the following technique to e.g. generate user project setting XML files for CMake generated VS environments (see e.g. this blog post by Jim Butler).
In your case I would do:
some.xml.in
<?xml version="1.0" encoding="utf-8"?>
<definition
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="${_my_xml_root_path}/schema.xsd">
<include href="${_my_xml_root_path}/another.xml" />
</definition>
And in your CMakeLists.txt something like (depending on the path you want to inject):
get_filename_component(_my_xml_root_path "../../../MyComponent" ABSOLUTE)
set(_some_xml_path "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/some.xml")
configure_file("some.xml.in" "${_some_xml_path}")
Then you can use ${_some_xml_path} later to give as an input file to some other build step.

Related

Using modular JAXB compilation does not (seem to) work when location is not an URL

I have 2 schemas: a.xsd and b.xsd which has a dependency on a.xsd (episode).
Schemas are split in different maven projects and packages.
Originally, b.xsd imports a.xsd like this (I don't want to change it):
<import namespace="urn:a" schemaLocation="a.xsd"/>
What do I need to put in my catalog.cat to translate a.xsd to maven:com.mycompany:a:jar::!/com/mycompany/a/a.xsd
I tried PUBLIC, SYSTEM, URI, REWRITE_URI, REWRITE_SYSTEM but nothing is working.
As soon as I change the reference a.xsd to http://.../a.xsd in my schema and use REWRITE_SYSTEM in my catalog, then it is working. But as I said, I don't want to modify my schema.
Nevermind, it seems to work with SYSTEM_SUFFIX.
See Modular Schema Compilation, starting with
However there's a bug in JAXB/XJC this does not work if you have schemaLocation in your xs:import.
Resolving schemas in XJC is quite buggy and I did not see any progress on that in the last few years.
So what works for me quite well in a number of projects:
Compile you schemas not from the local path but some absolute URL. This does not need to actually exist, can be completely virtual. Just use an absolute URL:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<schemas>
<schema>
<url>http://schemas.opengis.net/ows/2.0/owsAll.xsd</url>
</schema>
</schemas>
<!-- ... -->
</configuration>
</plugin>
Use a catalog file to rewrite your absolute URL prefix to some local path or resource in a JAR:
REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"
Apply your bindings not to local files but via absolute URLs:
<jaxb:bindings schemaLocation="http://schemas.opengis.net/ows/2.0/owsAll.xsd" node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="net.opengis.ows.v_2_0"/>
</jaxb:schemaBindings>
</jaxb:bindings>
Thus all your URLs will be absolute (without the need to patch the schemas) and so REWRITE_SYSTEM will work as desired. This is the best option I've found so far, and, believe me, I've compiled a lot of schemas.
Disclaimer: I'm the author of maven-jaxb2-plugin.

Xamarin/MonoTouch: Unable to compile in "Link SDK only" mode due to missing symbols

I am trying to compile my iOS application using MonoTouch in Link SDK only mode. It compiles completely fine if I turn off linking entirely but it also produces a colossal binary which is not suitable for release mode.
Unfortunately, one of the libraries that I need somehow invokes Expression.Visit and I can't figure out how to instruct the linker to not strip it out. This results in this compilation error:
Error MT2002: Failed to resolve "System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor::Visit(System.Linq.Expressions.Expression)" reference from "System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" (MT2002) (MyApp)
As per the documentation on custom linking, I have set up a linker file to try to stop this happening:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor">
<method signature="System.Linq.Expressions.Expression Visit(System.Linq.Expressions.Expression)" />
</type>
</assembly>
</linker>
Unfortunately, that doesn't have any effect - the error just happens as before.
The documentation mentions a preserve="fields" parameter I can supply to <type>, so I tried that:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor" preserve="methods" />
</assembly>
</linker>
That didn't work either.
I then introduced an XML syntax error into the file and the build failed saying it couldn't parse the linker file so I at least know that the file is being read.
But then I tried introducing errors into the assembly name:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="NonexistentAssembly">
</assembly>
</linker>
That caused an error, complaining that the assembly couldn't be resolved.
I then tried to mangle the type name:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="NonExistentType" preserve="methods" />
</assembly>
</linker>
Now, that just started showing the same "unable to resolve expressionvisitor::visit" error I was seeing before. It seems that type names are not checked.
Also, neither are signature names as this also presented the same compilation error.
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.ExpressionVisitor">
<method signature="jg98j23890rj2390erk90fk3ew!]['##'#'[" />
</type>
</assembly>
</linker>
So it seems that so long as you specify the assembly name and have a valid XML structure, the linker file does not cause any exceptions to be thrown. The documentation for the linker file though is not especially verbose for such a complex topic and includes numerous syntax errors, i.e.:
<type fullname="Foo" preserve="fields" />
<method name=".ctor" />
</type>
Also, it doesn't give a technical description of the linker file format so it's entirely possible that my definition is totally wrong.
I have also tried just skipping the linking of System.Core entirely with --linkskip=System.Core but this has no effect. I have tried this flag both with and without --xml.
In the MvvmCross project, I tried specifying a new class to call the Visit method in the same style as the LinkerPleaseInclude.cs file that gets added to every iOS project by the MvvmCross NuGet package:
[Preserve]
public class PleaseIncludeVisitor : ExpressionVisitor
{
public PleaseIncludeVisitor()
{
this.Visit(null);
}
}
Unfortunately, this also had no effect.
I am currently using Mono 3.2.6 ((no/9b58377) and Xamarin.iOS v7.0.7.2.
The main issue is that it is not possible to do code generation at runtime on iOS.
That means that a large part of System.Linq.Expressions would, normally, be impossible to provide under normal circumstances (just like System.Refection.Emit can't be provided).
To workaround this Xamarin.iOS has been providing an alternative implementation (that can interpret the most common expressions).
However the current code is not 100% API compatible with the .NET framework (that's fixed but not yet released). E.g.
System.Linq.Expressions.Expression System.Linq.Expressions.ExpressionVisitor::Visit(System.Linq.Expressions.Expression)
The above returns void in the current Xamarin.iOS (7.0.x) releases. That why the linker complains (it's not a bug) as it cannot find this member reference (and if it can't find it it cannot recreate the smaller, linked, assemblies). It is not possible to preserve a member that does not exist (which is why your attempts to use XML files or attributes won't help).
The current workaround is to identify which of your assemblies is using this API and rebuild it (from source) to use the existing System.Core.dll that is shipped with Xamarin.iOS.
Notes
I can't figure out how to instruct the linker to not strip it out.
The linker does not try to strip it out it tries to keep it in (i.e. it must load the reference to be able to save it back). However it cannot find that member in System.Core.dll making it impossible to provide a valid linked version of the assemblies.
<method signature="System.Linq.Expressions.Expression Visit(System.Linq.Expressions.Expression)" />
That's asking to preserve something that does not exist. It will be ignored, i.e. when the void-returning version is found it will not match the XML description.

How to exclude assembly reference using custom conditional properties in Xamarin.iOS project

I have solution in Xamarin.iOS with project that references very large DLL (binding for very large native library). So build time for solution is very large. After simple modification in any source file I need to wait for linking. So my idea was to exclude the reference from project using custom property and also to make define that I will use in .cs files to exclude code that depends on large assembly. But I'm unable to use custom condition to exclude the reference. The following strategy will not work for Xamarin.iOS (but will work in Visual Studio):
Create file CommonProperties.prop:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LinkWithLargeAssembly>True</LinkWithLargeAssembly>
</PropertyGroup>
</Project>
So the idea is: When it is not critical I can define LinkWithLargeAssembly as False and link my project fast. CommonProperties.prop can be imported in any assembly that depends on features of the large library.
In the project file .csproj import above file and try to exclude reference (for example monotouch):
...
<Import Project="CommonProperties.prop" />
...
<ItemGroup>
<Reference Include="monotouch" Condition=" '$(LinkWithLargeAssembly)' == 'True' " />
</ItemGroup>
...
I've tried also to define property $(LinkWithLargeAssembly) directly in the project file without import. Also I've tried to use already defined properties for example $(RootNamespace) and $(AssemblyName). But Condition attribute works only for properties $(Configuration) and $(Platform). That is following code will include and exclude monotouch depending on the configuration:
<ItemGroup>
<Reference Include="monotouch" Condition=" '$(Configuration)' == 'Debug' " />
</ItemGroup>
Is it possible to customize assembly reference including using my own conditional properties?
I solved the problem by adding new build configuration that was copied from Debug. I named it DebugNoLargeLib. So I can exclude reference with the following code because $(Configuration) property will be parsed correctly:
<ItemGroup>
<Reference Include="SomeLargeLib.dll" Condition=" '$(Configuration)' != 'DebugNoLargeLib' " />
</ItemGroup>
After I added preprocessor directive NO_LARGE_LIB to the Compiler section for configuration DebugNoLargeLib.
So now I'm able to link without large library and exclude code depending on it from compilation.
But I think this is mistake from Xamarin side that project files processing is not fully supported according to Microsoft specs.

basic XSD importing and xsd.exe?

I have a main xsd built against another one containing shared types (they are in the same directory).
That's the header of the main one :
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="XMLSchema_Module.xsd"
xmlns:cs="XML_Common"
targetNamespace="XMLSchema_Module.xsd"
elementFormDefault="qualified">
<xsd:import schemaLocation="XML_Common.xsd" namespace="XML_Common"/>
That's the header of the shared types one :
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="XML_Common"
elementFormDefault="qualified">
That's the shared type enumeration I want to use in an attribute of the main schema :
<xsd:simpleType name="TypesType">
<xsd:restriction base ="xsd:token">
<xsd:enumeration value="int"/>
And here is the reference in the main one :
<xsd:attribute name="Type" type="cs:TypesType"/>
I am using xsd.exe to generate the serialization classes (integrated in the build process as a pre-build event). These xsd were built using VisualStudio.
<Exec Command=""C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\xsd.exe" XSchemas\XMLSchema_Module.xsd /c /o:SerializationClasses /n:ScenarioManager" />
I am translating the actual message I obtain :
The type XML_Common:TypesType is not declared or is not a simple type.
It seems to be an import problem but I do not know how to solve it.
My bad, it seems that xsd.exe does not resolve schema imports.
From this article :
Now that the type has been defined in another file, the xsd.exe will
generate this error if you attempt to create the create the Request
XML: C:\Solution\Project>xsd.exe Request.xsd /c Schema validation
warning: Type 'http://www.Example.com/Types:Meeting' is not declared.
Warning: Schema could not be validated. Class generation may fail or
may produce incorrect results. Error: Error generating classes for
schema 'C:\Solution\Projects\Request'.
The datatype 'http://www.Example.com/Types:Meeting' is missing. If you would like more help, please type "xsd /?". This is due to the
fact that the xsd.exe does not use the schemaLocation hint to find the
imported schema. You’ve got to include it as a parameter. in your
xsd.exe call: C:\Solution\Project>xsd.exe Types.xsd Request.xsd /c
It should be emphasized that despite the pessimistic opening of LB40's answer, its last sentence yields the solution: in your xsd.exe call you have to include the referenced xsd as a parameter before the referencing xsd:
C:\Solution\Project>xsd.exe Types.xsd Request.xsd /c
This will generate a single cs source file containing the classes for both the schemas.

xjc generated code references OverrideAnnotationOf annotation from sun internal package

I'm trying to generate Java classes from a set of XML schemas. The following binding file is used to handle mixed content in the schemas:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateMixedExtensions="true"/>
</jaxb:bindings>
The code generation works fine but one of the generated classes has an #OverrideAnnotationOf from the com.sun.xml.internal.bind.annotation package. This package is included in rt.jar but the regular java compiler can't find it (and probably shouldn't find it because it is sun internal).
Is there a way to deal with the mixed content and not have the OverrideAnnotationOf from a sun internal package in my generated code?
In Java 6 and up, oracle moved the JAXB implementation embedded within the JRE to a different package to prevent potential collisions with the external JAXB reference implementation.
So the class OverrideAnnotationOf got moved from package com.sun.xml.bind.annotation to package com.sun.xml.internal.bind.annotation.
The embedded xjc, however, still generates java files that are annotated with com.sun.xml.bind.annotation.OverrideAnnotationOf(!)
Therefore, the JAXB implementation shipped with Java 7 will not understand its own output generated with generateMixedExtensions="true". Even if you use the -XDignore.symbol.file option.

Resources