-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CMake build support #19
base: master
Are you sure you want to change the base?
Conversation
Since it is included in gambatte.h it needs to be installed.
The current implementation provides: - Options to build both static and shared library at the same time - A toggle for enabling warnings as errors - Support for enabling zlib - Generating pkg-config and CMake targets - Exporting CMake targets to consume from the build directory
This is required as public header rely on knowing the value of HAVE_STDINT_H and HAVE_CSTDINT. This was also backported to scons since it edits code.
Changes include: - building on multiple platforms - run ctest tests - test consuming from the build directory, from an installation, and from pkg-config.
"libgambatte/src/mem/mbc/mmm01.cpp" | ||
"libgambatte/src/mem/mbc/pocket_camera.cpp" | ||
"libgambatte/src/mem/mbc/wisdom_tree.cpp" | ||
"libgambatte/src/mem/snes_spc/dsp.cpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should consider making snes_spc a separate "library" in this regard instead of bundled into libgambatte (not really any different in practice since it'd always just a static library included in libgambatte). Although that's probably suited for a later time.
- Classes and functions in public headers should be exported. - Internal symbols should hidden. - The "cinterface.cpp" module was left unmodified for compatibility. - This reduces binary size for non-Windows platforms. - For Windows, it allows using a DLL with the public API.
This allows using the same target when adding the project as a subproject using `add_subdirectory`.
Regarding symbols visibility, as it stood, the public API ( On the other hand, the To address that, I made the following changes in 4ea626a:
This change makes the shared library usable on Windows as previously programs such as the |
Is this GBEXPORT on classes behavior for if you're using a shared library yet you're using the C++ API? You shouldn't be using that API directly in such a case, as that usually will end up resulting in linking errors and trying to dynamically link with dlopen/LoadLibrary would not exactly be fun to do (both due to compiler specific name mangling and potentially even other compiler specific ABI differences). You should only be using the C++ API if you're using the library as a static library (and you are in fact a C++ user and using the same compiler here). To properly address the issue of a lack of a header, function declarations should just be added to cinterface.h (or whatever it's named now) for the cinterface.cpp functions. Programs such as the testrunner shouldn't be dynamically linking anyways (those statically link unless something changed in this PR), so something is going wrong much earlier there. |
Just to make sure I get this correctly:
I am thinking about making it a
I had made the static library a requirement to run the test: if(NOT LIBGAMBATTE_BUILD_STATIC)
message(FATAL_ERROR "Building the static library is required to run tests")
endif() But it's good to know that you are not supposed to dynamically link it. |
The C++ API should *not* be exported in the shared library.
#define GBEXPORT | ||
#endif | ||
|
||
extern "C" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this might be expected to be #included from a C context (not C++), it may be better to #ifdef this around __cplusplus
.
Similarly, instead of #including gambatte.h or newstate.h, it may be better to just forward declare struct GB
instead, (and other redeclarations from the gambatte namespace as that might not be available in a C context), at the very least do that when __cplusplus
is not defined.
#include "newstate.h" | ||
|
||
#if defined(_WIN32) || defined(__CYGWIN__) | ||
#define GBEXPORT __declspec(dllexport) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is used by the user of a dll rather than the dll itself, then dllexport would be incorrect, dllimport is the correct declspec (and I don't think visibility attribrute is correct either for non-Windows cases, rather it should just be extern
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking GCC's documentation on visibility, you're correct about the dllexport/dllimport.
According to that same documentation, for the non-Windows case, __attribute__((visibility("default")))
seems to indicate both export and import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking CI likely indicates it got used internally in the library, or it got used when linking it in statically. You can only use dllimport when you are a user of the library (so not the library itself) and the library is a dll (if it's static, you don't use dllimport/dllexport).
dllexport is only meant to be used when building the library. When using the API, dllimport should be used.
|
||
#ifdef __cplusplus | ||
namespace gambatte { | ||
extern "C" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extern "C" here is a bit interesting, technically this is correct, although in practice it typically doesn't actually matter, as most (if not all practical) C++ implementations wouldn't have any issues with a C++ linkage function being assigned to a C linkage function pointer and vice versa (as they function the same at runtime), although this isn't actually guaranteed by the standard (C++ linkage could entail a different calling convention compared to the same function being assigned C linkage, in practice this never occurs).
On that, technically this is not correctly handled in gambatte.h as they all would use C++ (default) linkage, so if we want that to be ""correctly"" done, all those callback definitions need extern "C".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the off chance that there is a compiler out there that defaults to using a different calling convention between C and C++, I went ahead and declared the other function prototypes as extern "C"
for consistency.
Moreover, to make sure the C API is actually usable from C, I added a simple test in c75fe83 that creates and deletes a GB object using the C API.
This ensures the header is usable from a C source.
This is mainly for correctness, but ensures compatibility when __stdcall is the default.
Thie PR adds support for building with CMake (See #18). It is based on the existing scons script for files and flags used.
The CMake script includes:
find_package(libgambatte)
pkg-config --cflags --libs libgambatte
testrunner
.There were a few code changes, mainly aiming at making building and installing more convenient:
newstate.h
to the public headers, sincegambatte.h
depends on it, it should be public too-DHAVE_X
, prefer generating aconfig.h
. This is necessary asgbint.h
needs to know which ofcstdint
orstdint.h
are available, but that information would be lost for a consumer of the library.config.h
, so the shell scripts keep working for the time beingThe CI script has been completely reworked:
Lastly, the README.md and INSTALL.md have been updated to remove the references to Qt, use CMake, and cover more common Linux distributions. Fixes #5
A few additional notes:
PNG_LIBRARY
andPNG_PNG_INCLUDE_DIR
are set manually to help the Find module. Causes the tests to SEGFAULT otherwise.src/statesaver.cpp:553
that breaks compilation. It is probably not a difficult fix, but this PR is already big enough as-is, and there may be more issues.