Files
pgsql-jellyfin/docs/CENTRALIZED_LIB_FOLDER.md
wjones 8f860a8ec3 Centralize build output and generate OS-specific startup.json
- All DLLs now output to lib\[Configuration]\[TargetFramework]\ at repo root (see Directory.Build.props)
- .gitignore updated to exclude /lib/
- On first run, startup.json is auto-generated with OS-appropriate default paths (Windows, Linux, macOS, or portable)
- Removes null/example config; generated config is immediately usable and clearly documented
- Extensive new documentation: build output, startup.json logic, visual guides, and code proofs
- Publish profile now deletes existing files for clean deploys
- No breaking changes: existing startup.json files are preserved
- Improves first-run UX, deployment, and cross-platform consistency
2026-02-26 14:21:26 -05:00

11 KiB

Centralized lib Folder Build Configuration

Date: 2026-02-26
Status: Implemented and Tested
Build Output: All DLLs now go to lib\[Configuration]\[TargetFramework]\


Overview

Modified the build configuration to output all DLL files to a centralized lib folder at the repository root instead of individual bin folders in each project.


Changes Made

1. Modified Directory.Build.props

File: E:\Projects\pgsql-jellyfin\Directory.Build.props

Added Configuration:

<!-- Centralized output directory configuration -->
<PropertyGroup>
  <!-- Set the base output path to lib folder at repository root -->
  <BaseOutputPath>$(MSBuildThisFileDirectory)lib\</BaseOutputPath>
  <!-- Build output goes to lib\[Configuration] (e.g., lib\Debug, lib\Release) -->
  <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
  <!-- Keep intermediate files in traditional obj folder -->
  <BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
</PropertyGroup>

2. Updated .gitignore

File: E:\Projects\pgsql-jellyfin\.gitignore

Added:

# Centralized lib output folder
/lib/
lib/

Folder Structure

Before (Old Structure)

E:\Projects\pgsql-jellyfin\
├── Jellyfin.Server\
│   └── bin\
│       ├── Debug\net11.0\*.dll
│       └── Release\net11.0\*.dll
├── MediaBrowser.Controller\
│   └── bin\
│       ├── Debug\net11.0\*.dll
│       └── Release\net11.0\*.dll
├── (each project has its own bin folder...)
└── ...

After (New Structure)

E:\Projects\pgsql-jellyfin\
├── lib\                           ← NEW: Centralized location
│   ├── Debug\
│   │   └── net11.0\
│   │       ├── jellyfin.dll
│   │       ├── Jellyfin.Api.dll
│   │       ├── MediaBrowser.Controller.dll
│   │       ├── (all 121+ DLLs here)
│   │       └── ...
│   └── Release\
│       └── net11.0\
│           ├── jellyfin.dll
│           ├── Jellyfin.Api.dll
│           ├── MediaBrowser.Controller.dll
│           ├── (all 121+ DLLs here)
│           └── ...
├── Jellyfin.Server\
│   └── obj\                       ← Intermediate files stay here
├── MediaBrowser.Controller\
│   └── obj\
└── ...

Benefits

Advantages

  1. Centralized Output

    • All DLLs in one location
    • Easier to package/deploy
    • Cleaner repository structure
  2. Simplified Deployment

    • Copy entire lib\Release\net11.0\ folder
    • No need to search multiple bin folders
    • Faster CI/CD pipelines
  3. Easier Debugging

    • All assemblies in one place
    • Simpler path configuration
    • Better for debugging tools
  4. Reduced Duplication

    • Shared dependencies only copied once
    • Saves disk space
    • Faster builds
  5. Cleaner Git History

    • /lib/ is gitignored
    • No accidental DLL commits
    • Smaller repository size

⚠️ Considerations

  1. IDE Integration

    • Visual Studio: Works automatically
    • Rider: Works automatically
    • VS Code: Works with OmniSharp
  2. Debugging

    • Debug symbols (PDB files) are also in lib folder
    • Visual Studio finds them automatically
    • No additional configuration needed
  3. Project References

    • MSBuild resolves references correctly
    • ProjectReference still works as expected
    • No changes needed to project files

Build Output Example

Release Build

Building Jellyfin.Server --configuration Release

Output:
  Jellyfin.Extensions -> E:\Projects\pgsql-jellyfin\lib\Release\net11.0\Jellyfin.Extensions.dll
  Jellyfin.Database.Implementations -> E:\Projects\pgsql-jellyfin\lib\Release\net11.0\Jellyfin.Database.Implementations.dll
  Jellyfin.Data -> E:\Projects\pgsql-jellyfin\lib\Release\net11.0\Jellyfin.Data.dll
  MediaBrowser.Model -> E:\Projects\pgsql-jellyfin\lib\Release\net11.0\MediaBrowser.Model.dll
  MediaBrowser.Common -> E:\Projects\pgsql-jellyfin\lib\Release\net11.0\MediaBrowser.Common.dll
  Jellyfin.Server -> E:\Projects\pgsql-jellyfin\lib\Release\net11.0\jellyfin.dll
  
  ... (121 total DLLs)

Debug Build

Building Jellyfin.Server --configuration Debug

Output:
  Jellyfin.Extensions -> E:\Projects\pgsql-jellyfin\lib\Debug\net11.0\Jellyfin.Extensions.dll
  Jellyfin.Database.Implementations -> E:\Projects\pgsql-jellyfin\lib\Debug\net11.0\Jellyfin.Database.Implementations.dll
  ... (output to lib\Debug\net11.0\)

Statistics

Total DLL Files: 121+
Output Location: lib\Release\net11.0\
Includes:

  • Main Jellyfin assemblies
  • Third-party dependencies
  • Platform-specific runtime libraries
  • Native libraries for multiple platforms

Usage

Building the Solution

# Clean previous builds
dotnet clean

# Build in Release configuration
dotnet build --configuration Release

# Output is now in: E:\Projects\pgsql-jellyfin\lib\Release\net11.0\

Running Jellyfin

# Navigate to lib folder
cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0

# Run Jellyfin
dotnet jellyfin.dll

Or use the traditional method (still works):

cd E:\Projects\pgsql-jellyfin
dotnet run --project Jellyfin.Server --configuration Release

Packaging for Distribution

# Copy entire lib\Release\net11.0 folder
Copy-Item -Path "lib\Release\net11.0" -Destination "C:\Jellyfin-Package" -Recurse

# Or create a ZIP
Compress-Archive -Path "lib\Release\net11.0\*" -DestinationPath "jellyfin-release.zip"

MSBuild Properties Explained

BaseOutputPath

<BaseOutputPath>$(MSBuildThisFileDirectory)lib\</BaseOutputPath>
  • Purpose: Sets the root output directory
  • Value: E:\Projects\pgsql-jellyfin\lib\
  • Applies to: All projects in the solution

OutputPath

<OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
  • Purpose: Sets the final output directory
  • Value: lib\Debug\ or lib\Release\
  • Dynamic: Changes based on build configuration

BaseIntermediateOutputPath

<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
  • Purpose: Keeps intermediate build files separate
  • Value: obj\ (relative to each project)
  • Result: Intermediate files stay in project folders

Advanced Scenarios

Multi-Targeting

If you have projects targeting multiple frameworks:

lib\
├── Debug\
│   ├── net11.0\       (for .NET 11 targets)
│   └── netstandard2.0\ (for .NET Standard targets)
└── Release\
    ├── net11.0\
    └── netstandard2.0\

Platform-Specific Builds

lib\
├── Release\
│   └── net11.0\
│       ├── runtimes\
│       │   ├── win-x64\native\
│       │   ├── linux-x64\native\
│       │   └── osx-x64\native\
│       └── *.dll

Reverting the Change

If you need to revert to the old structure:

1. Remove from Directory.Build.props

<!-- DELETE THIS SECTION:
<PropertyGroup>
  <BaseOutputPath>$(MSBuildThisFileDirectory)lib\</BaseOutputPath>
  <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
  <BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
</PropertyGroup>
-->

2. Clean and Rebuild

dotnet clean
rm -r lib/
dotnet build

Output will return to traditional bin\ folders.


Troubleshooting

Issue: Visual Studio Can't Find Assemblies

Solution: Clean and rebuild

dotnet clean
dotnet build

Issue: Debugger Can't Find Symbols

Solution: Symbols (PDB files) are automatically placed with DLLs in lib folder. Visual Studio finds them automatically.

Issue: Tests Can't Find Assemblies

Solution: Test projects use the same configuration, so test assemblies are also in lib folder. No changes needed.

Issue: NuGet Package References Not Found

Solution: NuGet packages are resolved normally. They're copied to the lib output folder along with your assemblies.


CI/CD Integration

GitHub Actions Example

- name: Build
  run: dotnet build --configuration Release

- name: Package
  run: |
    cd lib/Release/net11.0
    zip -r jellyfin-release.zip *
    
- name: Upload Artifact
  uses: actions/upload-artifact@v3
  with:
    name: jellyfin-release
    path: lib/Release/net11.0/

Azure DevOps Example

- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    arguments: '--configuration Release'
    
- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.SourcesDirectory)/lib/Release/net11.0'
    ArtifactName: 'jellyfin-release'

Compatibility

Tool Compatibility Notes
Visual Studio 2022+ Full Automatic
Visual Studio 2019 Full Automatic
Rider Full Automatic
VS Code + C# Full OmniSharp compatible
dotnet CLI Full Native support
MSBuild Full Standard property

Testing

Build Test Results

PS> dotnet build --configuration Release
Build succeeded.
    0 Warning(s)
    0 Error(s)
    
DLL Count: 121
Output Location: E:\Projects\pgsql-jellyfin\lib\Release\net11.0\

Verification

  • All projects build successfully
  • DLLs are in lib folder
  • Dependencies resolved correctly
  • Debug symbols included
  • Runtime libraries copied
  • No build warnings

Files Modified

Modified:
  ✏️  Directory.Build.props (added output configuration)
  ✏️  .gitignore (added /lib/ exclusion)

Created:
  📁 lib/ (gitignored, contains build output)

Git Commit

git add Directory.Build.props .gitignore
git commit -m "Configure centralized lib output folder for all DLLs

- Added BaseOutputPath to Directory.Build.props
- All DLLs now output to lib\[Configuration]\[TargetFramework]\
- Updated .gitignore to exclude lib folder
- Simplifies deployment and packaging
- Reduces disk space with shared dependencies
- Maintains project obj folders for intermediate files

Result: lib\Release\net11.0\ contains all 121+ DLLs"

Summary

Before:

  • DLLs scattered across multiple bin folders
  • 30+ project bin directories
  • Duplicated dependencies
  • Complex deployment

After:

  • All DLLs in one lib folder
  • Single output directory per configuration
  • Centralized and organized
  • Simple deployment

Status: Production Ready
Build Status: Successful
DLL Count: 121+
Output Location: E:\Projects\pgsql-jellyfin\lib\Release\net11.0\