From 8e684f095982597d548514ccd7f723f6f285b1f5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 3 Aug 2019 19:41:02 +0200 Subject: [PATCH] AudioServer: Port to the new generated IPC mechanism Fork the IPC Connection classes into Server:: and Client::ConnectionNG. The new IPC messages are serialized very snugly instead of using the same generic data structure for all messages. Remove ASAPI.h since we now generate all of it from AudioServer.ipc :^) --- .gitignore | 1 + Applications/Makefile.common | 2 +- Kernel/makeall.sh | 2 +- Libraries/LibAudio/AClientConnection.cpp | 16 +- Libraries/LibAudio/AClientConnection.h | 6 +- Libraries/LibAudio/ASAPI.h | 250 --------------------- Libraries/LibCore/CoreIPCClient.h | 146 +++++++++++- Libraries/LibCore/CoreIPCServer.h | 114 +++++++++- Makefile.common | 2 + Servers/AudioServer/ASClientConnection.cpp | 77 +++---- Servers/AudioServer/ASClientConnection.h | 13 +- Servers/AudioServer/ASEventLoop.cpp | 2 +- Servers/AudioServer/Makefile | 7 +- Userland/Makefile | 2 +- 14 files changed, 319 insertions(+), 321 deletions(-) delete mode 100644 Libraries/LibAudio/ASAPI.h diff --git a/.gitignore b/.gitignore index a5b456019eeaf8..0eebb5526a8628 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ Toolchain/Local .vscode compile_commands.json .clang_complete +*Endpoint.h diff --git a/Applications/Makefile.common b/Applications/Makefile.common index 845caa1727c5be..8935cb38be601a 100755 --- a/Applications/Makefile.common +++ b/Applications/Makefile.common @@ -3,7 +3,7 @@ DEFINES += -DUSERLAND all: $(APP) $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -ldraw -laudio -lcore -lc + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -ldraw -laudio -lipc -lcore -lc .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index 22dba1d56bb9f6..7b194612c18d69 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -21,11 +21,11 @@ build_targets="$build_targets ../Libraries/LibM" build_targets="$build_targets ../Libraries/LibCore" build_targets="$build_targets ../Libraries/LibIPC" build_targets="$build_targets ../Libraries/LibDraw" -build_targets="$build_targets ../Libraries/LibAudio" build_targets="$build_targets ../Servers/SystemServer" build_targets="$build_targets ../Servers/LookupServer" build_targets="$build_targets ../Servers/WindowServer" build_targets="$build_targets ../Servers/AudioServer" +build_targets="$build_targets ../Libraries/LibAudio" build_targets="$build_targets ../Libraries/LibGUI" build_targets="$build_targets ../Libraries/LibHTML" build_targets="$build_targets ../Userland" diff --git a/Libraries/LibAudio/AClientConnection.cpp b/Libraries/LibAudio/AClientConnection.cpp index 00f36d638778cd..3cd78c0aa894be 100644 --- a/Libraries/LibAudio/AClientConnection.cpp +++ b/Libraries/LibAudio/AClientConnection.cpp @@ -3,23 +3,23 @@ #include AClientConnection::AClientConnection() - : Connection("/tmp/asportal") + : ConnectionNG("/tmp/asportal") { } void AClientConnection::handshake() { - auto response = send_sync(getpid()); - set_server_pid(response.server_pid()); - set_my_client_id(response.your_client_id()); + auto response = send_sync(getpid()); + set_server_pid(response->server_pid()); + set_my_client_id(response->client_id()); } void AClientConnection::enqueue(const ABuffer& buffer) { for (;;) { const_cast(buffer).shared_buffer().share_with(server_pid()); - auto response = send_sync(buffer.shared_buffer_id()); - if (response.success()) + auto response = send_sync(buffer.shared_buffer_id()); + if (response->success()) break; sleep(1); } @@ -27,10 +27,10 @@ void AClientConnection::enqueue(const ABuffer& buffer) int AClientConnection::get_main_mix_volume() { - return send_sync().volume(); + return send_sync()->volume(); } void AClientConnection::set_main_mix_volume(int volume) { - send_sync(volume); + send_sync(volume); } diff --git a/Libraries/LibAudio/AClientConnection.h b/Libraries/LibAudio/AClientConnection.h index 3a40698dadba1c..1978a7f00d73c6 100644 --- a/Libraries/LibAudio/AClientConnection.h +++ b/Libraries/LibAudio/AClientConnection.h @@ -1,11 +1,11 @@ #pragma once -#include +#include #include class ABuffer; -class AClientConnection : public IPC::Client::Connection { +class AClientConnection : public IPC::Client::ConnectionNG { C_OBJECT(AClientConnection) public: AClientConnection(); @@ -13,8 +13,6 @@ class AClientConnection : public IPC::Client::Connection&) override {} - int get_main_mix_volume(); void set_main_mix_volume(int); }; diff --git a/Libraries/LibAudio/ASAPI.h b/Libraries/LibAudio/ASAPI.h deleted file mode 100644 index 6d91f6bcefbb90..00000000000000 --- a/Libraries/LibAudio/ASAPI.h +++ /dev/null @@ -1,250 +0,0 @@ -#pragma once - -#include - -struct ASAPI_ServerMessage { - enum class Type { - Invalid, - Greeting, - FinishedPlayingBuffer, - EnqueueBufferResponse, - DidGetMainMixVolume, - DidSetMainMixVolume, - }; - - Type type { Type::Invalid }; - unsigned extra_size { 0 }; - bool success { true }; - int value { 0 }; - - union { - struct { - int server_pid; - int your_client_id; - } greeting; - struct { - int buffer_id; - } playing_buffer; - }; -}; - -struct ASAPI_ClientMessage { - enum class Type { - Invalid, - Greeting, - EnqueueBuffer, - GetMainMixVolume, - SetMainMixVolume, - }; - - Type type { Type::Invalid }; - unsigned extra_size { 0 }; - int value { 0 }; - - union { - struct { - int client_pid; - } greeting; - struct { - int buffer_id; - } play_buffer; - }; -}; - -// FIXME: Everything below this line should be generated from some kind of IPC protocol description. - -namespace ASAPI_Server { -class Greeting; -class FinishedPlayingBuffer; -class EnqueueBufferResponse; -class DidGetMainMixVolume; -class DidSetMainMixVolume; -} - -namespace ASAPI_Client { - -template -class Message { -public: - static ASAPI_ClientMessage::Type message_type() { return type; } - operator const ASAPI_ClientMessage&() const { return m_message; } - -protected: - Message() - { - m_message.type = type; - } - - Message(const ASAPI_ClientMessage& message) - : m_message(message) - { - ASSERT(message.type == type); - } - - ASAPI_ClientMessage m_message; -}; - -class Greeting : public Message { -public: - typedef ASAPI_Server::Greeting ResponseType; - Greeting(const ASAPI_ClientMessage& message) - : Message(message) - { - } - - Greeting(int client_pid) - { - m_message.greeting.client_pid = client_pid; - } - - int client_pid() const { return m_message.greeting.client_pid; } -}; - -class EnqueueBuffer : public Message { -public: - typedef ASAPI_Server::EnqueueBufferResponse ResponseType; - - EnqueueBuffer(const ASAPI_ClientMessage& message) - : Message(message) - { - } - - EnqueueBuffer(int buffer_id) - { - m_message.play_buffer.buffer_id = buffer_id; - } - - int buffer_id() const { return m_message.play_buffer.buffer_id; } -}; - -class GetMainMixVolume : public Message { -public: - typedef ASAPI_Server::DidGetMainMixVolume ResponseType; - - GetMainMixVolume(const ASAPI_ClientMessage& message) - : Message(message) - { - } - - GetMainMixVolume() - { - } -}; - -class SetMainMixVolume : public Message { -public: - typedef ASAPI_Server::DidSetMainMixVolume ResponseType; - - SetMainMixVolume(const ASAPI_ClientMessage& message) - : Message(message) - { - } - - SetMainMixVolume(int volume) - { - m_message.value = volume; - } -}; - -} - -namespace ASAPI_Server { - -template -class Message { -public: - static ASAPI_ServerMessage::Type message_type() { return type; } - operator const ASAPI_ServerMessage&() const { return m_message; } - -protected: - Message() - { - m_message.type = type; - } - - Message(const ASAPI_ServerMessage& message) - : m_message(message) - { - ASSERT(message.type == type); - } - - ASAPI_ServerMessage m_message; -}; - -class Greeting : public Message { -public: - Greeting(const ASAPI_ServerMessage& message) - : Message(message) - { - } - - Greeting(int server_pid, int your_client_id) - { - m_message.greeting.server_pid = server_pid; - m_message.greeting.your_client_id = your_client_id; - } - - int server_pid() const { return m_message.greeting.server_pid; } - int your_client_id() const { return m_message.greeting.your_client_id; } -}; - -class FinishedPlayingBuffer : public Message { -public: - FinishedPlayingBuffer(const ASAPI_ServerMessage& message) - : Message(message) - { - } - - FinishedPlayingBuffer(int buffer_id) - { - m_message.playing_buffer.buffer_id = buffer_id; - } - - int buffer_id() const { return m_message.playing_buffer.buffer_id; } -}; - -class EnqueueBufferResponse : public Message { -public: - EnqueueBufferResponse(const ASAPI_ServerMessage& message) - : Message(message) - { - } - - EnqueueBufferResponse(bool success, int buffer_id) - { - m_message.success = success; - m_message.playing_buffer.buffer_id = buffer_id; - } - - bool success() const { return m_message.success; } - int buffer_id() const { return m_message.playing_buffer.buffer_id; } -}; - -class DidGetMainMixVolume : public Message { -public: - DidGetMainMixVolume(const ASAPI_ServerMessage& message) - : Message(message) - { - } - - DidGetMainMixVolume(int volume) - { - m_message.value = volume; - } - - int volume() const { return m_message.value; } -}; - -class DidSetMainMixVolume : public Message { -public: - DidSetMainMixVolume(const ASAPI_ServerMessage& message) - : Message(message) - { - } - - DidSetMainMixVolume() - { - } -}; - -} diff --git a/Libraries/LibCore/CoreIPCClient.h b/Libraries/LibCore/CoreIPCClient.h index c6169bf11c3640..f932014aca476b 100644 --- a/Libraries/LibCore/CoreIPCClient.h +++ b/Libraries/LibCore/CoreIPCClient.h @@ -1,12 +1,11 @@ #pragma once -#include #include #include #include #include #include - +#include #include #include #include @@ -236,5 +235,148 @@ namespace Client { int m_my_client_id { -1 }; }; + template + class ConnectionNG : public CObject { + C_OBJECT(Connection) + public: + ConnectionNG(const StringView& address) + : m_notifier(CNotifier(m_connection.fd(), CNotifier::Read)) + { + // We want to rate-limit our clients + m_connection.set_blocking(true); + m_notifier.on_ready_to_read = [this] { + drain_messages_from_server(); + CEventLoop::current().post_event(*this, make(m_connection.fd())); + }; + + int retries = 1000; + while (retries) { + if (m_connection.connect(CSocketAddress::local(address))) { + break; + } + + dbgprintf("Client::Connection: connect failed: %d, %s\n", errno, strerror(errno)); + sleep(1); + --retries; + } + ASSERT(m_connection.is_connected()); + } + + virtual void handshake() = 0; + + virtual void event(CEvent& event) override + { + if (event.type() == Event::PostProcess) { + postprocess_messages(m_unprocessed_messages); + } else { + CObject::event(event); + } + } + + void set_server_pid(pid_t pid) { m_server_pid = pid; } + pid_t server_pid() const { return m_server_pid; } + void set_my_client_id(int id) { m_my_client_id = id; } + int my_client_id() const { return m_my_client_id; } + + template + OwnPtr wait_for_specific_message() + { + // Double check we don't already have the event waiting for us. + // Otherwise we might end up blocked for a while for no reason. + for (ssize_t i = 0; i < m_unprocessed_messages.size(); ++i) { + if (m_unprocessed_messages[i]->id() == MessageType::static_message_id()) { + auto message = move(m_unprocessed_messages[i]); + m_unprocessed_messages.remove(i); + CEventLoop::current().post_event(*this, make(m_connection.fd())); + return message; + } + } + for (;;) { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(m_connection.fd(), &rfds); + int rc = CSyscallUtils::safe_syscall(select, m_connection.fd() + 1, &rfds, nullptr, nullptr, nullptr); + if (rc < 0) { + perror("select"); + } + ASSERT(rc > 0); + ASSERT(FD_ISSET(m_connection.fd(), &rfds)); + bool success = drain_messages_from_server(); + if (!success) + return nullptr; + for (ssize_t i = 0; i < m_unprocessed_messages.size(); ++i) { + if (m_unprocessed_messages[i]->id() == MessageType::static_message_id()) { + auto message = move(m_unprocessed_messages[i]); + m_unprocessed_messages.remove(i); + CEventLoop::current().post_event(*this, make(m_connection.fd())); + return message; + } + } + } + } + + bool post_message_to_server(const IMessage& message) + { + auto buffer = message.encode(); + int nwritten = write(m_connection.fd(), buffer.data(), (size_t)buffer.size()); + if (nwritten < 0) { + perror("write"); + ASSERT_NOT_REACHED(); + return false; + } + ASSERT(nwritten == buffer.size()); + return true; + } + + template + OwnPtr send_sync(Args&&... args) + { + bool success = post_message_to_server(RequestType(forward(args)...)); + ASSERT(success); + auto response = wait_for_specific_message(); + ASSERT(response); + return response; + } + + protected: + virtual void postprocess_messages(Vector>& new_bundles) + { + new_bundles.clear(); + } + + private: + bool drain_messages_from_server() + { + for (;;) { + u8 buffer[4096]; + ssize_t nread = recv(m_connection.fd(), buffer, sizeof(buffer), MSG_DONTWAIT); + if (nread < 0) { + if (errno == EAGAIN) { + return true; + } + perror("read"); + exit(1); + return false; + } + if (nread == 0) { + dbg() << "EOF on IPC fd"; + exit(1); + return false; + } + + auto message = Endpoint::decode_message(ByteBuffer::wrap(buffer, sizeof(buffer))); + ASSERT(message); + + m_unprocessed_messages.append(move(message)); + } + } + + CLocalSocket m_connection; + CNotifier m_notifier; + Vector> m_unprocessed_messages; + int m_server_pid { -1 }; + int m_my_client_id { -1 }; + }; + } // Client } // IPC diff --git a/Libraries/LibCore/CoreIPCServer.h b/Libraries/LibCore/CoreIPCServer.h index 54054826c30231..69a1681eb1fb64 100644 --- a/Libraries/LibCore/CoreIPCServer.h +++ b/Libraries/LibCore/CoreIPCServer.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -52,7 +54,13 @@ namespace Server { auto conn = new T(AK::forward(args)...) /* arghs */; conn->send_greeting(); return conn; - }; + } + + template + T* new_connection_ng_for_client(Args&&... args) + { + return new T(AK::forward(args)...) /* arghs */; + } template class Connection : public CObject { @@ -196,5 +204,109 @@ namespace Server { int m_client_pid { -1 }; }; + template + class ConnectionNG : public CObject { + C_OBJECT(Connection) + public: + ConnectionNG(Endpoint& endpoint, CLocalSocket& socket, int client_id) + : m_endpoint(endpoint) + , m_socket(socket) + , m_client_id(client_id) + { + add_child(socket); + m_socket.on_ready_to_read = [this] { drain_client(); }; + } + + virtual ~ConnectionNG() override + { + } + + void post_message(const IMessage& message) + { + auto buffer = message.encode(); + + int nwritten = write(m_socket.fd(), buffer.data(), (size_t)buffer.size()); + if (nwritten < 0) { + switch (errno) { + case EPIPE: + dbg() << "Connection::post_message: Disconnected from peer"; + delete_later(); + return; + case EAGAIN: + dbg() << "Connection::post_message: Client buffer overflowed."; + did_misbehave(); + return; + break; + default: + perror("Connection::post_message write"); + ASSERT_NOT_REACHED(); + } + } + + ASSERT(nwritten == buffer.size()); + } + + void drain_client() + { + unsigned messages_received = 0; + for (;;) { + u8 buffer[4096]; + ssize_t nread = recv(m_socket.fd(), buffer, sizeof(buffer), MSG_DONTWAIT); + if (nread == 0 || (nread == -1 && errno == EAGAIN)) { + if (!messages_received) { + // TODO: is delete_later() sufficient? + CEventLoop::current().post_event(*this, make(client_id())); + } + break; + } + if (nread < 0) { + perror("recv"); + ASSERT_NOT_REACHED(); + } + auto message = m_endpoint.decode_message(ByteBuffer::wrap(buffer, nread)); + if (!message) { + dbg() << "drain_client: Endpoint didn't recognize message"; + did_misbehave(); + return; + } + ++messages_received; + + auto response = m_endpoint.handle(*message); + if (response) + post_message(*response); + } + } + + void did_misbehave() + { + dbg() << "Connection{" << this << "} (id=" << m_client_id << ", pid=" << m_client_pid << ") misbehaved, disconnecting."; + m_socket.close(); + delete_later(); + } + + int client_id() const { return m_client_id; } + pid_t client_pid() const { return m_client_pid; } + void set_client_pid(pid_t pid) { m_client_pid = pid; } + + protected: + void event(CEvent& event) override + { + if (event.type() == Event::Disconnected) { + int client_id = static_cast(event).client_id(); + dbgprintf("Connection: Client disconnected: %d\n", client_id); + delete this; + return; + } + + CObject::event(event); + } + + private: + Endpoint& m_endpoint; + CLocalSocket& m_socket; + int m_client_id { -1 }; + int m_client_pid { -1 }; + }; + } // Server } // IPC diff --git a/Makefile.common b/Makefile.common index ccbff1ab93bbcf..c4bbac01c1e7ff 100644 --- a/Makefile.common +++ b/Makefile.common @@ -33,3 +33,5 @@ LD = i686-pc-serenity-g++ AS = i686-pc-serenity-as DEFINES = -DSANITIZE_PTRS -DDEBUG + +IPCCOMPILER = $(SERENITY_BASE_DIR)/DevTools/IPCCompiler/IPCCompiler diff --git a/Servers/AudioServer/ASClientConnection.cpp b/Servers/AudioServer/ASClientConnection.cpp index bebf2c39272fa7..968838a67edcc0 100644 --- a/Servers/AudioServer/ASClientConnection.cpp +++ b/Servers/AudioServer/ASClientConnection.cpp @@ -2,7 +2,6 @@ #include "ASMixer.h" #include -#include #include #include @@ -14,7 +13,7 @@ #include ASClientConnection::ASClientConnection(CLocalSocket& client_socket, int client_id, ASMixer& mixer) - : Connection(client_socket, client_id) + : ConnectionNG(*this, client_socket, client_id) , m_mixer(mixer) { } @@ -23,58 +22,44 @@ ASClientConnection::~ASClientConnection() { } -void ASClientConnection::send_greeting() +void ASClientConnection::did_finish_playing_buffer(Badge, int buffer_id) { - post_message(ASAPI_Server::Greeting(getpid(), client_id())); + (void)buffer_id; + //post_message(AudioClient::FinishedPlayingBuffer(buffer_id)); } -bool ASClientConnection::handle_message(const ASAPI_ClientMessage& message, const ByteBuffer&&) +OwnPtr ASClientConnection::handle(const AudioServer::Greet& message) { - switch (message.type) { - case ASAPI_ClientMessage::Type::Greeting: - set_client_pid(message.greeting.client_pid); - break; - case ASAPI_ClientMessage::Type::EnqueueBuffer: { - auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(message.play_buffer.buffer_id); - if (!shared_buffer) { - did_misbehave(); - return false; - } + set_client_pid(message.client_pid()); + return make(getpid(), client_id()); +} - ASAPI_ServerMessage reply; - reply.type = ASAPI_ServerMessage::Type::EnqueueBufferResponse; - reply.playing_buffer.buffer_id = message.play_buffer.buffer_id; +OwnPtr ASClientConnection::handle(const AudioServer::GetMainMixVolume&) +{ + return make(m_mixer.main_volume()); +} - if (!m_queue) - m_queue = m_mixer.create_queue(*this); +OwnPtr ASClientConnection::handle(const AudioServer::SetMainMixVolume& message) +{ + m_mixer.set_main_volume(message.volume()); + return make(); +} - if (m_queue->is_full()) { - post_message(ASAPI_Server::EnqueueBufferResponse(false, message.play_buffer.buffer_id)); - break; - } - m_queue->enqueue(ABuffer::create_with_shared_buffer(*shared_buffer)); - post_message(ASAPI_Server::EnqueueBufferResponse(true, message.play_buffer.buffer_id)); - break; - } - case ASAPI_ClientMessage::Type::GetMainMixVolume: { - post_message(ASAPI_Server::DidGetMainMixVolume(m_mixer.main_volume())); - break; - } - case ASAPI_ClientMessage::Type::SetMainMixVolume: { - m_mixer.set_main_volume(message.value); - post_message(ASAPI_Server::DidSetMainMixVolume()); - break; - } - case ASAPI_ClientMessage::Type::Invalid: - default: - dbgprintf("ASClientConnection: Unexpected message ID %d\n", int(message.type)); - did_misbehave(); +OwnPtr ASClientConnection::handle(const AudioServer::EnqueueBuffer& message) +{ + auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(message.buffer_id()); + if (!shared_buffer) { + // FIXME: The shared buffer should have been retrieved for us already. + // We don't want to do IPC error checking at this layer. + ASSERT_NOT_REACHED(); } - return true; -} + if (!m_queue) + m_queue = m_mixer.create_queue(*this); -void ASClientConnection::did_finish_playing_buffer(Badge, int buffer_id) -{ - post_message(ASAPI_Server::FinishedPlayingBuffer(buffer_id)); + if (m_queue->is_full()) + return make(false); + + m_queue->enqueue(ABuffer::create_with_shared_buffer(*shared_buffer)); + return make(true); } diff --git a/Servers/AudioServer/ASClientConnection.h b/Servers/AudioServer/ASClientConnection.h index 5747bdc84170bb..583fa2f312ffbc 100644 --- a/Servers/AudioServer/ASClientConnection.h +++ b/Servers/AudioServer/ASClientConnection.h @@ -1,23 +1,26 @@ #pragma once -#include +#include #include class ABuffer; class ASBufferQueue; class ASMixer; -class ASClientConnection final : public IPC::Server::Connection { +class ASClientConnection final : public IPC::Server::ConnectionNG + , public AudioServerEndpoint { C_OBJECT(ASClientConnection) public: explicit ASClientConnection(CLocalSocket&, int client_id, ASMixer& mixer); ~ASClientConnection() override; - void send_greeting() override; - bool handle_message(const ASAPI_ClientMessage&, const ByteBuffer&& = {}) override; - void did_finish_playing_buffer(Badge, int buffer_id); private: + virtual OwnPtr handle(const AudioServer::Greet&) override; + virtual OwnPtr handle(const AudioServer::GetMainMixVolume&) override; + virtual OwnPtr handle(const AudioServer::SetMainMixVolume&) override; + virtual OwnPtr handle(const AudioServer::EnqueueBuffer&) override; + ASMixer& m_mixer; RefPtr m_queue; }; diff --git a/Servers/AudioServer/ASEventLoop.cpp b/Servers/AudioServer/ASEventLoop.cpp index 46b0fb12f0f603..876e8e937941a4 100644 --- a/Servers/AudioServer/ASEventLoop.cpp +++ b/Servers/AudioServer/ASEventLoop.cpp @@ -16,6 +16,6 @@ ASEventLoop::ASEventLoop() } static int s_next_client_id = 0; int client_id = ++s_next_client_id; - IPC::Server::new_connection_for_client(*client_socket, client_id, m_mixer); + IPC::Server::new_connection_ng_for_client(*client_socket, client_id, m_mixer); }; } diff --git a/Servers/AudioServer/Makefile b/Servers/AudioServer/Makefile index 07cbcb5fbd74d3..59a66fa302f902 100644 --- a/Servers/AudioServer/Makefile +++ b/Servers/AudioServer/Makefile @@ -13,6 +13,11 @@ DEFINES += -DUSERLAND all: $(APP) +main.cpp: AudioServerEndpoint.h + +AudioServerEndpoint.h: AudioServer.ipc + @echo "IPC $<"; $(IPCCOMPILER) $< > $@ + $(APP): $(OBJS) $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -lipc @@ -22,5 +27,5 @@ $(APP): $(OBJS) -include $(OBJS:%.o=%.d) clean: - @echo "CLEAN"; rm -f $(APP) $(OBJS) *.d + @echo "CLEAN"; rm -f $(APP) $(OBJS) *.d AudioServerEndpoint.h diff --git a/Userland/Makefile b/Userland/Makefile index 7a52b5c449ccd5..5da8e05a899cff 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -19,7 +19,7 @@ clean: $(APPS) : % : %.o $(OBJS) @echo "LD $@" - @$(LD) -o $@ $(LDFLAGS) $< -lc -lgui -ldraw -laudio -lcore + @$(LD) -o $@ $(LDFLAGS) $< -lc -lgui -ldraw -laudio -lipc -lcore %.o: %.cpp @echo "CXX $<"