Adding a New Gemstone Library
Philosophies
As its name infers, the Gemstone Libraries site is for “libraries”, i.e., sets of reusable code that can be packaged and referenced by other libraries and applications. As such, an “application” project is not commonly a suitable project type. However, an exception to this rule is that the application is directly related to a particular Gemstone library; case in point: pqdif-explorer
. Also, it is certainly fine if libraries contain helper applications as part of their source code, but the primary project should normally be a library, i.e., <OutputType>Library</OutputType>
.
Each new library in Gemstone should be as standalone as possible to make it readily accessible as a package and usable by a variety of projects. It is OK to reference other Gemstone libraries as well as other packages, but this should be limited to exactly what is needed. External package sources should be limited to either NuGet or GitHub.
When choosing external packages to reference, care should be taken to evaluate the source quality. Consequently, only libraries that are open source should be used so that source quality can be evaluated. Additionally, make sure the license of referenced packages is compatible with the Gemstone MIT license.
Currently Gemstone libraries target .NET Standard 2.1, in addition to .NET 7.0, to make the library more widely accessible. However, it is expected that this code-base will eventually only target newer versions of .NET and the standard libraries will be abandoned so code can properly accommodate new language and runtime features that may not be available to .NET Standard.
Ideally Gemstone libraries should target multiple frameworks to accommodate more deployment options. As new C# and/or .NET features become available that improve a library’s security, performance, or portability, dropping older less used target frameworks should be preferred to using #if/#else/endif
preprocessor directives for multiple code implementations, as this becomes more difficult to maintain. If the change separates one or more highly used framework targets, use your best judgment, as a primary goal is always to make the library widely usable.
Create new Gemstone Library based on Template
- Create a new repo based on Gemstone.GemTem Template
- Description should be similar to “Gemstone Security Library”
- Once template is created, clone locally and run “RenameProject.bat” script
- Type a PascalCase named like “Security” (no quotes)
- After renaming completes, delete “RenameProject.bat” file and “build /tools” folder in new repo
- Commit renamed project with a message like “Renamed template to Gemstone.Security”, and push to GitHub
- Click on “Settings” from repo home page on GitHub, then
- Click “Edit” under Social preview and select “Upload an image…” and select “docs/img/gemstone-social-preview.png” from new repo
- Select “master branch / docs folder” under GitHub Pages Source
- Click “Collaborators & teams” tab on the left, then click “Add a team” and select “Dev Team” from the list
- Change the “Dev Team” permission level to “Write” - this gives developers write access to this repo
- From repo home page on GitHub, click on “environment” then click on “View deployment”
- Copy URL for repo’s GitHub pages site, should be similar to https://gemstone.github.io/security/
- Return to repo home page on GitHub and click the “Edit” button (will be to right of repo description, like “Gemstone Security Library”)
- Paste in GitHub pages URL under “Website” and click “Save”
- Add new repository name, e.g.,
security
, to repos.txt in build dependency order
Add New Library to Root Development Solution
- Open “…\gemstone\root-dev\Gemstone.sln” from Visual Studio
- Right-click on root “Gemstone” solution in “Solution Explorer” and select “Add > New Solution Folder” - name should match repo, PascalCase
- Right-click on new repo solution folder and select “Add > Existing Project…” for each of the following C# project files similar to the following:
- “…\gemstone\security\src\gemstone.security\Gemstone.Security.csproj”
- “…\gemstone\security\src\UnitTests\Gemstone.Security.UnitTests.csproj”
- Right-click on new repo solution folder and select “Add > Existing Item…” for “…\gemstone\security\docs\README.md”. Repeat for:
- “…\gemstone\security\appveyor.yml”
- “…\gemstone\security.github\workflows\codeql-analysis.yml”
- Now remove the
Debug
andRelease
configurations that were added to the solution:- Open the
Configuration Manager...
from Visual Studio - Select the drop-down for “Active solution configuration:” and select
<Edit...>
- Remove the
Debug
andRelease
configurations, leaving onlyDevelopment
- Save configuration updates and save Visual Studio
- Open the
- Failing to remove the
Debug
andRelease
build configurations will cause new clones ofroot-dev
to auto-open theDebug
build configuration which causes NuGetpackage
based references instead of desiredproject
based references for cross-project debugging - defeating the purpose of the solution. See Relative Project Paths info. - Commit updates with a message like “Added Gemstone.Security project to root-dev solution with project-based references”
- Check-in updates
Setup Continuous Integration Process for New Library
- Project should be added to AppVeyor for build testing and configured with similar settings to another Gemstone project, e.g., Gemstone.Common
- Once the AppVeyor project exists, click on “Badges” under “Settings” and copy the “Sample markdown code”
- Edit “docs/README.md” on the repo and update the “Build status” link with the copied markdown
Updated Documentation for New Library
Note that build documentation will require Sandcastle Help File Builder tools and visual studio plug-in. Make sure this tool is installed before proceeding with documentation.
- Update “docs/README.md” in the repo to properly describe library purpose (you can update class links later)
- Assuming some code with XML comments has been added, open local solution file, e.g., “…\gemstone\security\src\Gemstone.Security.sln”
- Build Gemstone library, then navigate to “docs/help” in the solution and build the “docgen” project
- Monitor for warnings here - it will show you what documentation comments you may have missed
- You can check out your locally compiled documentation by navigating to “…\gemstone\security\docs\help" and opening “index.html” in a browser
- Check-in documentation when complete, GitHub pages will auto-deploy updates within a couple minutes
- After documentation has been posted, update “docs/README.md” home page again and add a few links to commonly used library classes
- Note that the home page content of the automated documentation comes from the shared-content repo, if the new library should be added to the list,
- Add link to common.tokens
- Shared content updates will be rolled into all Gemstone library repos as part of the nightly build process
Old Steps for Manual Removal of Debug/Release Build Configurations:
- Save solution and close Visual Studio
- Open “…gemstone\root-dev\Gemstone.sln” in a text editor, e.g., Notepad++
- Move the “Project” sections related to new repo to better alpha locations in file. Locate best peer section for each:
- First section will look similar to:
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Security", "Security", "{AC074377-1D21-43EA-8CC6-280FD0B613AD}" ProjectSection(SolutionItems) = preProject ..\security\docs\README.md = ..\security\docs\README.md EndProjectSection EndProject
- Second section will look similar to:
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gemstone.Security", "..\security\src\Gemstone.Security\Gemstone.Security.csproj", "{1D1987D0-3CA1-4FAA-839A-F3510FA3A4A4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gemstone.Security.UnitTests", "..\security\src\UnitTests\Gemstone.Security.UnitTests.csproj", "{3DAC8F1B-00F9-4D83-B155-249D093662BC}" EndProject
- First section will look similar to:
- The root-dev solution is only for development purposes and Visual Studio will now have added all possible build configurations :-p
- Change the following:
GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Development|Any CPU = Development|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection
- To a section with only the
Development
build configuration:GlobalSection(SolutionConfigurationPlatforms) = preSolution Development|Any CPU = Development|Any CPU EndGlobalSection
- Change the following:
- Now remove all solution configurations related to
Debug
andRelease
leaving only build configurations forDevelopment
, for example:- The following:
{721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU {721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Development|Any CPU.ActiveCfg = Development|Any CPU {721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Development|Any CPU.Build.0 = Development|Any CPU {721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU {721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Release|Any CPU.Build.0 = Release|Any CPU {41B5D5D3-9A97-48ED-840C-188A0CA95480}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41B5D5D3-9A97-48ED-840C-188A0CA95480}.Debug|Any CPU.Build.0 = Debug|Any CPU {41B5D5D3-9A97-48ED-840C-188A0CA95480}.Development|Any CPU.ActiveCfg = Development|Any CPU {41B5D5D3-9A97-48ED-840C-188A0CA95480}.Development|Any CPU.Build.0 = Development|Any CPU
- Would become:
{721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Development|Any CPU.ActiveCfg = Development|Any CPU {721D3830-2CD7-45DE-A288-4FAF1D53CEC6}.Development|Any CPU.Build.0 = Development|Any CPU {41B5D5D3-9A97-48ED-840C-188A0CA95480}.Development|Any CPU.ActiveCfg = Development|Any CPU {41B5D5D3-9A97-48ED-840C-188A0CA95480}.Development|Any CPU.Build.0 = Development|Any CPU
- The following:
- Complete all
Debug
andRelease
removals:- From
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- To associated
EndGlobalSection
- From
- Re-open
root-dev
“Gemstone.sln” solution file to verify that the manual changes succeeded