forked from oomer/bellatui
first working EFSW file monitoring, defaults to ., tested on macos
This commit is contained in:
parent
c2087251e2
commit
7f478c7d6b
29
README.md
29
README.md
@ -1,6 +1,6 @@
|
|||||||
# bellatui
|
# bellatui
|
||||||
|
|
||||||
Command line bella renderer with encrypted networking and text user interface.
|
Command line bella renderer with encrypted networking ,text user interface and file monitoring.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -54,6 +54,7 @@ workdir/
|
|||||||
├── bella_engine_sdk/
|
├── bella_engine_sdk/
|
||||||
├── libzmq/
|
├── libzmq/
|
||||||
├── cppzmq/
|
├── cppzmq/
|
||||||
|
├── efsw/
|
||||||
├── belatui/
|
├── belatui/
|
||||||
|
|
||||||
( additional Windows package manager dependency )
|
( additional Windows package manager dependency )
|
||||||
@ -95,9 +96,14 @@ cd build
|
|||||||
make -j4
|
make -j4
|
||||||
cd ../..
|
cd ../..
|
||||||
git clone https://github.com/zeromq/cppzmq
|
git clone https://github.com/zeromq/cppzmq
|
||||||
|
git clone https://github.com/SpartanJ/efsw.git
|
||||||
|
mkdir -p efsw/build
|
||||||
|
cd efsw/build
|
||||||
|
/Applications/CMake.app/Contents/bin/cmake ..
|
||||||
|
cd ../..
|
||||||
git clone https://github.com/oomer/bellatui.git
|
git clone https://github.com/oomer/bellatui.git
|
||||||
cd bellatui
|
cd bellatui
|
||||||
make -j4
|
make all -j4
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
@ -152,6 +158,12 @@ cd cppzmq
|
|||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
|
cd ../..
|
||||||
|
git clone https://github.com/SpartanJ/efsw.git
|
||||||
|
mkdir -p efsw/build
|
||||||
|
cd efsw/build
|
||||||
|
cmake ..
|
||||||
|
make -j4
|
||||||
```
|
```
|
||||||
|
|
||||||
### compiling bellatui
|
### compiling bellatui
|
||||||
@ -159,7 +171,7 @@ cmake ..
|
|||||||
cd ../..
|
cd ../..
|
||||||
git clone https://github.com/oomer/bellatui.git
|
git clone https://github.com/oomer/bellatui.git
|
||||||
cd bellatui
|
cd bellatui
|
||||||
make
|
make all -j4
|
||||||
```
|
```
|
||||||
|
|
||||||
# Windows
|
# Windows
|
||||||
@ -173,18 +185,17 @@ Get bella_engine_sdk
|
|||||||
git clone https://github.com/microsoft/vcpkg.git
|
git clone https://github.com/microsoft/vcpkg.git
|
||||||
cd vcpkg
|
cd vcpkg
|
||||||
vcpkg install zeromq[sodium]:x64-windows
|
vcpkg install zeromq[sodium]:x64-windows
|
||||||
|
cd ..
|
||||||
|
git clone https://github.com/SpartanJ/efsw.git
|
||||||
|
mkdir -p efsw/build
|
||||||
|
cd efsw/build
|
||||||
|
cmake ..
|
||||||
|
|
||||||
git clone https://github.com/oomer/bellatui.git
|
git clone https://github.com/oomer/bellatui.git
|
||||||
|
|
||||||
msbuild bellatui.vcxproj /p:Configuration=release /p:Platform=x64 /p:PlatformToolset=v143
|
msbuild bellatui.vcxproj /p:Configuration=release /p:Platform=x64 /p:PlatformToolset=v143
|
||||||
```
|
```
|
||||||
|
|
||||||
Build directories expected to be relative
|
|
||||||
```
|
|
||||||
--folder
|
|
||||||
--bella_engine_sdk
|
|
||||||
--bellatui
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
473
bellatui.cpp
473
bellatui.cpp
@ -37,21 +37,263 @@
|
|||||||
#include <sys/wait.h> // For waitpid
|
#include <sys/wait.h> // For waitpid
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "bella_sdk/bella_engine.h"
|
#include <efsw/FileSystem.hpp> // For file watching
|
||||||
#include "dl_core/dl_fs.h"
|
#include <efsw/System.hpp> // For file watching
|
||||||
|
#include <efsw/efsw.hpp> // For file watching
|
||||||
|
#include <iostream>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "../bella_engine_sdk/src/bella_sdk/bella_engine.h" // For rendering
|
||||||
|
#include "../bella_engine_sdk/src/dl_core/dl_fs.h" // For rendering
|
||||||
using namespace dl;
|
using namespace dl;
|
||||||
using namespace dl::bella_sdk;
|
using namespace dl::bella_sdk;
|
||||||
|
|
||||||
|
/// A class that manages a queue of files to render with both FIFO order and fast lookups
|
||||||
|
class RenderQueue {
|
||||||
|
public:
|
||||||
|
// Default constructor
|
||||||
|
RenderQueue() = default;
|
||||||
|
|
||||||
|
// Move constructor
|
||||||
|
RenderQueue(RenderQueue&& other) noexcept {
|
||||||
|
std::lock_guard<std::mutex> lock(other.mutex);
|
||||||
|
pathVector = std::move(other.pathVector);
|
||||||
|
pathMap = std::move(other.pathMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move assignment operator
|
||||||
|
RenderQueue& operator=(RenderQueue&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
std::lock_guard<std::mutex> lock1(mutex);
|
||||||
|
std::lock_guard<std::mutex> lock2(other.mutex);
|
||||||
|
pathVector = std::move(other.pathVector);
|
||||||
|
pathMap = std::move(other.pathMap);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete copy operations since mutexes can't be copied
|
||||||
|
RenderQueue(const RenderQueue&) = delete;
|
||||||
|
RenderQueue& operator=(const RenderQueue&) = delete;
|
||||||
|
|
||||||
|
// Add a file to the queue if it's not already there
|
||||||
|
bool push(const dl::String& path) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (pathMap.find(path) == pathMap.end()) {
|
||||||
|
pathVector.push_back(path);
|
||||||
|
pathMap[path] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next file to render (FIFO order)
|
||||||
|
bool pop(dl::String& outPath) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (!pathVector.empty()) {
|
||||||
|
outPath = pathVector.front();
|
||||||
|
pathVector.erase(pathVector.begin());
|
||||||
|
pathMap.erase(outPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a specific file by name
|
||||||
|
bool remove(const dl::String& path) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (pathMap.find(path) != pathMap.end()) {
|
||||||
|
// Remove from vector using erase-remove idiom
|
||||||
|
pathVector.erase(
|
||||||
|
std::remove(pathVector.begin(), pathVector.end(), path),
|
||||||
|
pathVector.end()
|
||||||
|
);
|
||||||
|
// Remove from map
|
||||||
|
pathMap.erase(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a file exists in the queue
|
||||||
|
bool contains(const dl::String& path) const {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return pathMap.find(path) != pathMap.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of files in the queue
|
||||||
|
size_t size() const {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return pathVector.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the queue is empty
|
||||||
|
bool empty() const {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return pathVector.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all files from the queue
|
||||||
|
void clear() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
pathVector.clear();
|
||||||
|
pathMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<dl::String> pathVector; // Maintains FIFO order
|
||||||
|
std::map<dl::String, bool> pathMap; // Enables fast lookups
|
||||||
|
mutable std::mutex mutex; // Thread safety
|
||||||
|
};
|
||||||
|
|
||||||
|
std::atomic<bool> active_render(false);
|
||||||
|
RenderQueue renderQueue; // Replace the old vector and map with our new class
|
||||||
|
std::mutex renderQueueMutex; // Add mutex for thread safety
|
||||||
|
std::vector<dl::String> renderDelete; // This is the efsw queue for when we delete a file
|
||||||
|
std::mutex renderDeleteMutex; // Add mutex for thread safety
|
||||||
|
|
||||||
|
dl::String currentRender;
|
||||||
|
std::mutex currentRenderMutex; // Add mutex for thread safety
|
||||||
|
|
||||||
|
// Queues for incoming files from the efsw watcher
|
||||||
|
RenderQueue incomingDeleteQueue;
|
||||||
|
RenderQueue incomingRenderQueue;
|
||||||
|
std::mutex incomingDeleteQueueMutex; // Add mutex for thread safety
|
||||||
|
std::mutex incomingRenderQueueMutex; // Add mutex for thread safety
|
||||||
|
|
||||||
|
|
||||||
|
/// Processes a file action
|
||||||
|
class UpdateListener : public efsw::FileWatchListener {
|
||||||
|
public:
|
||||||
|
UpdateListener() : should_stop_(false) {}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
should_stop_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getActionName( efsw::Action action ) {
|
||||||
|
switch ( action ) {
|
||||||
|
case efsw::Actions::Add:
|
||||||
|
return "Add";
|
||||||
|
case efsw::Actions::Modified:
|
||||||
|
return "Modified";
|
||||||
|
case efsw::Actions::Delete:
|
||||||
|
return "Delete";
|
||||||
|
case efsw::Actions::Moved:
|
||||||
|
return "Moved";
|
||||||
|
default:
|
||||||
|
return "Bad Action";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleFileAction( efsw::WatchID watchid, const std::string& dir,
|
||||||
|
const std::string& filename, efsw::Action action,
|
||||||
|
std::string oldFilename = "" ) override {
|
||||||
|
if (should_stop_) return; // Early exit if we're stopping
|
||||||
|
|
||||||
|
std::string actionName = getActionName( action );
|
||||||
|
/*std::cout << "Watch ID " << watchid << " DIR ("
|
||||||
|
<< dir + ") FILE (" +
|
||||||
|
( oldFilename.empty() ? "" : "from file " + oldFilename + " to " ) +
|
||||||
|
filename + ") has event "
|
||||||
|
<< actionName << std::endl;*/
|
||||||
|
if (actionName == "Delete") {
|
||||||
|
if (active_render || !incomingRenderQueue.empty()) {
|
||||||
|
dl::String belPath = (dir + filename).c_str();
|
||||||
|
if (belPath.endsWith(".bsz")) {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(incomingDeleteQueueMutex);
|
||||||
|
if (!incomingDeleteQueue.contains(belPath)) {
|
||||||
|
incomingDeleteQueue.push(belPath);
|
||||||
|
std::cout << "\n==" << "STOP RENDER: " << belPath.buf() << "\n==" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (actionName == "Add" || actionName == "Modified") {
|
||||||
|
dl::String belPath = (dir + filename).c_str();
|
||||||
|
if (should_stop_) return; // Check again before starting render
|
||||||
|
if (belPath.endsWith(".bsz")) {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(incomingRenderQueueMutex);
|
||||||
|
if (!incomingRenderQueue.contains(belPath)) {
|
||||||
|
incomingRenderQueue.push(belPath);
|
||||||
|
std::cout << "\n==" << "RENDER QUEUED: " << belPath.buf() << "\n==" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::atomic<bool> should_stop_; // ctrl-c was not working, so we use this to stop the thread
|
||||||
|
};
|
||||||
|
|
||||||
// Global state variables
|
// Global state variables
|
||||||
std::string initializeGlobalLicense(); // Function to return license text
|
std::string initializeGlobalLicense(); // Function to return license text
|
||||||
std::string initializeGlobalThirdPartyLicences(); // Function to return third-party licenses
|
std::string initializeGlobalThirdPartyLicences(); // Function to return third-party licenses
|
||||||
std::atomic<bool> connection_state (false); // Tracks if client/server are connected
|
std::atomic<bool> connection_state (false); // Tracks if client/server are connected
|
||||||
std::atomic<bool> abort_state (false); // Used to signal program termination
|
std::atomic<bool> abort_state (false); // Used to signal program termination
|
||||||
std::atomic<bool> server (false); // Indicates if running in server mode
|
std::atomic<bool> server (false); // Indicates if running in server mode
|
||||||
|
UpdateListener* global_ul = nullptr; // Global pointer to UpdateListener
|
||||||
|
|
||||||
// Function declarations
|
// Function declarations
|
||||||
std::string get_pubkey_from_srv(std::string server_address, uint16_t publickey_port); // Gets server's public key for encryption
|
std::string get_pubkey_from_srv(std::string server_address, uint16_t publickey_port); // Gets server's public key for encryption
|
||||||
|
|
||||||
|
|
||||||
|
bool STOP = false;
|
||||||
|
|
||||||
|
void sigend( int ) {
|
||||||
|
std::cout << std::endl << "Bye bye" << std::endl;
|
||||||
|
STOP = true;
|
||||||
|
if (global_ul) { // Use the global pointer
|
||||||
|
global_ul->stop();
|
||||||
|
}
|
||||||
|
// Give a short time for cleanup
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
exit(0); // Force exit after cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
efsw::WatchID handleWatchID( efsw::WatchID watchid ) {
|
||||||
|
switch ( watchid ) {
|
||||||
|
case efsw::Errors::FileNotFound:
|
||||||
|
case efsw::Errors::FileRepeated:
|
||||||
|
case efsw::Errors::FileOutOfScope:
|
||||||
|
case efsw::Errors::FileRemote:
|
||||||
|
case efsw::Errors::WatcherFailed:
|
||||||
|
case efsw::Errors::Unspecified: {
|
||||||
|
std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
std::cout << "Added WatchID: " << watchid << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return watchid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int s_logCtx = 0;
|
||||||
|
static void log(void* /*ctx*/, LogType type, const char* msg)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case LogType_Info:
|
||||||
|
DL_PRINT("[INFO] %s\n", msg);
|
||||||
|
break;
|
||||||
|
case LogType_Warning:
|
||||||
|
DL_PRINT("[WARN] %s\n", msg);
|
||||||
|
break;
|
||||||
|
case LogType_Error:
|
||||||
|
DL_PRINT("[ERROR] %s\n", msg);
|
||||||
|
break;
|
||||||
|
case LogType_Custom:
|
||||||
|
DL_PRINT("%s\n", msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Main client communication thread
|
// Main client communication thread
|
||||||
void client_thread( std::string server_pkey,
|
void client_thread( std::string server_pkey,
|
||||||
std::string client_pkey,
|
std::string client_pkey,
|
||||||
@ -59,12 +301,6 @@ void client_thread( std::string server_pkey,
|
|||||||
std::string server_address,
|
std::string server_address,
|
||||||
uint16_t command_port);
|
uint16_t command_port);
|
||||||
|
|
||||||
// Main server thread that handles rendering and client requests
|
|
||||||
void server_thread( std::string server_skey,
|
|
||||||
uint16_t command_port,
|
|
||||||
bool test_render,
|
|
||||||
Engine engine);
|
|
||||||
|
|
||||||
// Utility function to open files with system default program
|
// Utility function to open files with system default program
|
||||||
void openFileWithDefaultProgram(const std::string& filePath);
|
void openFileWithDefaultProgram(const std::string& filePath);
|
||||||
|
|
||||||
@ -89,14 +325,15 @@ public:
|
|||||||
// Called when a rendering pass starts
|
// Called when a rendering pass starts
|
||||||
void onStarted(String pass) override
|
void onStarted(String pass) override
|
||||||
{
|
{
|
||||||
|
std::cout << "Started pass " << pass.buf() << std::endl;
|
||||||
logInfo("Started pass %s", pass.buf());
|
logInfo("Started pass %s", pass.buf());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called to update the current status of rendering
|
// Called to update the current status of rendering
|
||||||
void onStatus(String pass, String status) override
|
//void onStatus(String pass, String status) override
|
||||||
{
|
//{
|
||||||
logInfo("%s [%s]", status.buf(), pass.buf());
|
// logInfo("%s [%s]", status.buf(), pass.buf());
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Called to update rendering progress (percentage, time remaining, etc)
|
// Called to update rendering progress (percentage, time remaining, etc)
|
||||||
void onProgress(String pass, Progress progress) override
|
void onProgress(String pass, Progress progress) override
|
||||||
@ -106,6 +343,11 @@ public:
|
|||||||
logInfo("%s [%s]", progress.toString().buf(), pass.buf());
|
logInfo("%s [%s]", progress.toString().buf(), pass.buf());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onImage(String pass, Image image) override
|
||||||
|
{
|
||||||
|
logInfo("We got an image %d x %d.", (int)image.width(), (int)image.height());
|
||||||
|
}
|
||||||
|
|
||||||
// Called when an error occurs during rendering
|
// Called when an error occurs during rendering
|
||||||
void onError(String pass, String msg) override
|
void onError(String pass, String msg) override
|
||||||
{
|
{
|
||||||
@ -116,6 +358,7 @@ public:
|
|||||||
void onStopped(String pass) override
|
void onStopped(String pass) override
|
||||||
{
|
{
|
||||||
logInfo("Stopped %s", pass.buf());
|
logInfo("Stopped %s", pass.buf());
|
||||||
|
active_render = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current progress as a string
|
// Returns the current progress as a string
|
||||||
@ -143,6 +386,16 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Main server thread that handles client requests
|
||||||
|
void server_thread( std::string server_skey,
|
||||||
|
uint16_t command_port,
|
||||||
|
bool test_render,
|
||||||
|
Engine& engine,
|
||||||
|
MyEngineObserver& engineObserver);
|
||||||
|
|
||||||
|
void render_thread( Engine& engine,
|
||||||
|
MyEngineObserver& engineObserver);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Heartbeat Monitoring System
|
* Heartbeat Monitoring System
|
||||||
*
|
*
|
||||||
@ -245,6 +498,41 @@ void heartbeat_thread( std::string server_pkey,
|
|||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void file_watcher_thread(const std::string& watch_path = "") {
|
||||||
|
bool commonTest = true;
|
||||||
|
bool useGeneric = false;
|
||||||
|
|
||||||
|
global_ul = new UpdateListener();
|
||||||
|
efsw::FileWatcher fileWatcher(useGeneric);
|
||||||
|
|
||||||
|
fileWatcher.followSymlinks(false);
|
||||||
|
fileWatcher.allowOutOfScopeLinks(false);
|
||||||
|
|
||||||
|
if (!watch_path.empty() && dl::fs::exists(watch_path.data())) {
|
||||||
|
commonTest = false;
|
||||||
|
if (fileWatcher.addWatch(watch_path, global_ul, true) > 0) {
|
||||||
|
fileWatcher.watch();
|
||||||
|
std::cout << "Watching directory: " << watch_path << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Error trying to watch directory: " << watch_path << std::endl;
|
||||||
|
std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (commonTest) {
|
||||||
|
std::string CurPath(efsw::System::getProcessPath());
|
||||||
|
std::cout << "CurPath: " << CurPath.c_str() << std::endl;
|
||||||
|
fileWatcher.watch();
|
||||||
|
handleWatchID(fileWatcher.addWatch(CurPath + "test", global_ul, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
while(STOP == false) {
|
||||||
|
efsw::System::sleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete global_ul;
|
||||||
|
global_ul = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main Program Entry Point
|
* Main Program Entry Point
|
||||||
*
|
*
|
||||||
@ -274,6 +562,18 @@ int DL_main(Args& args)
|
|||||||
uint16_t publickey_port = 5799;
|
uint16_t publickey_port = 5799;
|
||||||
bool test_render = false;
|
bool test_render = false;
|
||||||
|
|
||||||
|
Engine engine;
|
||||||
|
engine.scene().loadDefs();
|
||||||
|
MyEngineObserver engineObserver;
|
||||||
|
engine.subscribe(&engineObserver);
|
||||||
|
|
||||||
|
// Very early on, we will subscribe to the global bella logging callback, and ask to flush
|
||||||
|
// any messages that may have accumulated prior to this point.
|
||||||
|
//
|
||||||
|
subscribeLog(&s_logCtx, log);
|
||||||
|
flushStartupMessages();
|
||||||
|
|
||||||
|
|
||||||
// Register command-line arguments
|
// Register command-line arguments
|
||||||
args.add("sa", "serverAddress", "", "Bella render server ip address");
|
args.add("sa", "serverAddress", "", "Bella render server ip address");
|
||||||
args.add("cp", "commandPort", "", "tcp port for zmq server socket for commands");
|
args.add("cp", "commandPort", "", "tcp port for zmq server socket for commands");
|
||||||
@ -283,6 +583,8 @@ int DL_main(Args& args)
|
|||||||
args.add("tr", "testRender", "", "force res to 100x100");
|
args.add("tr", "testRender", "", "force res to 100x100");
|
||||||
args.add("tp", "thirdparty", "", "prints third party licenses");
|
args.add("tp", "thirdparty", "", "prints third party licenses");
|
||||||
args.add("li", "licenseinfo", "", "prints license info");
|
args.add("li", "licenseinfo", "", "prints license info");
|
||||||
|
args.add("ef", "efsw", "", "mode efsw");
|
||||||
|
args.add("wd", "watchdir", "", "mode file warch");
|
||||||
|
|
||||||
// Handle special command-line options
|
// Handle special command-line options
|
||||||
if (args.versionReqested())
|
if (args.versionReqested())
|
||||||
@ -296,6 +598,39 @@ int DL_main(Args& args)
|
|||||||
printf("%s", args.help("SDK Test", fs::exePath(), bellaSdkVersion().toString()).buf());
|
printf("%s", args.help("SDK Test", fs::exePath(), bellaSdkVersion().toString()).buf());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
std::string path=".";
|
||||||
|
|
||||||
|
if (args.have("--watchdir")) {
|
||||||
|
path = args.value("--watchdir").buf();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//EFSW mode alwys on
|
||||||
|
// Create the file watcher thread
|
||||||
|
std::thread watcher_thread(file_watcher_thread, path);
|
||||||
|
// Don't wait for the thread to finish here, let it run in background
|
||||||
|
watcher_thread.detach();
|
||||||
|
|
||||||
|
/*if (args.have("--efswxxxxx"))
|
||||||
|
{
|
||||||
|
std::cout << "EFSW mode" << std::endl;
|
||||||
|
signal( SIGABRT, sigend );
|
||||||
|
signal( SIGINT, sigend );
|
||||||
|
signal( SIGTERM, sigend );
|
||||||
|
|
||||||
|
//std::cout << "Press ^C to exit demo" << std::endl;
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
if (args.have("--watchdir")) {
|
||||||
|
path = args.value("--watchdir").buf();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the file watcher thread
|
||||||
|
std::thread watcher_thread(file_watcher_thread, path);
|
||||||
|
|
||||||
|
// Don't wait for the thread to finish here, let it run in background
|
||||||
|
watcher_thread.detach();
|
||||||
|
}*/
|
||||||
|
|
||||||
// Show license information if requested
|
// Show license information if requested
|
||||||
if (args.have("--licenseinfo"))
|
if (args.have("--licenseinfo"))
|
||||||
@ -364,9 +699,6 @@ int DL_main(Args& args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Engine engine;
|
|
||||||
engine.scene().loadDefs();
|
|
||||||
|
|
||||||
// Generate brand new keypair on launch
|
// Generate brand new keypair on launch
|
||||||
// [TODO] Add client side public key fingerprinting for added security
|
// [TODO] Add client side public key fingerprinting for added security
|
||||||
if(server.load()) {
|
if(server.load()) {
|
||||||
@ -378,7 +710,8 @@ int DL_main(Args& args)
|
|||||||
std::cout << "\ncurve keypair gen failed.";
|
std::cout << "\ncurve keypair gen failed.";
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
std::thread server_t(server_thread, server_skey, command_port, test_render, engine);
|
std::thread server_t(server_thread, server_skey, command_port, test_render, std::ref(engine), std::ref(engineObserver));
|
||||||
|
std::thread render_t(render_thread, std::ref(engine), std::ref(engineObserver));
|
||||||
///std::thread heartbeat_t(heartbeat_thread, server_skey, server.load(), 5555);
|
///std::thread heartbeat_t(heartbeat_thread, server_skey, server.load(), 5555);
|
||||||
std::thread heartbeat_t(heartbeat_thread, //function
|
std::thread heartbeat_t(heartbeat_thread, //function
|
||||||
"", //NA Public server key
|
"", //NA Public server key
|
||||||
@ -397,7 +730,7 @@ int DL_main(Args& args)
|
|||||||
|
|
||||||
while(true) { // inner loop
|
while(true) { // inner loop
|
||||||
if (connection_state.load()==false) {
|
if (connection_state.load()==false) {
|
||||||
std::cout << "Client connectiono dead" << std::endl;
|
std::cout << "Client connection dead" << std::endl;
|
||||||
break; // Go back to awaiting client
|
break; // Go back to awaiting client
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
@ -595,6 +928,16 @@ void client_thread( std::string server_pkey,
|
|||||||
exit(0);
|
exit(0);
|
||||||
// RENDER
|
// RENDER
|
||||||
} else if(command == "render") {
|
} else if(command == "render") {
|
||||||
|
std::string compoundArg;
|
||||||
|
if(num_args > 1) {
|
||||||
|
for (size_t i = 1; i < args.size(); ++i) {
|
||||||
|
compoundArg += args[i];
|
||||||
|
if (i < args.size() - 1) {
|
||||||
|
compoundArg += " "; // Add spaces between arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << compoundArg << std::endl;
|
||||||
|
}
|
||||||
//>>>ZOUT
|
//>>>ZOUT
|
||||||
command_sock.send(zmq::message_t("render"), zmq::send_flags::none);
|
command_sock.send(zmq::message_t("render"), zmq::send_flags::none);
|
||||||
//ZIN<<<
|
//ZIN<<<
|
||||||
@ -694,9 +1037,10 @@ void client_thread( std::string server_pkey,
|
|||||||
void server_thread( std::string server_skey,
|
void server_thread( std::string server_skey,
|
||||||
uint16_t command_port,
|
uint16_t command_port,
|
||||||
bool test_render,
|
bool test_render,
|
||||||
Engine engine) {
|
Engine& engine,
|
||||||
MyEngineObserver engineObserver;
|
MyEngineObserver& engineObserver) {
|
||||||
engine.subscribe(&engineObserver);
|
//MyEngineObserver engineObserver;
|
||||||
|
//engine.subscribe(&engineObserver);
|
||||||
|
|
||||||
zmq::context_t ctx;
|
zmq::context_t ctx;
|
||||||
zmq::socket_t command_sock(ctx, zmq::socket_type::rep);
|
zmq::socket_t command_sock(ctx, zmq::socket_type::rep);
|
||||||
@ -733,12 +1077,9 @@ void server_thread( std::string server_skey,
|
|||||||
command_sock.send(zmq::message_t("RDY"), zmq::send_flags::none);
|
command_sock.send(zmq::message_t("RDY"), zmq::send_flags::none);
|
||||||
connection_state = false; //<<
|
connection_state = false; //<<
|
||||||
// RENDER
|
// RENDER
|
||||||
} else if (client_command == "render") {
|
} else if (client_command == "xxxxrender") {
|
||||||
std::cout << "start render" << std::endl;
|
std::cout << "start render" << std::endl;
|
||||||
if(test_render) {
|
|
||||||
engine.scene().camera()["resolution"]= Vec2 {100, 100};
|
|
||||||
}
|
|
||||||
engine.start();
|
|
||||||
//>>>ZOUT
|
//>>>ZOUT
|
||||||
command_sock.send(zmq::message_t("render started...type stat to get progress"), zmq::send_flags::none);
|
command_sock.send(zmq::message_t("render started...type stat to get progress"), zmq::send_flags::none);
|
||||||
} else if (client_command == "stop") {
|
} else if (client_command == "stop") {
|
||||||
@ -834,6 +1175,9 @@ void server_thread( std::string server_skey,
|
|||||||
//>>ZOUT
|
//>>ZOUT
|
||||||
command_sock.send(zmq::message_t("ACK"), zmq::send_flags::none);
|
command_sock.send(zmq::message_t("ACK"), zmq::send_flags::none);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,6 +1198,85 @@ void server_thread( std::string server_skey,
|
|||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render_thread( Engine& engine,
|
||||||
|
MyEngineObserver& engineObserver) {
|
||||||
|
// Create persistent instances outside the loop
|
||||||
|
RenderQueue renderThreadQueue;
|
||||||
|
RenderQueue renderThreadDeleteQueue;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// Append items from incoming queues to our persistent queues
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(incomingRenderQueueMutex);
|
||||||
|
// Process each item in the incoming queue and add it to our persistent queue
|
||||||
|
dl::String path;
|
||||||
|
while (incomingRenderQueue.pop(path)) {
|
||||||
|
renderThreadQueue.push(path);
|
||||||
|
}
|
||||||
|
incomingRenderQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(incomingDeleteQueueMutex);
|
||||||
|
// Process each item in the incoming queue and add it to our persistent queue
|
||||||
|
dl::String path;
|
||||||
|
while (incomingDeleteQueue.pop(path)) {
|
||||||
|
renderThreadDeleteQueue.push(path);
|
||||||
|
}
|
||||||
|
incomingDeleteQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the files without holding the mutex
|
||||||
|
bool expected = false;
|
||||||
|
|
||||||
|
// This is an atomic operation that does two things at once:
|
||||||
|
// 1. Checks if active_render equals expected (false)
|
||||||
|
// 2. If they are equal, sets active_render to true
|
||||||
|
//
|
||||||
|
// The operation is atomic, meaning no other thread can interfere
|
||||||
|
// between the check and the set. This prevents two threads from
|
||||||
|
// both thinking they can start rendering at the same time.
|
||||||
|
//
|
||||||
|
// Returns true if the exchange was successful (we got the render slot)
|
||||||
|
// Returns false if active_render was already true (someone else is rendering)
|
||||||
|
dl::String belPath;
|
||||||
|
if (active_render.compare_exchange_strong(expected, true)) {
|
||||||
|
// We successfully got the render slot - no one else is rendering
|
||||||
|
if (renderThreadQueue.pop(belPath)) {
|
||||||
|
std::cout << "\n==" << "RENDERING: " << belPath.buf() << "\n==" << std::endl;
|
||||||
|
engine.loadScene(belPath);
|
||||||
|
engine.scene().camera()["resolution"]= Vec2 {100, 100};
|
||||||
|
engine.start();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(currentRenderMutex);
|
||||||
|
currentRender = belPath;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
active_render = false; // Release the render slot
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
|
} else { // someone else is rendering
|
||||||
|
std::cout << "Waiting for render slot" << std::endl;
|
||||||
|
|
||||||
|
//std::cout << "Render Queue size: " << renderThreadQueue.size() << std::endl;
|
||||||
|
//std::cout << "Delete Queue size: " << renderThreadDeleteQueue.size() << std::endl;
|
||||||
|
while (renderThreadDeleteQueue.pop(belPath)) { // pop all the deletes
|
||||||
|
std::cout << "renderThreadDeleteQueue contains " << belPath.buf() << " " << renderThreadDeleteQueue.contains(belPath) << std::endl;
|
||||||
|
if (belPath == currentRender) {
|
||||||
|
std::cout << "/n==/nStopping render" << belPath.buf() << std::endl;
|
||||||
|
engine.stop();
|
||||||
|
active_render = false;
|
||||||
|
} else if (renderThreadQueue.contains(belPath)) { // dequeue deletes
|
||||||
|
renderThreadQueue.remove(belPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void openFileWithDefaultProgram(const std::string& filePath) {
|
void openFileWithDefaultProgram(const std::string& filePath) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
230
makefile
230
makefile
@ -1,143 +1,137 @@
|
|||||||
|
|
||||||
SDKNAME =bella_engine_sdk
|
BELLA_SDK_NAME = bella_engine_sdk
|
||||||
OUTNAME =bellatui
|
EXECUTABLE_NAME = bellatui
|
||||||
UNAME =$(shell uname)
|
PLATFORM = $(shell uname)
|
||||||
|
BUILD_TYPE ?= release# Default to release build if not specified
|
||||||
|
|
||||||
ifeq ($(UNAME), Darwin)
|
# Common paths
|
||||||
|
BELLA_SDK_PATH = ../bella_engine_sdk
|
||||||
|
LIBEFSW_PATH = ../efsw
|
||||||
|
LIBZMQ_PATH = ../libzmq
|
||||||
|
CPPZMQ_PATH = ../cppzmq
|
||||||
|
|
||||||
SDKBASE = ../bella_engine_sdk
|
OBJ_DIR = obj/$(PLATFORM)/$(BUILD_TYPE)
|
||||||
|
BIN_DIR = bin/$(PLATFORM)/$(BUILD_TYPE)
|
||||||
|
OUTPUT_FILE = $(BIN_DIR)/$(EXECUTABLE_NAME)
|
||||||
|
|
||||||
SDKFNAME = lib$(SDKNAME).dylib
|
# Platform-specific configuration
|
||||||
ZMQNAME = libzmq.5.dylib
|
ifeq ($(PLATFORM), Darwin)
|
||||||
INCLUDEDIRS = -I$(SDKBASE)/src
|
# macOS configuration
|
||||||
INCLUDEDIRS2 = -I../cppzmq
|
SDK_LIB_EXT = dylib
|
||||||
INCLUDEDIRS3 = -I../libzmq/include
|
# LZFSE_LIB_NAME = liblzfse.$(SDK_LIB_EXT)
|
||||||
LIBDIR = $(SDKBASE)/lib
|
# PLIST_LIB_NAME = libplist-2.0.4.$(SDK_LIB_EXT)
|
||||||
ZMQDIR = ../libzmq/build/lib
|
ZMQ_LIB_NAME = libzmq.5.$(SDK_LIB_EXT)
|
||||||
LIBDIRS2 = -L../libzmq/build/lib
|
EFSW_LIB_NAME = libefsw.$(SDK_LIB_EXT)
|
||||||
LIBDIRS = -L$(LIBDIR)
|
MACOS_SDK_PATH = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
|
||||||
OBJDIR = obj/$(UNAME)
|
|
||||||
BINDIR = bin/$(UNAME)
|
|
||||||
OUTPUT = $(BINDIR)/$(OUTNAME)
|
|
||||||
|
|
||||||
ISYSROOT = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
|
|
||||||
|
|
||||||
|
# Compiler settings
|
||||||
CC = clang
|
CC = clang
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
|
|
||||||
CCFLAGS = -arch x86_64\
|
# Architecture flags
|
||||||
-arch arm64\
|
ARCH_FLAGS = -arch arm64 -mmacosx-version-min=11.0 -isysroot $(MACOS_SDK_PATH)
|
||||||
-mmacosx-version-min=11.0\
|
|
||||||
-isysroot $(ISYSROOT)\
|
|
||||||
-fvisibility=hidden\
|
|
||||||
-O3\
|
|
||||||
$(INCLUDEDIRS)\
|
|
||||||
$(INCLUDEDIRS2)\
|
|
||||||
$(INCLUDEDIRS3)\
|
|
||||||
$(LIBDIRS2)
|
|
||||||
|
|
||||||
CFLAGS = $(CCFLAGS)\
|
# Linking flags - Use multiple rpath entries to look in executable directory
|
||||||
-std=c11
|
LINKER_FLAGS = $(ARCH_FLAGS) -framework Cocoa -framework IOKit -fvisibility=hidden -O5 \
|
||||||
|
-rpath @executable_path \
|
||||||
|
-rpath .
|
||||||
|
|
||||||
CXXFLAGS = $(CCFLAGS)\
|
#-rpath @loader_path \
|
||||||
-std=c++11
|
#-Xlinker -rpath -Xlinker @executable_path
|
||||||
|
|
||||||
CPPDEFINES = -DNDEBUG=1\
|
|
||||||
-DDL_USE_SHARED
|
|
||||||
|
|
||||||
LIBS = -l$(SDKNAME)\
|
|
||||||
-lm\
|
|
||||||
-lzmq\
|
|
||||||
-ldl
|
|
||||||
|
|
||||||
LINKFLAGS = -mmacosx-version-min=11.0\
|
|
||||||
-isysroot $(ISYSROOT)\
|
|
||||||
-framework Cocoa\
|
|
||||||
-framework IOKit\
|
|
||||||
-framework CoreVideo\
|
|
||||||
-framework CoreFoundation\
|
|
||||||
-framework Accelerate\
|
|
||||||
-fvisibility=hidden\
|
|
||||||
-O5\
|
|
||||||
-rpath @executable_path\
|
|
||||||
-weak_library $(LIBDIR)/libvulkan.dylib
|
|
||||||
else
|
else
|
||||||
|
# Linux configuration
|
||||||
|
SDK_LIB_EXT = so
|
||||||
|
# LZFSE_LIB_NAME = liblzfse.$(SDK_LIB_EXT)
|
||||||
|
# PLIST_LIB_NAME = libplist.$(SDK_LIB_EXT)
|
||||||
|
ZMQ_LIB_NAME = libzmq.$(SDK_LIB_EXT)
|
||||||
|
EFSW_LIB_NAME = libefsw.$(SDK_LIB_EXT)
|
||||||
|
|
||||||
SDKBASE = ../bella_engine_sdk
|
# Compiler settings
|
||||||
|
|
||||||
SDKFNAME = lib$(SDKNAME).so
|
|
||||||
ZMQNAME = libzmq.so.5
|
|
||||||
SODNAME = libsodium.so.23
|
|
||||||
INCLUDEDIRS = -I$(SDKBASE)/src
|
|
||||||
INCLUDEDIRS2 = -I../cppzmq
|
|
||||||
INCLUDEDIRS3 = -I../libzmq/include
|
|
||||||
LIBDIR = $(SDKBASE)/lib
|
|
||||||
ZMQDIR = ../libzmq/build/lib
|
|
||||||
SODDIR = /usr/lib/x86_64-linux-gnu/
|
|
||||||
LIBDIRS = -L$(LIBDIR)
|
|
||||||
LIBDIRS2 = -L../libzmq/build/lib
|
|
||||||
OBJDIR = obj/$(UNAME)
|
|
||||||
BINDIR = bin/$(UNAME)
|
|
||||||
OUTPUT = $(BINDIR)/$(OUTNAME)
|
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
|
|
||||||
CCFLAGS = -m64\
|
# Architecture flags
|
||||||
-Wall\
|
ARCH_FLAGS = -m64 -D_FILE_OFFSET_BITS=64
|
||||||
-fvisibility=hidden\
|
|
||||||
-D_FILE_OFFSET_BITS=64\
|
|
||||||
-O3\
|
|
||||||
$(INCLUDEDIRS)\
|
|
||||||
$(INCLUDEDIRS2)\
|
|
||||||
$(INCLUDEDIRS3)\
|
|
||||||
$(LIBDIRS2)
|
|
||||||
|
|
||||||
CFLAGS = $(CCFLAGS)\
|
# Linking flags
|
||||||
-std=c11
|
LINKER_FLAGS = $(ARCH_FLAGS) -fvisibility=hidden -O3 -Wl,-rpath,'$$ORIGIN' -Wl,-rpath,'$$ORIGIN/lib' -weak_library $(LIBDIR)/libvulkan.dylib
|
||||||
|
|
||||||
CXXFLAGS = $(CCFLAGS)\
|
# Platform-specific libraries
|
||||||
-std=c++11
|
#PLIST_LIB = -lplist
|
||||||
|
|
||||||
CPPDEFINES = -DNDEBUG=1\
|
|
||||||
-DDL_USE_SHARED
|
|
||||||
|
|
||||||
LIBS = -l$(SDKNAME)\
|
|
||||||
-lm\
|
|
||||||
-ldl\
|
|
||||||
-lrt\
|
|
||||||
-lpthread\
|
|
||||||
-lX11\
|
|
||||||
-lGL\
|
|
||||||
-lzmq\
|
|
||||||
-lvulkan
|
|
||||||
|
|
||||||
LINKFLAGS = -m64\
|
|
||||||
-fvisibility=hidden\
|
|
||||||
-O3\
|
|
||||||
-Wl,-rpath,'$$ORIGIN'\
|
|
||||||
-Wl,-rpath,'$$ORIGIN/lib'
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJS = bellatui.o
|
|
||||||
OBJ = $(patsubst %,$(OBJDIR)/%,$(OBJS))
|
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
# Common include and library paths
|
||||||
@mkdir -p $(@D)
|
INCLUDE_PATHS = -I$(BELLA_SDK_PATH)/src -I$(LIBEFSW_PATH)/include -I$(LIBEFSW_PATH)/src -I$(LIBZMQ_PATH)/include -I$(CPPZMQ_PATH)
|
||||||
$(CXX) -c -o $@ $< $(CXXFLAGS) $(CPPDEFINES)
|
SDK_LIB_PATH = $(BELLA_SDK_PATH)/lib
|
||||||
|
SDK_LIB_FILE = lib$(BELLA_SDK_NAME).$(SDK_LIB_EXT)
|
||||||
|
EFSW_LIB_PATH = $(LIBEFSW_PATH)/build
|
||||||
|
#EFSW_LIB_FILE = lib$(EFSW_LIB_NAME)
|
||||||
|
ZMQ_LIB_PATH = $(LIBZMQ_PATH)/build/lib
|
||||||
|
# Library flags
|
||||||
|
LIB_PATHS = -L$(SDK_LIB_PATH) -L$(EFSW_LIB_PATH) -L$(ZMQ_LIB_PATH)
|
||||||
|
LIBRARIES = -l$(BELLA_SDK_NAME) -lm -ldl -lefsw -lzmq
|
||||||
|
|
||||||
$(OUTPUT): $(OBJ)
|
# Build type specific flags
|
||||||
@mkdir -p $(@D)
|
ifeq ($(BUILD_TYPE), debug)
|
||||||
$(CXX) -o $@ $^ $(LINKFLAGS) $(LIBDIRS) $(LIBDIRS2) $(LIBS)
|
CPP_DEFINES = -D_DEBUG -DDL_USE_SHARED
|
||||||
@cp $(LIBDIR)/$(SDKFNAME) $(BINDIR)/$(SDKFNAME)
|
COMMON_FLAGS = $(ARCH_FLAGS) -fvisibility=hidden -g -O0 $(INCLUDE_PATHS)
|
||||||
@cp $(ZMQDIR)/$(ZMQNAME) $(BINDIR)/$(ZMQNAME)
|
else
|
||||||
chmod 755 $(BINDIR)/$(ZMQNAME)
|
CPP_DEFINES = -DNDEBUG=1 -DDL_USE_SHARED
|
||||||
ifeq ($(UNAME), Linux)
|
COMMON_FLAGS = $(ARCH_FLAGS) -fvisibility=hidden -O3 $(INCLUDE_PATHS)
|
||||||
@cp $(SODDIR)/$(SODNAME) $(BINDIR)/$(SODNAME)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: clean
|
# Language-specific flags
|
||||||
|
C_FLAGS = $(COMMON_FLAGS) -std=c17
|
||||||
|
CXX_FLAGS = $(COMMON_FLAGS) -std=c++17 -Wno-deprecated-declarations
|
||||||
|
|
||||||
|
# Objects
|
||||||
|
OBJECTS = $(EXECUTABLE_NAME).o
|
||||||
|
OBJECT_FILES = $(patsubst %,$(OBJ_DIR)/%,$(OBJECTS))
|
||||||
|
|
||||||
|
# Build rules
|
||||||
|
$(OBJ_DIR)/$(EXECUTABLE_NAME).o: $(EXECUTABLE_NAME).cpp
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(CXX) -c -o $@ $< $(CXX_FLAGS) $(CPP_DEFINES)
|
||||||
|
|
||||||
|
$(OUTPUT_FILE): $(OBJECT_FILES)
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(CXX) -o $@ $(OBJECT_FILES) $(LINKER_FLAGS) $(LIB_PATHS) $(LIBRARIES)
|
||||||
|
@echo "Copying libraries to $(BIN_DIR)..."
|
||||||
|
@cp $(SDK_LIB_PATH)/$(SDK_LIB_FILE) $(BIN_DIR)/$(SDK_LIB_FILE)
|
||||||
|
# @cp $(LZFSE_BUILD_DIR)/$(LZFSE_LIB_NAME) $(BIN_DIR)/$(LZFSE_LIB_NAME)
|
||||||
|
# @cp $(PLIST_LIB_DIR)/$(PLIST_LIB_NAME) $(BIN_DIR)/$(PLIST_LIB_NAME)
|
||||||
|
@cp $(EFSW_LIB_PATH)/$(EFSW_LIB_NAME) $(BIN_DIR)/$(EFSW_LIB_NAME)
|
||||||
|
@cp $(ZMQ_LIB_PATH)/$(ZMQ_LIB_NAME) $(BIN_DIR)/$(ZMQ_LIB_NAME)
|
||||||
|
@echo "Build complete: $(OUTPUT_FILE)"
|
||||||
|
|
||||||
|
# Add default target
|
||||||
|
all: $(OUTPUT_FILE)
|
||||||
|
|
||||||
|
.PHONY: clean cleanall all
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJDIR)/*.o
|
rm -f $(OBJ_DIR)/$(EXECUTABLE_NAME).o
|
||||||
rm -f $(OUTPUT)
|
rm -f $(OUTPUT_FILE)
|
||||||
rm -f $(BINDIR)/$(SDKFNAME)
|
rm -f $(BIN_DIR)/$(SDK_LIB_FILE)
|
||||||
|
rm -f $(BIN_DIR)/*.dylib
|
||||||
|
rmdir $(OBJ_DIR) 2>/dev/null || true
|
||||||
|
rmdir $(BIN_DIR) 2>/dev/null || true
|
||||||
|
|
||||||
|
cleanall:
|
||||||
|
rm -f obj/*/release/*.o
|
||||||
|
rm -f obj/*/debug/*.o
|
||||||
|
rm -f bin/*/release/$(EXECUTABLE_NAME)
|
||||||
|
rm -f bin/*/debug/$(EXECUTABLE_NAME)
|
||||||
|
rm -f bin/*/release/$(SDK_LIB_FILE)
|
||||||
|
rm -f bin/*/debug/$(SDK_LIB_FILE)
|
||||||
|
rm -f bin/*/release/*.dylib
|
||||||
|
rm -f bin/*/debug/*.dylib
|
||||||
|
rmdir obj/*/release 2>/dev/null || true
|
||||||
|
rmdir obj/*/debug 2>/dev/null || true
|
||||||
|
rmdir bin/*/release 2>/dev/null || true
|
||||||
|
rmdir bin/*/debug 2>/dev/null || true
|
||||||
|
rmdir obj/* 2>/dev/null || true
|
||||||
|
rmdir bin/* 2>/dev/null || true
|
||||||
|
rmdir obj 2>/dev/null || true
|
||||||
|
rmdir bin 2>/dev/null || true
|
||||||
Loading…
x
Reference in New Issue
Block a user