diff --git a/libpurple/account.h b/libpurple/account.h
--- a/libpurple/account.h
+++ b/libpurple/account.h
@@ -54,6 +54,7 @@
 typedef void (*PurpleAccountRegistrationCb)(PurpleAccount *account, gboolean succeeded, void *user_data);
 typedef void (*PurpleAccountUnregistrationCb)(PurpleAccount *account, gboolean succeeded, void *user_data);
 
+#include "buddy.h"
 #include "connection.h"
 #include "log.h"
 #include "proxy.h"
diff --git a/libpurple/buddy.c b/libpurple/buddy.c
--- a/libpurple/buddy.c
+++ b/libpurple/buddy.c
@@ -20,6 +20,9 @@
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
+#include "buddy.h"
+
+#include "debug.h"
 #include "internal.h"
 #include "purplebuddypresence.h"
 #include "purpleprotocolclient.h"
diff --git a/libpurple/group.c b/libpurple/group.c
--- a/libpurple/group.c
+++ b/libpurple/group.c
@@ -22,6 +22,8 @@
  */
 
 #include "group.h"
+
+#include "debug.h"
 #include "internal.h" /* TODO: we need to kill this */
 #include "purpleprivate.h"
 #include "purpleprotocolserver.h"
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -229,7 +229,6 @@
 	'notify.h',
 	'plugins.h',
 	'protocol.h',
-	'protocols.h',
 	'purplechatuser.h',
 	'purpleconversation.h',
 	'purpleimconversation.h',
diff --git a/libpurple/protocol.h b/libpurple/protocol.h
--- a/libpurple/protocol.h
+++ b/libpurple/protocol.h
@@ -45,24 +45,72 @@
 
 #include "account.h"
 #include "buddyicon.h"
-#include "buddylist.h"
-#include "chat.h"
 #include "connection.h"
-#include "conversations.h"
-#include "debug.h"
-#include "xfer.h"
 #include "image.h"
-#include "notify.h"
-#include "plugins.h"
 #include "purpleaccountoption.h"
 #include "purpleaccountusersplit.h"
 #include "purplemessage.h"
-#include "purplewhiteboard.h"
 #include "purplewhiteboardops.h"
-#include "roomlist.h"
 #include "status.h"
 
 /**
+ * PurpleProtocolOptions:
+ * @OPT_PROTO_UNIQUE_CHATNAME: User names are unique to a chat and are not
+ *           shared between rooms.<sbr/>
+ *           XMPP lets you choose what name you want in chats, so it shouldn't
+ *           be pulling the aliases from the buddy list for the chat list; it
+ *           gets annoying.
+ * @OPT_PROTO_CHAT_TOPIC: Chat rooms have topics.<sbr/>
+ *           IRC and XMPP support this.
+ * @OPT_PROTO_NO_PASSWORD: Don't require passwords for sign-in.<sbr/>
+ *           Zephyr doesn't require passwords, so there's no need for a
+ *           password prompt.
+ * @OPT_PROTO_MAIL_CHECK: Notify on new mail.<sbr/>
+ *           MSN and Yahoo notify you when you have new mail.
+ * @OPT_PROTO_PASSWORD_OPTIONAL: Allow passwords to be optional.<sbr/>
+ *           Passwords in IRC are optional, and are needed for certain
+ *           functionality.
+ * @OPT_PROTO_USE_POINTSIZE: Allows font size to be specified in sane point
+ *           size.<sbr/>
+ *           Probably just XMPP and Y!M
+ * @OPT_PROTO_REGISTER_NOSCREENNAME: Set the Register button active even when
+ *           the username has not been specified.<sbr/>
+ *           Gadu-Gadu doesn't need a username to register new account (because
+ *           usernames are assigned by the server).
+ * @OPT_PROTO_SLASH_COMMANDS_NATIVE: Indicates that slash commands are native
+ *           to this protocol.<sbr/>
+ *           Used as a hint that unknown commands should not be sent as
+ *           messages.
+ * @OPT_PROTO_INVITE_MESSAGE: Indicates that this protocol supports sending a
+ *           user-supplied message along with an invitation.
+ * @OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE: Indicates that this protocol
+ *           supports sending a user-supplied message along with an
+ *           authorization acceptance.
+ * @OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE: Indicates that this protocol
+ *           supports sending a user-supplied message along with an
+ *           authorization denial.
+ *
+ * Protocol options
+ *
+ * These should all be stuff that some protocols can do and others can't.
+ */
+typedef enum  /*< flags >*/
+{
+    OPT_PROTO_UNIQUE_CHATNAME               = 0x00000004,
+    OPT_PROTO_CHAT_TOPIC                    = 0x00000008,
+    OPT_PROTO_NO_PASSWORD                   = 0x00000010,
+    OPT_PROTO_MAIL_CHECK                    = 0x00000020,
+    OPT_PROTO_PASSWORD_OPTIONAL             = 0x00000080,
+    OPT_PROTO_USE_POINTSIZE                 = 0x00000100,
+    OPT_PROTO_REGISTER_NOSCREENNAME         = 0x00000200,
+    OPT_PROTO_SLASH_COMMANDS_NATIVE         = 0x00000400,
+    OPT_PROTO_INVITE_MESSAGE                = 0x00000800,
+    OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE = 0x00001000,
+    OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE  = 0x00002000
+
+} PurpleProtocolOptions;
+
+/**
  * PurpleProtocol:
  *
  * Represents an instance of a protocol registered with #PurpleProtocolManager.
diff --git a/libpurple/protocols.h b/libpurple/protocols.h
--- a/libpurple/protocols.h
+++ b/libpurple/protocols.h
@@ -39,63 +39,6 @@
 
 typedef struct _PurpleProtocolChatEntry PurpleProtocolChatEntry;
 
-/**
- * PurpleProtocolOptions:
- * @OPT_PROTO_UNIQUE_CHATNAME: User names are unique to a chat and are not
- *           shared between rooms.<sbr/>
- *           XMPP lets you choose what name you want in chats, so it shouldn't
- *           be pulling the aliases from the buddy list for the chat list; it
- *           gets annoying.
- * @OPT_PROTO_CHAT_TOPIC: Chat rooms have topics.<sbr/>
- *           IRC and XMPP support this.
- * @OPT_PROTO_NO_PASSWORD: Don't require passwords for sign-in.<sbr/>
- *           Zephyr doesn't require passwords, so there's no need for a
- *           password prompt.
- * @OPT_PROTO_MAIL_CHECK: Notify on new mail.<sbr/>
- *           MSN and Yahoo notify you when you have new mail.
- * @OPT_PROTO_PASSWORD_OPTIONAL: Allow passwords to be optional.<sbr/>
- *           Passwords in IRC are optional, and are needed for certain
- *           functionality.
- * @OPT_PROTO_USE_POINTSIZE: Allows font size to be specified in sane point
- *           size.<sbr/>
- *           Probably just XMPP and Y!M
- * @OPT_PROTO_REGISTER_NOSCREENNAME: Set the Register button active even when
- *           the username has not been specified.<sbr/>
- *           Gadu-Gadu doesn't need a username to register new account (because
- *           usernames are assigned by the server).
- * @OPT_PROTO_SLASH_COMMANDS_NATIVE: Indicates that slash commands are native
- *           to this protocol.<sbr/>
- *           Used as a hint that unknown commands should not be sent as
- *           messages.
- * @OPT_PROTO_INVITE_MESSAGE: Indicates that this protocol supports sending a
- *           user-supplied message along with an invitation.
- * @OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE: Indicates that this protocol
- *           supports sending a user-supplied message along with an
- *           authorization acceptance.
- * @OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE: Indicates that this protocol
- *           supports sending a user-supplied message along with an
- *           authorization denial.
- *
- * Protocol options
- *
- * These should all be stuff that some protocols can do and others can't.
- */
-typedef enum  /*< flags >*/
-{
-	OPT_PROTO_UNIQUE_CHATNAME               = 0x00000004,
-	OPT_PROTO_CHAT_TOPIC                    = 0x00000008,
-	OPT_PROTO_NO_PASSWORD                   = 0x00000010,
-	OPT_PROTO_MAIL_CHECK                    = 0x00000020,
-	OPT_PROTO_PASSWORD_OPTIONAL             = 0x00000080,
-	OPT_PROTO_USE_POINTSIZE                 = 0x00000100,
-	OPT_PROTO_REGISTER_NOSCREENNAME         = 0x00000200,
-	OPT_PROTO_SLASH_COMMANDS_NATIVE         = 0x00000400,
-	OPT_PROTO_INVITE_MESSAGE                = 0x00000800,
-	OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE = 0x00001000,
-	OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE  = 0x00002000
-
-} PurpleProtocolOptions;
-
 #include "media.h"
 #include "protocol.h"
 #include "status.h"
diff --git a/libpurple/purple-gio.c b/libpurple/purple-gio.c
--- a/libpurple/purple-gio.c
+++ b/libpurple/purple-gio.c
@@ -21,9 +21,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "purple-gio.h"
+
+#include "debug.h"
 #include "internal.h"
 #include "proxy.h"
-#include "purple-gio.h"
 
 typedef struct {
 	GIOStream *stream;
diff --git a/libpurple/purpleaccountoption.h b/libpurple/purpleaccountoption.h
--- a/libpurple/purpleaccountoption.h
+++ b/libpurple/purpleaccountoption.h
@@ -29,6 +29,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <libpurple/prefs.h>
+
 /**
  * SECTION:purpleaccountoption
  * @section_id: libpurple-account-option
diff --git a/libpurple/purpleimconversation.c b/libpurple/purpleimconversation.c
--- a/libpurple/purpleimconversation.c
+++ b/libpurple/purpleimconversation.c
@@ -21,6 +21,7 @@
 
 #include <libpurple/purpleimconversation.h>
 
+#include <libpurple/debug.h>
 #include <libpurple/enums.h>
 #include <libpurple/purpleprivate.h>
 #include <libpurple/purpleprotocolclient.h>
diff --git a/libpurple/purpleprotocolfactory.h b/libpurple/purpleprotocolfactory.h
--- a/libpurple/purpleprotocolfactory.h
+++ b/libpurple/purpleprotocolfactory.h
@@ -42,6 +42,7 @@
 #include <libpurple/account.h>
 #include <libpurple/connection.h>
 #include <libpurple/protocol.h>
+#include <libpurple/roomlist.h>
 
 G_BEGIN_DECLS
 
diff --git a/libpurple/server.c b/libpurple/server.c
--- a/libpurple/server.c
+++ b/libpurple/server.c
@@ -44,6 +44,7 @@
 #include "server.h"
 #include "status.h"
 #include "util.h"
+#include "xfer.h"
 
 #define SECS_BEFORE_RESENDING_AUTORESPONSE 600
 #define SEX_BEFORE_RESENDING_AUTORESPONSE "Only after you're married"
diff --git a/libpurple/util.h b/libpurple/util.h
--- a/libpurple/util.h
+++ b/libpurple/util.h
@@ -42,6 +42,7 @@
 #include "signals.h"
 #include "xmlnode.h"
 #include "notify.h"
+#include "protocol.h"
 #include "protocols.h"
 
 
