Swift Package Manager cannot find a neighboring folder/class in Sources - swift-package-manager

Goal: To access neighboring folder/classes within the source folder.
Scenario: I have two classes:
RicPackage (default) and
Apple
The 'RicPackage' was auto-generated upon the creation of the Swift Package 'RicPackage'. I want to expand and try to access other folders w/classes autonomously.
Here's the manifest that I'm working on:
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "RicPackage",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "RicPackage",
targets: ["RicPackage"]),
.library(
name: "Apple",
targets: ["Apple"]),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "RicPackage",
dependencies: []),
.target(
name: "Apple",
dependencies: []),
.testTarget(
name: "RicPackageTests",
dependencies: ["RicPackage"]),
]
)
I want to be able to access 'Apple' and other such folders independently from the host program.
Here's the Apple source code:
import Foundation
class Apple {
public private(set) var text = "Hello from Apple!"
public init() {
}
public func eat() -> String {
print("Inside Eat Apple")
return "Hello from Eat Apple."
}
}
Here's the test.
Once I get this to work, I'll try to access it from the host application.
I believe that classes & functions must be 'pubic' to be seen.
Questions:
What am I doing wrong with the package manifest file?
Must a target class file have the same name as its folder container?
... for example: 'Apple/Apple.swift'.

So in RicPackageTest, you can't find Apple. Is there an import missing? Not necessarily, you won't find it either.
It's because in the way that RicPackageTest is constructed it has no knowledge of the Apple package.
You wrote:
.testTarget(
name: "RicPackageTests",
dependencies: ["RicPackage"]),
That's what's missing, you aren't saying that RicPackageTests should "depend" (ie "knows of") Apple package.
So you should do:
.testTarget(
name: "RicPackageTests",
dependencies: ["RicPackage", "Apple"]),

Thanks to Larme for correctly answering my novice question.
Here's the solution:
Need dependency:
Need reference in test:

Related

Vue CLI with electron - Unexpected character (1:0) when using native modules

In some popular NodeJS libraries, e.g. ssh2 or node-pty, there is natively compiled code as part of the library.
Creating the project with
vue create my-project
vue add electron-builder
yarn add ssh2
then importing and using ssh2's Client in the background process results in following errors during
electron:build
ERROR Failed to compile with 1 errors 5:29:10 PM
error in ./node_modules/cpu-features/build/Release/cpufeatures.node
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
# ./node_modules/cpu-features/lib/index.js 1:16-60
# ./node_modules/ssh2/lib/protocol/constants.js
# ./node_modules/ssh2/lib/client.js
# ./node_modules/ssh2/lib/index.js
...
This error occurs with many other libs or transitive dependencies and the reason for it is absence of native-ext-loader on Webpack chain. I understand why it is not included by default, and I would like to see what is the best way to add it.
One solution I found is this:
Add yarn add -D native-ext-loader (my version is 2.3.0 and electron is at 13.x)
Adjust vue.config.js and add the chainWebpackMainProcess like this:
const path = require('path')
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
// options placed here will be merged with default
mac: {
target: 'dmg',
icon: 'build/icon.icns',
asar: true
}
},
preload: 'src/preload.ts',
chainWebpackMainProcess(config) {
config.module
.rule("node")
.test(/\.node$/)
.use("native-ext-loader")
.loader("native-ext-loader")
.options(
process.env.NODE_ENV === "development"
? {
rewritePath: path.resolve(__dirname, "native"),
}
: {}
)
}
}
}
}
Both, electron:build and electron:serve are now working and ssh2 client is happily delivering the stdout to renderer via ipcMain. Not sure it is the most elegant way of solving it, though.

How do you restore private NuGet packages from private VSTS feeds with Cake

I have a task which restores our NuGet package for our dotnet core application:
Task("Restore-Packages")
.Does(() =>
{
DotNetCoreRestore(sln, new DotNetCoreRestoreSettings {
Sources = new[] {"https://my-team.pkgs.visualstudio.com/_packaging/my-feed/nuget/v3/index.json"},
Verbosity = DotNetCoreVerbosity.Detailed
});
});
However when run on VSTS it errors with the following:
2018-06-14T15:10:53.3857512Z C:\Program Files\dotnet\sdk\2.1.300\NuGet.targets(114,5): error : Unable to load the service index for source https://my-team.pkgs.visualstudio.com/_packaging/my-feed/nuget/v3/index.json. [D:\a\1\s\BitCoinMiner.sln]
2018-06-14T15:10:53.3857956Z C:\Program Files\dotnet\sdk\2.1.300\NuGet.targets(114,5): error : Response status code does not indicate success: 401 (Unauthorized). [D:\a\1\s\BitCoinMiner.sln]
How do I authorize access for the build agent to our private VSTS?
I literally just had this same problem, apparently the build agents in VSTS can't get to your private VSTS feed without an access token so you are going to have to create a Personal Access Token in VSTS and provide that to the built in Cake method to add an authenticated VSTS Nuget feed as one of the sources. Here, I have wrapped it in my own convenience Cake method that checks to see if the package feed is already present, if not, then it adds it:
void SetUpNuget()
{
var feed = new
{
Name = "<feedname>",
Source = "https://<your-vsts-account>.pkgs.visualstudio.com/_packaging/<yournugetfeed>/nuget/v3/index.json"
};
if (!NuGetHasSource(source:feed.Source))
{
var nugetSourceSettings = new NuGetSourcesSettings
{
UserName = "<any-odd-string>",
Password = EnvironmentVariable("NUGET_PAT"),
Verbosity = NuGetVerbosity.Detailed
};
NuGetAddSource(
name:feed.Name,
source:feed.Source,
settings:nugetSourceSettings);
}
}
and then I call it from the "Restore" task:
Task("Restore")
.Does(() => {
SetUpNuget();
DotNetCoreRestore("./<solution-name>.sln");
});
Personally, I prefer to keep PATs away from the source control so here I am reading from env vars. In VSTS you can create an environment variable under the Variables tab of your CI build configuration.
Hope this helps! Here is a link to Cake's documentation.
As pointed out by both #KevinSmith and #NickTurner, a better approach to accessing the VSTS feed is by using the pre-defined system variable System.AccessToken as opposed to using limited validity, manually created and cumbersome PATs. This variable is available on the build agents for the current build to use. More info here.
One way of using this token in the Cake script is as follows:
First, expose the system variable as an environment variable for the Cake task in azure-pipelines.yml
steps:
- task: cake-build.cake.cake-build-task.Cake#0
displayName: 'Cake '
inputs:
target: Pack
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
Then in Cake you can access it like you would any environment variable, so in my case:
if (!NuGetHasSource(source:feed.Source))
{
Information($"Nuget feed {feed.Source} not found, adding...");
var nugetSourceSettings = new NuGetSourcesSettings
{
UserName = "whoosywhatsit",
Password = EnvironmentVariable("SYSTEM_ACCESSTOKEN"),
Verbosity = NuGetVerbosity.Detailed
};
NuGetAddSource(
name:feed.Name,
source:feed.Source,
settings:nugetSourceSettings);
}
This seems to work! If there are better approaches of accessing this variable in Cake please let me know. Please also note in my case, I am only using this to restore packages from my VSTS feed, not for pushing to it. That I do via a DotNetCoreCLI#2 task in the YML like so:
- task: DotNetCoreCLI#2
displayName: 'dotnet nuget push'
inputs:
command: push
packagesToPush: 'artifacts/package.nupkg'
publishVstsFeed: '<id of my VSTS feed>'
And Azure pipeline handles the rest.

How to get outputs of one Rule item as inputs of another one?

I want to create automatic crossplatform installation builder for my project. For this reason I made this file myprojectpackage.qbs:
Product {
type: "mypackage"
Depends { name: "myproject" } // <- this one has type "application"
Depends { name: "applicationpackage" }
}
applicationpackage.qbs uses some submodules and looks like:
Module {
name: "applicationpackage"
Depends { name: "qtlibsbinariespackage" }
Depends { name: "3rdpartybinariespackage" }
Depends { name: "resourcepackage" }
}
All these modules try to find something and copy to package directory. After they finish, I have a folder with a portable version of application. Every module of this group have typical structure:
Module {
name: "somepackage"
Rule {
condition: qbs.targetOS.contains("windows")
multiplex: true
alwaysRun: true
inputsFromDependencies: ["application"]
Artifact {
filePath: "Copied_files.txt"
fileTags: "mypackage"
}
prepare: {
var cmdQt = new JavaScriptCommand()
// prepare paths
cmdQt.sourceCode = function() {
// copy some files and write to Copied_files.txt
}
return [cmdQt]
}
}
}
After portable folder package complete, I want to make a zip archieve. So, I need another Module, which will run after package modules. I think, that only way to do like this is taking .txt files, that were created by modules in applicationpackage, as inputs for another Rule.
I have tried a lot of things (FileTaggers, outputFileTags etc.), but noone worked properly. So is there any way to do make modules work in pipeline as I want to do?
Do I understand correctly that you want to "merge" the contents of the txt files tagged "mypackage" into the archive, i.e. everything listed in all the files is supposed to end up there?
If so, then you simply need a "top-level" rule that does the aggregation. Your existing rules would tag their outputs as e.g. "mypackage.part" and then a multiplex rule would take these as inputs and create a "mypackage" artifact.
Note that there is the archiver module (https://doc.qt.io/qbs/archiver-module.html) that can do the final step of creating the package for you from the aggregated txt file.

Angular 2 submodule routing with AOT and Rollup

What is the correct way to configure a submodule in Angular 2 so that it will work after AOT and rollup? I'm not concerned about lazy loading and will be happy for all submodules to be bundled together, but loadChildren is the cleanest way of referencing a submodule and having it use the correct <router-outlet>, and although I've tried various methods, none will work in both development and production.
I followed the instructions in the AOT cookbook to prepare my app for deployment. My module structure is root > account > admin, and I want the admin routes to load in the outlet defined by the account component.
Here's the router config for the account module:
import { NgModule } from '#angular/core';
import { AdminModule } from './admin/admin.module';
const accountRoutes: Routes = [{
path: 'account',
component: AccountComponent,
children: [
{ path: 'setup', component: SetupComponent },
{ path: 'admin', loadChildren: () => AdminModule }
]
}];
This works in development, but NGC compilation fails with Error: Error encountered resolving symbol values statically. Reference to a local (non-exported) symbol 'accountRoutes'.
I added an export to accountRoutes but this also fails to compile with Error: Error encountered resolving symbol values statically. Function calls are not supported..
One suggestion was to use a string instead of a function so that NGC can compile the code:
loadChildren: 'app/account/admin/admin.module#AdminModule'
This works in development and compiles successfully but the compiled app will not run, because SystemJS is unavailable. The error is:
ERROR Error: Uncaught (in promise): TypeError: System.import is not a function
TypeError: System.import is not a function
at t.loadFactory (build.js:6)
at t.load (build.js:6)
at t.loadModuleFactory (build.js:12)
I tried including SystemJS in the production build but it could not find the separate module file app/account/admin/admin.module.ngfactory - after rollup everything is in one build.js. There may be a way to have separate rollups build each submodule, but that's a lot of work.
I found the suggestion of referring to an exported function:
export function loadAdminModule() {
return AdminModule;
}
loadChildren: loadAdminModule
This works in development, but in production the runtime compiler is unavailable so it logs build.js:1 ERROR Error: Uncaught (in promise): Error: Runtime compiler is not loaded.
The helper function can be modified so it works in production by referencing the NgFactory instead, but this won't work in development.
import { AdminModuleNgFactory } from '../../../aot/src/app/account/admin/admin.module.ngfactory';
export function loadAdminModule() {
return AdminModuleNgFactory;
}
loadChildren: loadAdminModule
Is there a supported way of using loadChildren so that it will work with the instructions in the AOT cookbook? Is it better to use webpack instead?
For anyone having the same problem, here's the temporary workaround I'm using. Hopefully a better answer will come along soon.
I now define my submodules in a dedicated file, submodules.ts. I have two versions of this file, submodules-jit.ts for development, and submodules-aot.ts for AOT/rollup deployment to production. I gitignore submodules.ts and have added commands to my npm start and npm build:aot scripts that substitute in the right one.
// submodules-jit.ts
import { AdminModule } from './account/admin/admin.module'
export function adminModule(): any { return AdminModule; }
// submodules-aot.ts
import { AdminModuleNgFactory } from '../../aot/src/app/account/admin/admin.module.ngfactory'
import { AdminModule } from './account/admin/admin.module'
export function adminModule(): any { return AdminModuleNgFactory; }
export function adminModuleKeep(): any { return AdminModule; }
AdminModule must be referenced in the AOT file so it is preserved.
Then I use the adminModule function in my routes:
import { adminModule } from '../submodules'
{ path: 'admin', loadChildren: adminModule }
Finally for convenience, npm scripts drop in the correct file.
"build:aot": "cp src/submodules-aot.ts src/app/submodules.ts && ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
"start": "cp src/submodules-jit.ts src/app/submodules.ts && concurrently \"npm run build:watch\" \"npm run serve\""
Needless to say this is a horrible hack, but it keeps the routing files clean and most of the evil in one place.
In my case I solved with your hint on loading routes from an external module, then reading this issue on angular/cli issue page.
So, I came out refactoring my routes from:
import { TestModule } from './pathToModule/test.module';
export function exportTestModule() {
return TestModule;
}
. . .
{
path: 'test',
loadChildren: exportTestModule
}
To:
. . .
{
path: 'test',
loadChildren: './pathToModule#TestModule'
}

JASMINE not defined when I try to run Karma test runner

I am trying to hook up the Karma test runner, using this seed project as a model.
I pull the seed project in, build it, and the test runner works great.
When I edit the karma.conf.js config file to start including the files from my project, and move it to my current setup (outside the seed project), I get this error:
Running "karma:dev" (karma) task
ERROR [config]: Error in config file!
[ReferenceError: JASMINE is not defined]
ReferenceError: JASMINE is not defined
at module.exports (C:\dev_AD_2014.01_PHASE1\config\karma-dev.conf.js:4:7)
...
I think I see what it's complaining about... in the seed project, it's karma config file is of an older format, that must have JASMINE and JASMINE_ADAPTER defined somewhere:
Seed Project karma config snippet
files = [
JASMINE,
JASMINE_ADAPTER,
'../app/lib/angular/angular.js',
'lib/angular/angular-mocks.js',
'../app/js/*.js',
....
];
exclude = ['karma.conf.js'];
...
My newer setup uses all the latest grunt plugins, and wants the config file wrapped in a module definition like so:
My karma config snippet
module.exports = function(config) {
config.set({
files: [
JASMINE,
JASMINE_ADAPTER,
// library and vendor files
'../dev/vendor/**/*.js'
'../dev/app/**/*.js'
],
exclude: ['**/*.e2e.js', '../config/*.js'],
reporters: ['progress'],
...
So it seems the problem is clear: the newer version(s) of some grunt plugins expect the modular definition, but are longer is setting up JASMINE, etc, as variables that are defined. That's my guess, but I'm a little lost on how to resolve this. I don't want to use the version of Karma that comes with the seed project if I can help it... I think it's version 0.4.4. I believe the newest stable version is 0.10.x.
What am I doing wrong?
Thanks!
If you want to use the latest stable Karma version (0.10.9) you should define Jasmine in the frameworks section and be sure to have karma-jasmine in the plugins section, in your karma configuration file.
Here's an example config file:
karma.conf.js
module.exports = function(config){
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// list of files / patterns to load in the browser
files: [
{pattern: 'app/**/*.js', watched: true, included: true, served: true}
],
// list of files to exclude
exclude: [
],
preprocessors: {
},
proxies: {
},
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
autoWatch: true,
// frameworks to use
frameworks: ['jasmine'],
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: [
'Chrome'
],
plugins: [
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-script-launcher',
'karma-jasmine'
],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
Source: Karma-runner docs
Including JASMINE and JASMINE_ADAPTER in the files array is applicable to Karma versions 0.8.x and down. With newer versions of Karma, that is version 0.13 currently, just remove those 2 lines from the files array since you are already loading Jasmine as the framework(framework=['jamsine']).

Resources