Add a library target, complete with headers that strip implementation details out.

This commit is contained in:
Lior Halphon 2023-06-03 14:39:21 +03:00
parent 4254dcdb2c
commit be171cfe66
11 changed files with 96 additions and 26 deletions

View File

@ -12,9 +12,22 @@ case `echo $1 | cut -d '-' -f 1` in
cd ..
rm -rf *
)
(
cd `mktemp -d`
curl -L https://github.com/BR903/cppp/archive/refs/heads/master.zip > cppp.zip
unzip cppp.zip
cd cppp-*
make -sj
sudo make install
cd ..
rm -rf *
)
;;
macos)
brew install rgbds sdl2
brew install rgbds sdl2 cppp
;;
*)
echo "Unsupported OS"

View File

@ -29,7 +29,7 @@ jobs:
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Build
run: |
${{ matrix.cc }} -v; (make -j sdl tester libretro ${{ matrix.extra_targets }} CONF=release CC=${{ matrix.cc }} || (echo "==== Build Failed ==="; make sdl tester libretro ${{ matrix.extra_targets }} CONF=release CC=${{ matrix.cc }}))
${{ matrix.cc }} -v; (make -j all CONF=release CC=${{ matrix.cc }} || (echo "==== Build Failed ==="; make all CONF=release CC=${{ matrix.cc }}))
- name: Sanity tests
shell: bash
run: |

View File

@ -2723,17 +2723,17 @@ static bool is_in_trivial_memory(uint16_t addr)
typedef uint16_t opcode_address_getter_t(GB_gameboy_t *gb, uint8_t opcode);
uint16_t trivial_1(GB_gameboy_t *gb, uint8_t opcode)
static uint16_t trivial_1(GB_gameboy_t *gb, uint8_t opcode)
{
return gb->pc + 1;
}
uint16_t trivial_2(GB_gameboy_t *gb, uint8_t opcode)
static uint16_t trivial_2(GB_gameboy_t *gb, uint8_t opcode)
{
return gb->pc + 2;
}
uint16_t trivial_3(GB_gameboy_t *gb, uint8_t opcode)
static uint16_t trivial_3(GB_gameboy_t *gb, uint8_t opcode)
{
return gb->pc + 3;
}

View File

@ -10,6 +10,10 @@
#define likely(x) GB_likely(x)
#define unlikely(x) GB_unlikely(x)
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#define __builtin_bswap16(x) ({ typeof(x) _x = (x); _x >> 8 | _x << 8; })
#endif
#define internal __attribute__((visibility("internal")))
#define noinline __attribute__((noinline))
@ -44,10 +48,6 @@
#endif
#endif
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#define __builtin_bswap16(x) ({ typeof(x) _x = (x); _x >> 8 | _x << 8; })
#endif
struct GB_gameboy_s;
typedef struct GB_gameboy_s GB_gameboy_t;
#endif

View File

@ -1402,7 +1402,7 @@ GB_accessory_t GB_get_built_in_accessory(GB_gameboy_t *gb)
bool GB_is_inited(GB_gameboy_t *gb)
{
return gb->magic == state_magic();
return gb->magic == GB_state_magic();
}
bool GB_is_cgb(const GB_gameboy_t *gb)
@ -1784,7 +1784,7 @@ static void GB_reset_internal(GB_gameboy_t *gb, bool quick)
gb->io_registers[GB_IO_OBP1] = preserved_state->obp1;
}
gb->magic = state_magic();
gb->magic = GB_state_magic();
request_boot_rom(gb);
}

View File

@ -1452,7 +1452,7 @@ static int get_state_model_internal(virtual_file_t *file, GB_model_t *model)
if (file->read(file, GB_GET_SECTION(&save, header), GB_SECTION_SIZE(header)) != GB_SECTION_SIZE(header)) return errno;
fix_broken_windows_saves = true;
}
if (save.magic != state_magic()) {
if (save.magic != GB_state_magic()) {
return get_state_model_bess(file, model);
}
if (!READ_SECTION(&save, file, core_state)) return errno ?: EIO;
@ -1499,7 +1499,7 @@ bool GB_is_save_state(const char *path)
if (!f) return false;
uint32_t magic = 0;
fread(&magic, sizeof(magic), 1, f);
if (magic == state_magic()) {
if (magic == GB_state_magic()) {
ret = true;
goto exit;
}
@ -1507,7 +1507,7 @@ bool GB_is_save_state(const char *path)
// Legacy corrupted Windows save state
if (magic == 0) {
fread(&magic, sizeof(magic), 1, f);
if (magic == state_magic()) {
if (magic == GB_state_magic()) {
ret = true;
goto exit;
}

View File

@ -44,7 +44,7 @@ int GB_get_state_model(const char *path, GB_model_t *model);
int GB_get_state_model_from_buffer(const uint8_t *buffer, size_t length, GB_model_t *model);
#ifdef GB_INTERNAL
static inline uint32_t state_magic(void)
static inline uint32_t GB_state_magic(void)
{
if (sizeof(bool) == 1) return 'SAME';
return 'S4ME';

View File

@ -48,13 +48,13 @@ if ((gb)->unit##_cycles <= 0) {\
return;\
}\
switch ((gb)->unit##_state)
#endif
#define GB_BATCHABLE_STATE_MACHINE(gb, unit, cycles, divisor, allow_batching) \
const bool __state_machine_allow_batching = (allow_batching); \
GB_STATE_MACHINE(gb, unit, cycles, divisor)
#define GB_STATE(gb, unit, state) case state: goto unit##state
#endif
#define GB_UNIT(unit) int32_t unit##_cycles, unit##_state

View File

@ -33,7 +33,12 @@ else
DEFAULT := sdl
endif
ifneq ($(shell which xdg-open)$(FREEDESKTOP),)
NULL := /dev/null
ifeq ($(PLATFORM),windows32)
NULL := NUL
endif
ifneq ($(shell which xdg-open 2> $(NULL))$(FREEDESKTOP),)
# Running on an FreeDesktop environment, configure for (optional) installation
DESTDIR ?=
PREFIX ?= /usr/local
@ -54,6 +59,9 @@ CONF ?= debug
BIN := build/bin
OBJ := build/obj
INC := build/include/sameboy
LIB := build/lib
BOOTROMS_DIR ?= $(BIN)/BootROMs
ifdef DATA_DIR
@ -64,13 +72,13 @@ endif
# Use clang if it's available.
ifeq ($(origin CC),default)
ifneq (, $(shell which clang))
ifneq (, $(shell which clang 2> $(NULL)))
CC := clang
endif
endif
# Find libraries with pkg-config if available.
ifneq (, $(shell which pkg-config))
ifneq (, $(shell which pkg-config 2> $(NULL)))
# But not on macOS, it's annoying
ifneq ($(PLATFORM),Darwin)
PKG_CONFIG := pkg-config
@ -100,11 +108,9 @@ endif
# Set compilation and linkage flags based on target, platform and configuration
OPEN_DIALOG = OpenDialog/gtk.c
NULL := /dev/null
ifeq ($(PLATFORM),windows32)
OPEN_DIALOG = OpenDialog/windows.c
NULL := NUL
endif
ifeq ($(PLATFORM),Darwin)
@ -212,6 +218,11 @@ LDFLAGS += -Wl,/NODEFAULTLIB:libcmt.lib
endif
endif
LIBFLAGS := -nostdlib -Wl,-r
ifneq ($(PLATFORM),Darwin)
LIBFLAGS += -no-pie
endif
ifeq ($(CONF),debug)
CFLAGS += -g
else ifeq ($(CONF), release)
@ -241,6 +252,8 @@ else
$(error Invalid value for CONF: $(CONF). Use "debug", "release" or "native_release")
endif
# Define our targets
ifeq ($(PLATFORM),windows32)
@ -259,11 +272,20 @@ tester: $(TESTER_TARGET) $(BIN)/tester/dmg_boot.bin $(BIN)/tester/cgb_boot.bin $
_ios: $(BIN)/SameBoy-iOS.app $(OBJ)/reregister
ios-ipa: $(BIN)/SameBoy-iOS.ipa
ios-deb: $(BIN)/SameBoy-iOS.deb
all: cocoa sdl tester libretro
ifeq ($(PLATFORM),windows32)
lib: lib-unsupported
else
lib: $(LIB)/libsameboy.o $(LIB)/libsameboy.a
endif
all: sdl tester libretro lib
ifeq ($(PLATFORM),Darwin)
all: cocoa ios-ipa ios-deb
endif
# Get a list of our source files and their respective object file targets
CORE_SOURCES := $(shell ls Core/*.c)
CORE_HEADERS := $(shell ls Core/*.h)
SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) $(patsubst %,SDL/audio/%.c,$(SDL_AUDIO_DRIVERS))
TESTER_SOURCES := $(shell ls Tester/*.c)
IOS_SOURCES := $(filter-out iOS/reregister.m, $(shell ls iOS/*.m)) $(shell ls AppleCommon/*.m)
@ -275,12 +297,15 @@ CORE_SOURCES += $(shell ls Windows/*.c)
endif
CORE_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(CORE_SOURCES))
PUBLIC_HEADERS := $(patsubst Core/%,$(INC)/%,$(CORE_HEADERS))
COCOA_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(COCOA_SOURCES))
IOS_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(IOS_SOURCES))
QUICKLOOK_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(QUICKLOOK_SOURCES))
SDL_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(SDL_SOURCES))
TESTER_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(TESTER_SOURCES))
lib: $(PUBLIC_HEADERS)
# Automatic dependency generation
ifneq ($(filter-out ios ios-ipa ios-dev clean bootroms libretro %.bin, $(MAKECMDGOALS)),)
@ -631,9 +656,31 @@ $(OBJ)/control.tar.gz: iOS/deb-postinst iOS/deb-control
$(OBJ)/debian-binary:
-@$(MKDIR) -p $(dir $@)
echo 2.0 > $@
$(LIB)/libsameboy.o: $(CORE_OBJECTS)
-@$(MKDIR) -p $(dir $@)
@# This is a somewhat simple hack to force Clang and GCC to build a native object file out of one or many LTO objects
echo "static const char __attribute__((used)) x=0;"| $(CC) $(filter-out -flto,$(CFLAGS)) -c -x c - -o $(OBJ)/lto_hack.o
@# And this is a somewhat complicated hack to invoke the correct LTO-enabled LD command in a mostly cross-platform nature
$(CC) $(FAT_FLAGS) $(CFLAGS) $(LIBFLAGS) $^ $(OBJ)/lto_hack.o -o $@
-@rm $(OBJ)/lto_hack.o
$(LIB)/libsameboy.a: $(LIB)/libsameboy.o
-@$(MKDIR) -p $(dir $@)
-@rm -f $@
ar -crs $@ $^
$(INC)/%.h: Core/%.h
-@$(MKDIR) -p $(dir $@)
-@# CPPP doesn't like multibyte characters, so we replace the single quote character before processing so it doesn't complain
sed "s/'/@SINGLE_QUOTE@/g" $^ | cppp -UGB_INTERNAL | sed "s/@SINGLE_QUOTE@/'/g" > $@
lib-unsupported:
@echo Due to limitations of lld-link, compiling SameBoy as a library on Windows is not supported.
@false
# Clean
clean:
rm -rf build
.PHONY: libretro tester cocoa ios _ios
.PHONY: libretro tester cocoa ios _ios ios-ipa ios-deb liblib-unsupported

View File

@ -40,9 +40,10 @@ SameBoy is an open-source project licensed under the MIT license, and you're wel
SameBoy requires the following tools and libraries to build:
* clang (Recommended; required for macOS) or GCC
* make
* macOS Cocoa port: macOS SDK and Xcode (For command line tools and ibtool)
* SDL port: libsdl2
* macOS Cocoa frontend: macOS SDK and Xcode (For command line tools and ibtool)
* SDL frontend: libsdl2
* [rgbds](https://github.com/gbdev/rgbds/releases/), for boot ROM compilation
* [cppp](https://github.com/BR903/cppp), for cleaning up headers when compiling SameBoy as a library
On Windows, SameBoy also requires:
* Visual Studio (For headers, etc.)
@ -52,7 +53,8 @@ On Windows, SameBoy also requires:
To compile, simply run `make`. The targets are:
* `cocoa` (Default for macOS)
* `sdl` (Default for everything else)
* `ios` (Plain iOS .app bundle), `ios-ipa` (iOS IPA archive for sideloading), `ios-deb` (iOS deb package for jailbroken devices)
* `lib` (Creates libsameboy.o and libsameboy.a for statically linking SameBoy, as well as a headers directory with corresponding headers; currently not supported on Windows due to linker limitations)
* `ios` (Plain iOS .app bundle), `ios-ipa` (iOS IPA archive for side-loading), `ios-deb` (iOS deb package for jailbroken devices)
* `libretro`
* `bootroms`
* `tester`

View File

@ -1,5 +1,13 @@
#pragma once
#ifdef noinline
#undef noinline
#include_next <stdio.h>
#define noinline __attribute__((noinline))
#else
#include_next <stdio.h>
#endif
#include <stdlib.h>
#include <stdarg.h>