Skip to content

Commit

Permalink
Create new arch module template: cpp-lib (#12481)
Browse files Browse the repository at this point in the history
## Description

Adds a new `cpp-lib` template designed to be applied on top of the new projects created by the (now recommended) `create-react-native-library` script. Also updates the `cpp-app` template to be able to autolink and run these new libraries.

### Type of Change
- New feature (non-breaking change which adds functionality)
- This change requires a documentation update

### Why
Devs need to add windows support to native modules in a way which can be consumed by the new arch RNW apps (i.e. the `cpp-app` template).

Resolves #12480

### What
Create a new `cpp-lib` template which can be applied on top of the template created by `npx  create-react-native-library`, adding Windows support for a turbo module. It will also automatically apply the `cpp-app` template to the example project if it exists.

## Screenshots
<img width="441" alt="image" src="https://github.com/microsoft/react-native-windows/assets/10852185/f5f31727-a233-419c-8afe-ad91f797abb2">


## Testing
Verified the new template could be applied to a fresh library created by `create-react-native-library` and that example app autolinks, builds, and runs correctly.

## Changelog
Should this change be included in the release notes: yes

Created a new arch module template: cpp-lib
  • Loading branch information
jonthysell committed Jan 18, 2024
1 parent e2ee456 commit 6164875
Show file tree
Hide file tree
Showing 35 changed files with 1,275 additions and 280 deletions.
30 changes: 30 additions & 0 deletions .ado/jobs/cli-init-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ parameters:
configuration: Debug
platform: x86
additionalRunArguments: --no-autolink
- Name: FabricLibX64Release
template: cpp-lib
configuration: Release
platform: x64
additionalRunArguments:
- Name: FabricLibX86Debug
template: cpp-lib
configuration: Debug
platform: x86
additionalRunArguments:
- BuildEnvironment: Continuous
Matrix:
- Name: FabricX64Debug
Expand All @@ -44,6 +54,26 @@ parameters:
configuration: Release
platform: x86
additionalRunArguments: --no-autolink
- Name: FabricLibX64Debug
template: cpp-lib
configuration: Debug
platform: x64
additionalRunArguments:
- Name: FabricLibX64Release
template: cpp-lib
configuration: ReleaseLib
platform: x64
additionalRunArguments:
- Name: FabricLibX86Debug
template: cpp-lib
configuration: Debug
platform: x86
additionalRunArguments:
- Name: FabricLibX86Release
template: cpp-lib
configuration: Release
platform: x86
additionalRunArguments:
jobs:
- ${{ each config in parameters.buildMatrix }}:
- ${{ if eq(config.BuildEnvironment, parameters.buildEnvironment) }}:
Expand Down
83 changes: 55 additions & 28 deletions .ado/templates/react-native-init-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,49 +40,70 @@ steps:
- ${{ if endsWith(parameters.template, '-app') }}:
- script: |
npx --yes react-native@$(reactNativeDevDependency) init testcli --template react-native@$(reactNativeDevDependency)
displayName: Init new app project
displayName: Init new app project with react-native init
workingDirectory: $(Agent.BuildDirectory)
- ${{ if endsWith(parameters.template, '-lib') }}:
- script: |
npx --yes create-react-native-module@0.20.2 --package-name "testcli" testcli
displayName: Init new lib project
npx --yes create-react-native-library@latest --slug testcli --description testcli --author-name "React-Native-Windows Bot" --author-email 53619745+rnbot@users.noreply.github.com --author-url http://example.com --repo-url http://example.com --languages java-objc --type module-new --react-native-version $(reactNativeDevDependency) testcli
displayName: Init new lib project with create-react-native-library
workingDirectory: $(Agent.BuildDirectory)
- script: |
rmdir /s /q android
displayName: Remove broken android folder # See issue https://github.com/microsoft/react-native-windows/issues/12209
workingDirectory: $(Agent.BuildDirectory)\testcli
- script: |
call yarn install
call yarn upgrade react@$(reactDevDependency) --dev
call yarn upgrade react-native@$(reactNativeDevDependency) --dev
displayName: Update project react and react-native dev versions
workingDirectory: $(Agent.BuildDirectory)\testcli
- script: |
call yarn add react-native-windows@$(npmVersion)
displayName: yarn add react-native-windows@$(npmVersion)
displayName: yarn install
workingDirectory: $(Agent.BuildDirectory)\testcli
env:
npm_config_registry: http://localhost:4873
YARN_ENABLE_IMMUTABLE_INSTALLS: false
- ${{ if endsWith(parameters.template, '-app') }}:
- script: |
call yarn upgrade react@$(reactDevDependency) --dev
call yarn upgrade react-native@$(reactNativeDevDependency) --dev
displayName: Update project react and react-native dev versions
workingDirectory: $(Agent.BuildDirectory)\testcli
- script: |
call yarn add react-native-windows@$(npmVersion)
displayName: yarn add react-native-windows@$(npmVersion)
workingDirectory: $(Agent.BuildDirectory)\testcli
env:
npm_config_registry: http://localhost:4873
- ${{ if endsWith(parameters.template, '-lib') }}:
- script: |
call yarn config set npmRegistryServer http://localhost:4873
call yarn config set unsafeHttpWhitelist --json "[\"localhost\"]"
call yarn add react-native-windows@$(npmVersion) --dev
call yarn add react-native-windows@* --peer
displayName: yarn add react-native-windows@$(npmVersion)
workingDirectory: $(Agent.BuildDirectory)\testcli
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
- script: |
call yarn react-native init-windows --template ${{ parameters.template }} --overwrite --logging ${{ parameters.additionalInitArguments }}
displayName: Call react-native init-windows
workingDirectory: $(Agent.BuildDirectory)\testcli
env:
npm_config_registry: http://localhost:4873
- ${{ if endsWith(parameters.template, '-app') }}:
- powershell: |
$path = (Get-ChildItem -Filter "Package.appxmanifest" -File -Recurse).FullName;
[xml] $manifest = Get-Content $path
$manifest.Package.Identity.Name = 'ReactNative.InitTest'
$manifest.Save("$path")
displayName: Set AppX package name to "ReactNative.InitTest"
- ${{ if endsWith(parameters.template, '-lib') }}:
- script: |
call yarn install
displayName: yarn install again
workingDirectory: $(Agent.BuildDirectory)\testcli
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
- powershell: |
$path = (Get-ChildItem -Filter "Package.appxmanifest" -File -Recurse).FullName;
[xml] $manifest = Get-Content $path
$manifest.Package.Identity.Name = 'ReactNative.InitTest'
$manifest.Save("$path")
displayName: Set AppX package name to "ReactNative.InitTest"
${{ if endsWith(parameters.template, '-app') }}:
workingDirectory: $(Agent.BuildDirectory)\testcli\windows
${{ if endsWith(parameters.template, '-lib') }}:
workingDirectory: $(Agent.BuildDirectory)\testcli\example\windows
# End npm test server
- template: verdaccio-stop.yml
Expand All @@ -95,7 +116,10 @@ steps:

- template: react-native-debug-info.yml
parameters:
workingDirectory: $(Agent.BuildDirectory)\testcli
${{ if endsWith(parameters.template, '-app') }}:
workingDirectory: $(Agent.BuildDirectory)\testcli
${{ if endsWith(parameters.template, '-lib') }}:
workingDirectory: $(Agent.BuildDirectory)\testcli\example

- template: ../templates/run-windows-with-certificates.yml
parameters:
Expand All @@ -105,7 +129,10 @@ steps:
buildPlatform: ${{ parameters.platform }}
deployOption: ${{ parameters.additionalRunArguments }}
buildLogDirectory: $(Build.BinariesDirectory)\${{ parameters.platform }}\${{ parameters.configuration }}\BuildLogs
workingDirectory: $(Agent.BuildDirectory)\testcli
${{ if endsWith(parameters.template, '-app') }}:
workingDirectory: $(Agent.BuildDirectory)\testcli
${{ if endsWith(parameters.template, '-lib') }}:
workingDirectory: $(Agent.BuildDirectory)\testcli\example
restoreLockedMode: false # Allow new lockfile to be created

- template: upload-build-logs.yml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Create new arch module template: cpp-lib",
"packageName": "react-native-windows",
"email": "jthysell@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@
<UseHermes>true</UseHermes>
</PropertyGroup>

<Target Name="EnsureUseWinUI3" BeforeTargets="PrepareForBuild" Condition="'$(UseWinUI3)' == 'false'">
<Warning Text="Property 'UseWinUI3' was set to 'false'. Projects built against Microsoft.ReactNative.Composition require UseWinUI3 and it will be set to true." />
</Target>

<PropertyGroup>
<UseWinUI3>true</UseWinUI3>
</PropertyGroup>

<Import Project="$(MSBuildThisFileDirectory)Microsoft.ReactNative.Common.props" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
This file will be consumed by ALL C++ Win32 module projects (both inside
and outside of this repo) that build on top of Microsoft.ReactNative.
Do not make any changes here unless it applies to ALL such projects.
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!--
Define SkipAddPriPayloadFilesToCopyToOutputDirectoryItems=true and GenerateLibraryLayout=false to avoid
conflicts with copying Microsoft.ReactNative XBF files by the native module DLLs and by Microsoft.ReactNative.
-->
<SkipAddPriPayloadFilesToCopyToOutputDirectoryItems>true</SkipAddPriPayloadFilesToCopyToOutputDirectoryItems>
<GenerateLibraryLayout>false</GenerateLibraryLayout>
</PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)Microsoft.ReactNative.Composition.Common.props" />
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\Codegen.props" />
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\NuGet.Cpp.props" />
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\WinUI.props" />
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\PackageVersionDefinitions.props" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
This file will be consumed by C++ ALL Win32 module projects (both inside
and outside of this repo) that build on top of Microsoft.ReactNative.
Do not make any changes here unless it applies to ALL such projects.
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Starting with the base of the UWP Cpp targets for now (until we need to start differentiating). -->
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.targets" />
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\Codegen.targets" />

<ItemGroup>
<PackageReference Include="boost" Version="1.76.0.0" />
<PackageReference Include="Microsoft.VCRTForwarders.140" Version="1.0.2-rc" />
</ItemGroup>

</Project>
2 changes: 0 additions & 2 deletions vnext/templates/cpp-app/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ const config = {
inlineRequires: true,
},
}),
// This fixes the 'missing-asset-registry-path` error (see https://github.com/microsoft/react-native-windows/issues/11437)
assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
},
};

Expand Down
15 changes: 7 additions & 8 deletions vnext/templates/cpp-app/template.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ const templateUtils = require('../templateUtils');
async function preInstall(config = {}, options = {}) {}

async function getFileMappings(config = {}, options = {}) {
const rnwPath = path.dirname(
require.resolve('react-native-windows', [config.root]),
);
const rnwVersion = require(path.join(rnwPath, 'package.json')).version;

const devMode = existsSync(path.join(rnwPath, 'src'));
const {rnwVersion, devMode} = templateUtils.getRnwInfo(config, options);

const projectName =
config?.project?.windows?.project?.projectName ?? options?.name ?? 'MyApp';
Expand All @@ -38,6 +33,10 @@ async function getFileMappings(config = {}, options = {}) {
const packageGuid = uuid.v4();
const currentUser = username.sync(); // Gets the current username depending on the platform.

const appJsonPath = path.join(config?.root ?? process.cwd(), 'app.json');
const mainComponentName =
(existsSync(appJsonPath) ? require(appJsonPath).name : null) ?? projectName;

const cppNugetPackages = [];

const replacements = {
Expand All @@ -50,7 +49,7 @@ async function getFileMappings(config = {}, options = {}) {

rnwVersion: rnwVersion,

mainComponentName: projectName, // TODO: replace with app.json name
mainComponentName,

// Visual Studio is very picky about the casing of the guids for projects, project references and the solution
// https://www.bing.com/search?q=visual+studio+project+guid+casing&cvid=311a5ad7f9fc41089507b24600d23ee7&FORM=ANAB01&PC=U531
Expand All @@ -61,7 +60,7 @@ async function getFileMappings(config = {}, options = {}) {
// packaging and signing variables:
packageGuidLower: `{${packageGuid.toLowerCase()}}`,
packageGuidUpper: `{${packageGuid.toUpperCase()}}`,
currentUser: currentUser,
currentUser,

devMode,

Expand Down
2 changes: 1 addition & 1 deletion vnext/templates/cpp-app/windows/ExperimentalFeatures.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<PropertyGroup Label="Microsoft.ReactNative Experimental Features">
<UseFabric>true</UseFabric>
<UseWinUI3>false</UseWinUI3>
<UseWinUI3>true</UseWinUI3>

<ReactExperimentalFeaturesSet>true</ReactExperimentalFeaturesSet>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// AutolinkedNativeModules.g.cpp contents generated by "react-native autolink-windows"
// clang-format off
#include "pch.h"
#include "AutolinkedNativeModules.g.h"{{ &autolinkCppIncludes }}

namespace winrt::Microsoft::ReactNative
{

void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::ReactNative::IReactPackageProvider> const& packageProviders)
{ {{ &autolinkCppPackageProviders }}
}

}
10 changes: 10 additions & 0 deletions vnext/templates/cpp-app/windows/MyApp/AutolinkedNativeModules.g.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// AutolinkedNativeModules.g.h contents generated by "react-native autolink-windows"
// clang-format off
#pragma once

namespace winrt::Microsoft::ReactNative
{

void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::ReactNative::IReactPackageProvider> const& packageProviders);

}
Loading

0 comments on commit 6164875

Please sign in to comment.