diff --git a/.idea/php.xml b/.idea/php.xml
index b37795f..71b8d6f 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/src/ncc/CLI/Commands/BuildCommand.php b/src/ncc/CLI/Commands/BuildCommand.php
index f7d9384..f2bff4f 100644
--- a/src/ncc/CLI/Commands/BuildCommand.php
+++ b/src/ncc/CLI/Commands/BuildCommand.php
@@ -78,7 +78,6 @@
$options[BuildConfigurationOptions::OUTPUT_FILE] = $output_path;
}
-
// Load the project
try
{
diff --git a/src/ncc/Classes/NccExtension/NccCompiler.php b/src/ncc/Classes/NccExtension/NccCompiler.php
index 84047af..e2e83e1 100644
--- a/src/ncc/Classes/NccExtension/NccCompiler.php
+++ b/src/ncc/Classes/NccExtension/NccCompiler.php
@@ -25,6 +25,7 @@
namespace ncc\Classes\NccExtension;
+ use ncc\Classes\PackageReader;
use ncc\Classes\PackageWriter;
use ncc\CLI\Main;
use ncc\Enums\Flags\PackageFlags;
@@ -43,6 +44,7 @@
use ncc\Objects\Package\Metadata;
use ncc\Objects\Package\Resource;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
+ use ncc\Objects\ProjectConfiguration\Dependency;
use ncc\Utilities\Base64;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
@@ -88,25 +90,26 @@
{
$configuration = $this->project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
$configuration->setOptions(array_merge($configuration->getOptions(), $options));
+ $static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES]);
if(count($options) > 0)
{
$configuration->setOptions(array_merge($configuration->getOptions(), $options));
}
- if($configuration->getOutputName() !== null)
+ if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
+ {
+ $package_path = ConstantCompiler::compileConstants(
+ $this->project_manager->getProjectConfiguration(), $configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
+ );
+ }
+ elseif($configuration->getOutputName() !== null)
{
$package_path =
ConstantCompiler::compileConstants($this->project_manager->getProjectConfiguration(), $configuration->getOutputPath())
. DIRECTORY_SEPARATOR .
ConstantCompiler::compileConstants($this->project_manager->getProjectConfiguration(), $configuration->getOutputName());
}
- elseif(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
- {
- $package_path = ConstantCompiler::compileConstants(
- $this->project_manager->getProjectConfiguration(), $configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
- );
- }
else
{
$package_path =
@@ -120,11 +123,18 @@
count($this->project_manager->getProjectConfiguration()->getExecutionPolicies()) +
count($this->project_manager->getComponents($build_configuration)) +
count($this->project_manager->getResources($build_configuration));
+
$package_writer = $this->createPackageWriter($package_path, $configuration);
-
Console::out(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()));
+ if($static_dependencies)
+ {
+ // Add the static dependencies flag so that the package manager
+ // Won't try to resolve the dependencies from the system.
+ $package_writer->addFlag(PackageFlags::STATIC_DEPENDENCIES);
+ }
+
// Debugging information
if(Resolver::checkLogLevel(LogLevel::DEBUG, Main::getLogLevel()))
{
@@ -193,31 +203,52 @@
$this->processResource($package_writer, $resource);
}
- $package_manager = new PackageManager();
-
// Add the project dependencies
foreach($this->project_manager->getProjectConfiguration()->getBuild()->getDependencies() as $dependency)
{
- if(isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES]))
- {
- $package_entry = $package_manager->getPackageLock()->getEntry($dependency->getName());
- $shadow_package = $package_entry->getShadowPackagePath($dependency->getVersion());
- // TODO: Add support for static dependencies
- }
-
- $package_writer->addDependencyConfiguration($dependency);
+ $this->processDependency($package_writer, $dependency, $static_dependencies);
}
// Add the build dependencies
foreach($configuration->getDependencies() as $dependency)
{
- $package_writer->addDependencyConfiguration($dependency);
+ $this->processDependency($package_writer, $dependency, $static_dependencies);
}
$package_writer->close();
return $package_path;
}
+ /**
+ * Processes dependencies, optionally recursively
+ *
+ * @param PackageWriter $package_writer
+ * @param Dependency $dependency
+ * @param bool $static
+ * @return void
+ * @throws IOException
+ */
+ private function processDependency(PackageWriter $package_writer, Dependency $dependency, bool $static=false): void
+ {
+ Console::outVerbose(sprintf('Processing dependency \'%s=%s\'', $dependency->getName(), $dependency->getVersion()));
+
+ /** @noinspection UnusedFunctionResultInspection */
+ $package_writer->addDependencyConfiguration($dependency);
+
+ if(!$static)
+ {
+ return;
+ }
+
+ $entry = (new PackageManager())->getPackageLock()->getVersionEntry($dependency->getName(), $dependency->getVersion());
+ $package_writer->merge((new PackageReader($entry->getShadowPackagePath($dependency->getName()))));
+
+ foreach($entry->getDependencies() as $sub_dependency)
+ {
+ $this->processDependency($package_writer, $sub_dependency, $static);
+ }
+ }
+
/**
* Creates a package writer with the specified options
*
diff --git a/src/ncc/Classes/PackageReader.php b/src/ncc/Classes/PackageReader.php
index eab31ca..b15fbf1 100644
--- a/src/ncc/Classes/PackageReader.php
+++ b/src/ncc/Classes/PackageReader.php
@@ -270,6 +270,34 @@
return fread($this->package_file, (int)$location[1]);
}
+ /**
+ * Returns a resource pointer from the package by name
+ *
+ * @param string $name
+ * @return int[]
+ */
+ public function getPointer(string $name): array
+ {
+ if(!isset($this->headers[PackageStructure::DIRECTORY][$name]))
+ {
+ throw new RuntimeException(sprintf('Resource \'%s\' not found in package', $name));
+ }
+
+ $location = explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
+ return [(int)$location[0], (int)$location[1]];
+ }
+
+ /**
+ * Returns True if the package contains a resource by name
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function exists(string $name): bool
+ {
+ return isset($this->headers[PackageStructure::DIRECTORY][$name]);
+ }
+
/**
* Returns a resource from the package by pointer
*
@@ -631,9 +659,9 @@
}
/**
- * @return false|int
+ * @return int
*/
- public function getHeaderLength(): false|int
+ public function getHeaderLength(): int
{
return $this->header_length;
}
diff --git a/src/ncc/Classes/PackageWriter.php b/src/ncc/Classes/PackageWriter.php
index 6660b87..d65d58e 100644
--- a/src/ncc/Classes/PackageWriter.php
+++ b/src/ncc/Classes/PackageWriter.php
@@ -38,6 +38,7 @@
use ncc\Objects\ProjectConfiguration\Dependency;
use ncc\Objects\ProjectConfiguration\Installer;
use ncc\Extensions\ZiProto\ZiProto;
+ use ncc\Utilities\Console;
class PackageWriter
{
@@ -351,6 +352,42 @@
$this->addPointer(sprintf('@%s:%s', PackageDirectory::CLASS_POINTER, $class), $offset, $length);
}
+ /**
+ * Merges the contents of a package reader into the package writer
+ *
+ * @param PackageReader $reader
+ * @return void
+ */
+ public function merge(PackageReader $reader): void
+ {
+ $processed_resources = [];
+
+ foreach($reader->getDirectory() as $name => $pointer)
+ {
+ switch((int)substr(explode(':', $name, 2)[0], 1))
+ {
+ case PackageDirectory::METADATA:
+ case PackageDirectory::ASSEMBLY:
+ case PackageDirectory::INSTALLER:
+ case PackageDirectory::EXECUTION_UNITS:
+ Console::outDebug(sprintf('Skipping %s', $name));
+ break;
+
+ default:
+ if(isset($processed_resources[$pointer]))
+ {
+ Console::outDebug(sprintf('Merging %s as a pointer', $name));
+ $this->addPointer($name, (int)$processed_resources[$pointer][0], (int)$processed_resources[$pointer][1]);
+ break;
+ }
+
+ Console::outDebug(sprintf('Merging %s', $name));
+ $processed_resources[$pointer] = $this->add($name, $reader->get($name));
+
+ }
+ }
+ }
+
/**
* Finalizes the package by writing the magic bytes, header length, delimiter, headers, and data to the file
*
diff --git a/src/ncc/Classes/PhpExtension/ExecutableCompiler.php b/src/ncc/Classes/PhpExtension/ExecutableCompiler.php
index 619fe36..c0dcb28 100644
--- a/src/ncc/Classes/PhpExtension/ExecutableCompiler.php
+++ b/src/ncc/Classes/PhpExtension/ExecutableCompiler.php
@@ -71,20 +71,20 @@
// Prepare the gcc command
$gcc_path = (new ExecutableFinder())->find('gcc');
- if($configuration->getOutputName() !== null)
- {
- $binary_path =
- ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutputPath())
- . DIRECTORY_SEPARATOR .
- ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutputName());
- }
- elseif(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
+ if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
{
$binary_path = ConstantCompiler::compileConstants(
$this->getProjectManager()->getProjectConfiguration(),
$configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
);
}
+ elseif($configuration->getOutputName() !== null)
+ {
+ $binary_path =
+ ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutputPath())
+ . DIRECTORY_SEPARATOR .
+ ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutputName());
+ }
else
{
$binary_path =
@@ -137,6 +137,22 @@
Console::outVerbose(sprintf('Compiling executable to %s: %s', $binary_path, implode(' ', $gcc_options)));
$process->run(static function ($type, $buffer)
{
+ // If $buffer contains multiple lines, split it and output each line separately
+ if(str_contains($buffer, "\n"))
+ {
+ foreach(explode("\n", $buffer) as $line)
+ {
+ if($line === '')
+ {
+ continue;
+ }
+
+ Console::outVerbose(rtrim($line, "\n"));
+ }
+
+ return;
+ }
+
Console::outVerbose(rtrim($buffer, "\n"));
});
diff --git a/src/ncc/Classes/Runtime.php b/src/ncc/Classes/Runtime.php
index 44448f2..d72016e 100644
--- a/src/ncc/Classes/Runtime.php
+++ b/src/ncc/Classes/Runtime.php
@@ -27,6 +27,7 @@
use Exception;
use InvalidArgumentException;
use ncc\Enums\FileDescriptor;
+ use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\Versions;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\ImportException;
@@ -205,12 +206,15 @@
}
// Import dependencies recursively
- foreach($package_reader->getDependencies() as $dependency)
+ if(!$package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES))
{
- $dependency = $package_reader->getDependency($dependency);
+ foreach($package_reader->getDependencies() as $dependency)
+ {
+ $dependency = $package_reader->getDependency($dependency);
- /** @noinspection UnusedFunctionResultInspection */
- self::import($dependency->getName(), $dependency->getVersion());
+ /** @noinspection UnusedFunctionResultInspection */
+ self::import($dependency->getName(), $dependency->getVersion());
+ }
}
return $package_reader->getAssembly()->getPackage();
diff --git a/src/ncc/Enums/Flags/PackageFlags.php b/src/ncc/Enums/Flags/PackageFlags.php
index 69f6903..7d43294 100644
--- a/src/ncc/Enums/Flags/PackageFlags.php
+++ b/src/ncc/Enums/Flags/PackageFlags.php
@@ -31,4 +31,6 @@
public const MEDIUM_COMPRESSION = 'medium_gz';
public const HIGH_COMPRESSION = 'high_gz';
+
+ public const STATIC_DEPENDENCIES = 'static_dependencies';
}
\ No newline at end of file
diff --git a/src/ncc/Objects/PackageLock.php b/src/ncc/Objects/PackageLock.php
index d2f485f..9f6694a 100644
--- a/src/ncc/Objects/PackageLock.php
+++ b/src/ncc/Objects/PackageLock.php
@@ -30,6 +30,7 @@
use ncc\Exceptions\ConfigurationException;
use ncc\Interfaces\BytecodeObjectInterface;
use ncc\Objects\PackageLock\PackageEntry;
+ use ncc\Objects\PackageLock\VersionEntry;
use ncc\Utilities\Functions;
class PackageLock implements BytecodeObjectInterface
@@ -171,6 +172,18 @@
throw new InvalidArgumentException(sprintf('Package entry %s does not exist', $package_name));
}
+ /**
+ * Returns a version entry from a package entry
+ *
+ * @param string $package_name
+ * @param string $version
+ * @return VersionEntry
+ */
+ public function getVersionEntry(string $package_name, string $version): VersionEntry
+ {
+ return $this->getEntry($package_name)->getVersion($version);
+ }
+
/**
* Adds a new package entry to the package lock file
*