Using SqlClient in an MSBuild Task targeting netcoreapp2.1 - msbuild

I've written an MSBuild Task like this one, but mine has a reference to System.Data.SqlClient.
So I use dotnet publish to target the specific framework netcoreapp2.0 to get the dependencies in the bin dir.
The problem with this is when I run the task through an msbuild script I get: error : System.Data.SqlClient is not supported on this platform.
The build engine: Microsoft (R) Build Engine version 15.7.177.53362 for .NET Core.
Here is the complete (task & test) project
The csproj:
<Project DefaultTargets="Build">
<UsingTask TaskName="TestTasks.TestSqlClient" AssemblyFile=".\Task\bin\Debug\netcoreapp2.0\publish\TestTask.dll" />
<Target Name="Build">
<TestSqlClient />
</Target>
</Project>
list of files and dirs under bin\netcoreapp2.0\publish:
| Microsoft.Build.Framework.dll
| Microsoft.Build.Utilities.Core.dll
| System.Data.SqlClient.dll
| System.Text.Encoding.CodePages.dll
| TestTask.deps.json
| TestTask.dll
| TestTask.pdb
|
\---runtimes
+---unix
| \---lib
| \---netstandard2.0
| System.Data.SqlClient.dll
|
+---win
| \---lib
| +---netcoreapp2.0
| | System.Text.Encoding.CodePages.dll
| |
| \---netstandard2.0
| System.Data.SqlClient.dll
|
+---win-arm64
| \---native
| sni.dll
|
+---win-x64
| \---native
| sni.dll
|
\---win-x86
\---native
sni.dll

It appears you have run into https://github.com/Microsoft/msbuild/issues/1887. One of the current limitations of using dependencies from MSBuild tasks is that MSBuild will not load native dependencies. As you can see in your output, there is a “runtimes” folder which contains sni.dll for x86, x64, and more. The only way to workaround this on .NET Core is to manually resolve native dependencies youself using assembly load context. This is very difficult to do right and I don’t recommend it. See https://natemcmaster.com/blog/2017/11/11/msbuild-task-with-dependencies/ for more details.
A simpler workaround is to implement your tool as a console tool. Then use a target and the Exec task, or a customized implementation of ToolTask, to run your console tool during build. This is how the C# compiler itself works, and I have described this approach in more detail here: https://natemcmaster.com/blog/2017/11/11/build-tools-in-nuget/. Also, see https://github.com/natemcmaster/Yarn.MSBuild for a real-world example.

Related

PackageReference Resolve Version Logic as API

Is there any accessible API via an MSBuild task, target or otherwise that allows me to query what version of a NuGet package a given PackageReference will resolve (or has already resolved) to?
For example, if I have a csproj with
<PackageReference Include=“MyPkg” Version=“1.*”/>
And I have a custom target where I want to
<MyTarget>
<GetVersionOfResolvedPackageReference Name=“MyPkg” OutputProperty=“IWantToKnowThis” /> <!— or something —>
...
From How NuGet resolves package dependencies:
When the NuGet restore process runs prior to a build, it resolves
dependencies first in memory, then writes the resulting graph to a
file called project.assets.json in the obj folder of a project using
PackageReference. MSBuild then reads this file and translates it into
a set of folders where potential references can be found, and then
adds them to the project tree in memory.
<#
.Synopsis
Represents the method that
returns the project.assets
content as object.
#>
function Get-ProjectAssest([System.String]$Assest) {
return (Get-Content $Assest | ConvertTo-Json | ConvertFrom-Json).value |
ConvertFrom-Json
}
Get-ChildItem -Path . 'project.assets.json' -Recurse | ForEach-Object { Get-ProjectAssest($_.FullName) } | ForEach-Object {
# K = Package Identity
# V = Package Version
$_.libraries | ForEach-Object { $_.PSObject.Properties.Name } | Out-File 'PackageReference.ini' -Append
}
This PowerShell script recursively parses directories to find project.assets.json and writes result in PackageReference.ini file. You can call script from MSBuild via Exec task and after that read file via ReadLinesFromFile and performing further processing.
NOTE: Represented script will be produce duplicates of PackageReference lines for multiple projects.

Add JVM parameter to sbt shell configuration in IntelliJ

I have to set an additional library path -Djava.library.path=/x/y/z in order to execute run / debug tasks using SBT, otherwise I get a NoClassDefFoundError. Where can I do this in IntelliJ IDEA?
You could add additional parameters in "Settings | Build... | Build Tools | sbt"

How to re-include excluded paths in Intellij when using Maven

I am working on a multi level maven based project. One of the modules had dependencies issues and I had excluded it: now I wish to reenable/re-include that module.
The IJ documentation says to go to
File | Settings | Compiler | Excludes
However that option reports "No excludes". Apparently the above documentation does apply to Maven built projects
Note the above is also the suggested way for another question with similar title How do I re-include a class into the build path in Intellij IDEA? . So please do not mark this question as a "duplicate".
I also tried :
File | Project Structure | Modules.
But there was no mention of excluded paths there either.

Maven: How to use jetty:run in a multi-module Maven project, without needing to install

I'm new to Maven. I have a multi-module maven 2 project that has the following structure (somewhat simplified):
Project (POM packaging)
|
+-- Module1 (JAR)
| |
| +-- src
| |
| +-- main
| |
| +-- java
| +-- resources
|
+-- Module2 (JAR)
| |
| ...
|
+-- Web Module (WAR)
|
...
I've configured the Web Module to include the Maven Jetty plugin.
This works great for building the production artifacts. For development, I discovered that I need to call mvn install on any module that I change, followed by stoping jetty and calling jetty:run again.
It would be much more productive if there was a way for the plugin to pick changes directly from each module's target directories. According to the jetty plugin documentation there seems to be such a feature, but it appears this only applies to the WAR module.
Even more important to me is to be able to make changes to resource files, without the need to restart jetty. That's because most of the resources are HTML template files, and it's enormously more productive to design and update the templates during development without needing to restart to see the changes.
So, is there a way to set the classpath of the jetty plugin to include the target/classes and resources directories of each JAR module, instead of the actual JARs in the local repository?
Thanks!
Yaniv
This isn't possible with a multi-module Maven project. A cardinal rule of Maven projects is that each project should be able to stand alone. That doesn't preclude them from being built together, but any one project should be able to be built by itself so long as all it's dependencies are satisfied.
In this case, it means that the WAR project cannot look out to the other projects to see if they need to be updated, the POM for those other projects are the definitive declaration of what needs to be done to build the artifact. And once the artifact is built, it is put in the local repository. There is no association between the source files and the artifact at that point, so there's no way to tell what source files would trigger a rebuild of the artifact that the WAR depends on.
In Eclipse, you can use "Run Jetty" plugin to achieve this.
In IDEA's Run Configuration, there is an option 'Resolve Workspace artifacts', check it.
If you use M2Eclipse (Eclipse plug-in for a close integration of Maven within Eclipse), you can run your jetty:run goal in the web module and other dependencies will be taken into account from your workspace, even if they are not at all available in your local repository.
There is just an option in your run to tell Maven to resolve your modules in the workspace itself (by default, it would just fetch what is deployed in the local repository).
Unfortunately, I cannot have the same behaviour in IDEA and I have to run an install before running the jetty:run on the web module.
Based on this answer:Best practice wrt. `mvn install`, multi-module projects, and running one submodule
a workaround around Mavens horrible restrictions and reactor limitations is to define the plugin in the parent pom with skip true, and then reenable it in the respective submodule using skip false.
I solved by using a maven launcher and configuring Resolve Workspace artifacts,
that is not checked by default

How do I set up a test project for a Eclipse plugin project

I'm working on a eclipse plug-in and I've tried to create another test project seperate from the plug-in. The reason I do this is to not let the plug-in depend on jUnit when it is exported. However, I can't access the Eclipse Plug-in API when I do the testing. Whenever I try to add Plug-in dependencies the import list to that is empty.
Does anyone know how to import Eclipse plug-in API to an existing project? The workspace layout looks like this at the moment:
+- com.foo.myplugin
| |
| +- JRE System Library
| |
| +- Plug-in Dependencies
| |
| +- src
| |
| +- icons, META-INF, plugin.xml, etc...
|
+- com.foo.myplugin.test
|
+- JRE System Library
|
+- JUnit 4
|
+- src
The recomended way of ding this seems to be with Plug-in fragments:
http://rcpquickstart.com/2007/06/20/unit-testing-plug-ins-with-fragments/
The fragment gets a high-degree of access to your plugin's code and separates the testing logic / dependencies from the plugin itsself.
Now if only I could find a way to test them in an automated system... (see: Automating unit tests (junit) for Eclipse Plugin development )
You can export the plug-in dependency from the plug-in project. Easiest way is like this:
Go to your com.foo.plugin project properties
Go to Java Build Path > Order and Export
Check the Plug-in Dependencies entry
The test project should now be able to use plug-in API without the need to use all plugin configuration required for a plug-in project.
You could try to add the plugin nature to your new myplugin.test project.
In your .project file:
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
[...]
</natures>
Then in the .classpath, add:
<classpath>
[...]
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
[...]
</classpath>
Delete your myplugin.test from the workspace, re-import that project and see if that does the trick...