Swift Package Manager Public Headers with Complicated Layouts - swift

I have a sample Swift Package Manager package (let's call it TestPackage), that is structured in the following way:
TestPackage/
Sources/
TestPackage/
Services/
Services.h
Services.m
TestPackageUI/
UIComponent1.h
UIComponent1.m
UIComponent2.h
UIComponent2.m
include/
TestPackage.h (umbrella header)
The contents of my TestPackage.h look something like this:
/// Umbrella header
/// Services
#import "Services.h" // (or "Services/Services.h")
/// TestPackageUI
#import "Component1.h" // (or "TestPackageUI/Component1.h")
#import "Component2.h" // (or "TestPackageUI/Component2.h")
What I want is that users of this package can do import this package into objc/swift and use the Services and TestPackageUI. They could do something such as:
Objective-C:
#import TestPackage;
/// or
#import <TestPackage.h>
Swift:
import TestPackage
The SPM Usage documentation says:
In case of complicated include layouts or headers that are not compatible with modules, a custom module.modulemap can be provided in the include directory.
So I added a module.modulemap in the include directory with the following content:
module TestPackage {
header "TestPackage.h"
export *
}
But when I try to use this package, the umbrella header TestPackage.h cannot find the header files it includes. Note that these sub-directories are added as headerSearchPaths in the C Settings of the target. I would like to maintain the same project structure. Can anyone help with the correct way to write a modulemap that works with this layout? Thanks in advance.

Related

How to exclude UnityEditor reference from asmdef?

How to exclude UnityEditor reference from asmdef?
Why I need it:
I have an asmdef file. For example, it is MyAssembly/MyAssembly.asmdef. The MyAssembly contains a lot of features and each feature staff is placed in its own folder. And some of these features has a code that is needed only in editor, and it refers to UnityEditor namespace. Such editor code is placed into an Editor folder.
But as you know, Editor folder name means nothing in terms of asmdef usage. So I add AssemblyDefenitionReference in each folder and refer it to the MyAssemblyEditor.asmdef assembly definition. So the paths looks like this:
MyAssembly/MyAssembly.asmdef
MyAssembly/Editor/MyAssemblyEditor.asmdef - this folder contains no code. It's needed just to place asmdef, because it's not allowed to place two asmdefs in a single folder.
MyAssembly/SomeFeature/Editor/*feature editor staff*
MyAssembly/SomeFeature/Editor/Editor.asmref - refers to MyAssemblyEditor.asmdef
MyAssembly/SomeFeature/*feature staff*
All this works good. But the problem is that, when some developer adds a new feature, he can forget to add a reference to the MyAssemblyEditor.asmdef in the editor folder. And there are no any errors will be shown in this case. This mistake will be revealed only when the build will be cooked. But I'd like that using of UnityEditor in MyAssembly will be instantly marked as an error.
Feel free to suggest other solution for this problem.
This thread got me thinking I can use CsprojPostprocessor to remove all references to UnityEditor from my csproj file. I wrote such class:
using System.Text.RegularExpressions;
using UnityEditor;
// ReSharper disable once CheckNamespace
public class CsprojPostprocessor : AssetPostprocessor
{
public static string OnGeneratedCSProject(string path, string content)
{
if (!path.EndsWith("Editor.csproj") && !path.EndsWith("Tests.csproj"))
{
var newContent =
Regex.Replace(content, "<Reference Include=\"UnityEditor(.|\n)*?</Reference>", "");
return newContent;
}
return content;
}
}
It also can be done with an xml parser or something.
The only thing, that confuse me is that this mechanism is badly documented and doesn't look like something simple users should use. So I use it at my own risk, but looks like there is no guarantee it will be strongly supported in future.

Importing multiple scss files

I am trying to import multiple scss files into my Vue2 project however I am getting errors on compilation - I suspect this is possible, its just my implementation is wrong...
My 'main.scss' file is imported into 'index.js' using the following line:
import './styles/main.scss'
Then, in my 'main.scss' file I have the following:
#import "./base.scss";// color pallete
#import "./variants.scss"; //variant colors using primary colors from base.scss
'base.scss' looks like the following:
$slim-color-brand-orange: #e87820;
$slim-color-brand-blue: #004a79;
$slim-color-brand-charcoal: #595a59;
'variants.scss' looks like the following:
$slim-color-brand-orange-light: lighten($slim-color-brand-orange, 15%);
$slim-color-brand-blue-light: lighten($slim-color-brand-blue, 15%);
$slim-color-brand-charcoal-light: lighten($slim-color-brand-charcoal, 15%);
However the error that I receive looks like the following:
Undefined variable: "$slim-color-brand-light-blue-l5"
Below is an example of how I use the variables:
background-color: $color-error-background;
Can anybody tell me what I am doing wrong? - Thanks in advance ;)
This should work as long as your background-color: $color-error-background is in your main.scss file, after the import statement.
Base and Variants contains variables. Any scss file that imports them, will be able to access those variables.
I think the issue may be the import into index.js.

#include of a system header from a modularized project header file gives "Include of non-modular header inside framework module..." error

I am trying to embed libarchive in a Swift-based framework I am building.
I created a module map to privately include archive.h (inside module libarchive near the end)
framework module X
{
requires objc, blocks, objc_arc
umbrella header "X.h"
private header "XPrivate.h"
private header "x.h"
use Darwin.C
module libarchive
{
private header "archive.h"
export *
}
}
Inside archive.h, the following line is causing the error:
#include <inttypes.h>
I don't understand why this include isn't being mapped to the correct inttypes module in my SDK.
There is a module Darwin.C.inttypes is defined inside my SDK, here:
/Applications/Xcode.app/.../MacOSX10.12.sdk/usr/include/module.modulemap
Can someone tell me how to get the #include in archive.h to map to the declared module?
Pretend to be a system framework by changing to framework module X [system].
Not the correct solution but it seems to work.

Swift #import of module '<module name>' in implementation of <Project name>; use #import

I'm trying to create a mixed ObjC-Swift framework. But I'm losing a lot of hairs trying to make a private module for my Swift files.
I followed some steps in iOS mixed dynamic framework - bridge objc headers with private module combined with some steps in https://stackoverflow.com/a/36878037/749438
Basically I have a module.modulemap now which has the following content:
module MyCore { //Adding 'framework' before module is giving me an "Umbrella not found"-error :/
umbrella header "MyCore.h"
export *
module * { export * }
explicit module MyCorePrivate {
header "MyCore_PrivateUmbrella.h"
export *
}
}
The MyCore_PrivateUmbrella.h imports all headers I want to privately expose to my Swift code. The reason behind it is just that it's easier to include 1 header in the module then all the to-be-exposed headers (since you need to include the specific paths to the headers...).
My build settings look like:
DEFINES_MODULE: YES
PRODUCT_MODULE_NAME: MyCore
CLANG_ENABLE_MODULES: YES
SWIFT_OBJC_INTERFACE_HEADER_NAME: MyCore-Swift.h
SWIFT_INCLUDE_PATHS: path to the directory of the module.modulemap
and last but not least; ALWAYS_SEARCH_USER_PATHS is set to NO
In my Swift files I import the module using import MyCore.MyCorePrivate. This works as expected and I can use my code from Objective-C.
Building the project gives me an error like this (the black bars only hide the project name and path to the file):
Now clicking the error brings me to the generated MyCore-Swift.h where the #import MyCore.MyCorePrivate is seemingly wrong.
I've got no idea as of why it's wrong, neither do I know how to fix this. Especially since it's a file generated by XCode.
Does anyone knows what's going down here?
You will need to modify the resulting framework after building it:
1) Don't create any private modules. Revert back to default settings.
2) Any code you want to expose to swift add to your framework header and make sure the headers are set as public in the build section or else swift code wont have access. (Use the <> syntax)
3) Any code from swift to objc make public.
4) Compile you project
5) go to your framework build directory (i.e MyFramework.framework)
6) open the framework header file in the headers directory of the framework (Myframework.h file)
7) Delete all the import statements that should have been private from the framework header
8) Delete all the .h files for the headers that should have been private from the headers directory ( you removed the import statements from the main framework header)
9) go to the .module file and remove the swift modules section
The module file should be very bare bones:
framework module MyFramework {
umbrella header "MyFramework.h" export * module * {export *}}

How to override an HTML file in a custom module

I am developing a custom module for a payment method in magento 2. Currently I am using cc-form.html from the vendor directory and the module is working fine. see below path.
vendor/magento/module-payment/view/frontend/web/template/payment/cc-form.html
Is there any way to override the HTML file?
Yes, there is. You can look in pub static to see how path to static asset constructed.
How it works
Every asset is accessible from the page by itenter code heres "RequireJS ID". It similar to real path, but varied.
For example file http://magento.vg/static/adminhtml/Magento/backend/en_US/Magento_Theme/favicon.ico.
It's real path is /app/code/Magento/Theme/view/adminhtml/web/favicon.ico.
It's RequireJS ID is Magento_Theme/favicon.ico. This means that file could be accessible via require("text!Magento_Theme/favicon.ico") or similar command.
You can find that RequireJS ID consist with module name and useful part of path (after folder web).
How can I replace a file
So you have file
vendor/magento/module-payment/view/frontend/web/template/payment/cc-form.html
On the page it loaded with src as
http://magento.vg/static/frontend/Magento/luma/en_US/Magento_Payment/template/payment/cc-form.html
So its RequireJS ID is
Magento_Payment/template/payment/cc-form.html
Side note: Inside UI components stuff it equals to Magento_Payment/payment/cc-form. Words "template" and ".html" are added automatically.
And now you can replace this file for application via RequireJS config
var config = {
"map": {
"*": {
"Magento_Payment/template/payment/cc-form.html":
"<OwnBrand>_<OwnModule>/template/payment/cc-form.html"
}
}
};
This code snippet you place in requirejs-config.js file in your module. That is all.