Merge branch 'wip-cpp'

This commit is contained in:
Andrei Astafev 2019-10-05 11:24:04 +03:00
commit 093a2efc08
10 changed files with 501 additions and 6 deletions

109
CMakeLists.txt Normal file
View File

@ -0,0 +1,109 @@
cmake_minimum_required(VERSION 3.1)
project(whereami VERSION 1.0.0 LANGUAGES C CXX)
include(GNUInstallDirs)
option(BUILD_SHARED_LIBS "Build shared libs" ON)
option(BUILD_STATIC_LIBS "Build static libs" ON)
option(BUILD_EXAMPLES "Build examples" ON)
find_package(PkgConfig)
# whereami
set(CMAKE_C_STANDARD 99)
add_library(whereami OBJECT ${CMAKE_SOURCE_DIR}/src/whereami.c)
target_include_directories(whereami
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>)
set_target_properties(whereami PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(BUILD_SHARED_LIBS)
add_library(whereami_shared SHARED $<TARGET_OBJECTS:whereami>)
set_target_properties(whereami_shared
PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
OUTPUT_NAME whereami
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_INSTALL_LIBDIR})
install(TARGETS whereami_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(BUILD_STATIC_LIBS)
add_library(whereami_static STATIC $<TARGET_OBJECTS:whereami>)
set_target_properties(whereami_static
PROPERTIES OUTPUT_NAME whereami
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_INSTALL_LIBDIR})
install(TARGETS whereami_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(BUILD_EXAMPLES)
add_executable(executable ${CMAKE_SOURCE_DIR}/example/executable.c
${CMAKE_SOURCE_DIR}/src/whereami.c)
target_include_directories(executable PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
if(CMAKE_DL_LIBS)
target_link_libraries(executable ${CMAKE_DL_LIBS})
endif()
add_library(library SHARED ${CMAKE_SOURCE_DIR}/example/library.c
${CMAKE_SOURCE_DIR}/src/whereami.c)
target_include_directories(library PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
if(CMAKE_DL_LIBS)
target_link_libraries(library ${CMAKE_DL_LIBS})
endif()
endif()
if(PKG_CONFIG_FOUND)
configure_file(${CMAKE_SOURCE_DIR}/pkgconfig/whereami.pc.in ${CMAKE_BINARY_DIR}/whereami.pc)
install(FILES ${CMAKE_BINARY_DIR}/whereami.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
# whereamipp
if(CMAKE_CXX_COMPILER)
set(CMAKE_CXX_STANDARD 11)
add_library(whereamipp OBJECT ${CMAKE_SOURCE_DIR}/src/whereami++.cpp)
target_include_directories(whereamipp
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>)
set_target_properties(whereamipp PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(BUILD_SHARED_LIBS)
add_library(whereamipp_shared SHARED $<TARGET_OBJECTS:whereamipp>)
set_target_properties(whereamipp_shared
PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
OUTPUT_NAME whereamipp
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_INSTALL_LIBDIR})
install(TARGETS whereamipp_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(BUILD_STATIC_LIBS)
add_library(whereamipp_static STATIC $<TARGET_OBJECTS:whereamipp>)
set_target_properties(whereamipp_static
PROPERTIES OUTPUT_NAME whereamipp
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_INSTALL_LIBDIR})
install(TARGETS whereamipp_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(BUILD_EXAMPLES)
add_executable(executable-as-cxx ${CMAKE_SOURCE_DIR}/example/executable.cpp
${CMAKE_SOURCE_DIR}/src/whereami++.cpp
${CMAKE_SOURCE_DIR}/src/whereami.c)
target_include_directories(executable-as-cxx PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
if(CMAKE_DL_LIBS)
target_link_libraries(executable-as-cxx ${CMAKE_DL_LIBS})
endif()
add_library(library-as-cxx SHARED ${CMAKE_SOURCE_DIR}/example/library.cpp
${CMAKE_SOURCE_DIR}/src/whereami++.cpp
${CMAKE_SOURCE_DIR}/src/whereami.c)
target_include_directories(library-as-cxx PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
if(CMAKE_DL_LIBS)
target_link_libraries(library-as-cxx ${CMAKE_DL_LIBS})
endif()
endif()
if(PKG_CONFIG_FOUND)
configure_file(${CMAKE_SOURCE_DIR}/pkgconfig/whereamipp.pc.in ${CMAKE_BINARY_DIR}/whereamipp.pc)
install(FILES ${CMAKE_BINARY_DIR}/whereamipp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
endif()

View File

@ -84,28 +84,48 @@ endif
.PHONY: build-executable .PHONY: build-executable
build: build-executable build: build-executable
build-executable: $(bindir)/executable $(bindir)/executable-cpp build-executable: $(bindir)/executable $(bindir)/executable-as-cxx $(bindir)/executable-as-cxx11 $(bindir)/executable-cxx $(bindir)/executable-cxx11
$(bindir)/executable: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c $(bindir)/executable: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
mkdir -p $(@D) mkdir -p $(@D)
$(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@ $(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
$(if $(postbuild),$(postbuild) $@) $(if $(postbuild),$(postbuild) $@)
$(bindir)/executable-cpp: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c $(bindir)/executable-as-cxx: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
mkdir -p $(@D) mkdir -p $(@D)
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@ $(CXX) -std=c++03 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
$(if $(postbuild),$(postbuild) $@)
$(bindir)/executable-as-cxx11: $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/executable.c
mkdir -p $(@D)
$(CXX) -std=c++11 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
$(if $(postbuild),$(postbuild) $@)
$(bindir)/executable-cxx: $(srcdir)/whereami++.cpp $(srcdir)/whereami++.h $(exampledir)/executable.cpp
mkdir -p $(@D)
$(CXX) -std=c++03 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
$(if $(postbuild),$(postbuild) $@)
$(bindir)/executable-cxx11: $(srcdir)/whereami++.cpp $(srcdir)/whereami++.h $(exampledir)/executable.cpp
mkdir -p $(@D)
$(CXX) -std=c++11 -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -o $@
$(if $(postbuild),$(postbuild) $@) $(if $(postbuild),$(postbuild) $@)
.PHONY: build-library .PHONY: build-library
build: build-library build: build-library
build-library: $(bindir)/library$(libsuffix) $(bindir)/library-cpp$(libsuffix) build-library: $(bindir)/library$(libsuffix) $(bindir)/library-as-cxx$(libsuffix) $(bindir)/library-cxx$(libsuffix)
$(bindir)/library$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c $(bindir)/library$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c
mkdir -p $(@D) mkdir -p $(@D)
$(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@ $(CC) -I $(srcdir) $(CPPFLAGS) $(CFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
$(if $(postbuild),$(postbuild) $@) $(if $(postbuild),$(postbuild) $@)
$(bindir)/library-cpp$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c $(bindir)/library-as-cxx$(libsuffix): $(srcdir)/whereami.c $(srcdir)/whereami.h $(exampledir)/library.c
mkdir -p $(@D)
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
$(if $(postbuild),$(postbuild) $@)
$(bindir)/library-cxx$(libsuffix): $(srcdir)/whereami++.cpp $(srcdir)/whereami++.h $(exampledir)/library.cpp
mkdir -p $(@D) mkdir -p $(@D)
$(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@ $(CXX) -x c++ -I $(srcdir) $(CPPFLAGS) $(CXXFLAGS) $(filter-out %.h,$^) $(LDFLAGS) -shared -o $@
$(if $(postbuild),$(postbuild) $@) $(if $(postbuild),$(postbuild) $@)

101
example/executable.cpp Normal file
View File

@ -0,0 +1,101 @@
#include <iostream>
#include <whereami++.h>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#if defined(_MSC_VER)
#pragma warning(push, 3)
#endif
#include <windows.h>
#define RTLD_LAZY 1
#define RTLD_NOW 2
#define RTLD_GLOBAL 4
#define RTLD_LOCAL 8
static void* dlopen(const char* fileName, int mode)
{
wchar_t buffer[MAX_PATH];
if (MultiByteToWideChar(CP_UTF8, 0, fileName, -1, buffer, sizeof(buffer) / sizeof(*buffer)))
{
wchar_t buffer_[MAX_PATH];
GetFullPathNameW(buffer, sizeof(buffer_) / sizeof(*buffer_), buffer_, NULL);
return (void*)LoadLibraryW(buffer_);
}
return NULL;
}
static int dlclose(void* handle)
{
return FreeLibrary((HMODULE)handle) ? 0 : -1;
}
static const char* dlerror(void)
{
DWORD error;
error = GetLastError();
if (error)
{
static char message[1024];
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), message, sizeof(message), NULL);
return message;
}
return "no error";
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#else
#include <dlfcn.h>
#endif
int main(int argc, char** argv)
{
std::cout << "executable path: " << whereami::getExecutablePath() << std::endl;
whereami::whereami_path_t executablePath = whereami::getExecutablePath();
std::cout << " dirname: " << executablePath.dirname() << std::endl;
std::cout << " basename: " << executablePath.basename() << std::endl;
std::cout << "module path: " << whereami::getModulePath() << std::endl;
whereami::whereami_path_t modulePath = whereami::getModulePath();
std::cout << " dirname: " << modulePath.dirname() << std::endl;
std::cout << " basename: " << modulePath.basename() << std::endl;
for (int i = 1; i < argc; ++i)
{
std::string prefix = "--load-library=";
std::string arg = std::string(argv[i]);
if (arg.compare(0, prefix.length(), prefix) == 0)
{
std::string name = arg.substr(prefix.length());
void* handle;
std::cout << std::endl;
handle = dlopen(name.c_str(), RTLD_NOW);
if (!handle)
std::cout << "failed to load library: " << dlerror() << std::endl;
if (handle)
dlclose(handle);
}
}
return 0;
}

61
example/library.cpp Normal file
View File

@ -0,0 +1,61 @@
#include <iostream>
#include <whereami++.h>
#if defined(__GNUC__) && !defined(_WIN32)
__attribute__((constructor))
#endif
static void load()
{
std::cout << "library loaded" << std::endl;
std::cout << "executable path: " << whereami::getExecutablePath() << std::endl;
whereami::whereami_path_t executablePath = whereami::getExecutablePath();
std::cout << " dirname: " << executablePath.dirname() << std::endl;
std::cout << " basename: " << executablePath.basename() << std::endl;
std::cout << "module path: " << whereami::getModulePath() << std::endl;
whereami::whereami_path_t modulePath = whereami::getModulePath();
std::cout << " dirname: " << modulePath.dirname() << std::endl;
std::cout << " basename: " << modulePath.basename() << std::endl;
}
#if defined(__GNUC__) && !defined(_WIN32)
__attribute__((destructor))
#endif
static void unload()
{
std::cout << "library unloaded" << std::endl;
}
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#if defined(_MSC_VER)
#pragma warning(push, 3)
#endif
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
load();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
unload();
break;
}
return TRUE;
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif

13
pkgconfig/whereami.pc.in Normal file
View File

@ -0,0 +1,13 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@
Name: whereami
Description: Whereami C library
Version: @PROJECT_VERSION@
Requires:
Libs: -L@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ -lwhereami
Cflags: -I@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@

View File

@ -0,0 +1,13 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@
Name: whereamipp
Description: Whereami library C++ bindings
Version: @PROJECT_VERSION@
Requires:
Libs: -L@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ -lwhereamipp -whereami
Cflags: -I@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@

104
src/whereami++.cpp Normal file
View File

@ -0,0 +1,104 @@
// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
// https://github.com/gpakosz/whereami
// in case you want to #include "whereami++.cpp" in a larger compilation unit
#if !defined(WHEREAMIPP_H)
#include <whereami++.h>
#endif
namespace whereami {
namespace {
#define WHEREAMI_H
#define WAI_FUNCSPEC
#define WAI_PREFIX(function) function
#include "whereami.c"
}
whereami_string_t whereami_path_t::dirname() const
{
return path.substr(0, dirname_length);
}
whereami_string_t whereami_path_t::basename() const
{
return path.substr(dirname_length + 1);
}
#if defined(WHEREAMI_CXX11)
whereami_path_t::operator whereami_string_t() &&
{
return std::move(path);
}
whereami_path_t::operator whereami_string_t() const &
{
return path;
}
#else
whereami_path_t::operator const whereami_string_t&() const
{
return path;
}
#endif
#if defined(WHEREAMI_CXX11)
whereami_path_t::whereami_path_t(whereami_string_t&& path, int dirname_length) noexcept
: path(std::move(path)), dirname_length(dirname_length)
{
}
#else
whereami_path_t::whereami_path_t(whereami_string_t& path, int dirname_length)
: path(path), dirname_length(dirname_length)
{
}
#endif
#if !defined(WHEREAMI_DISABLE_OSTREAM)
std::ostream& operator<<(std::ostream& os, const whereami_path_t& path)
{
return os << path.path;
}
#endif
WAI_FUNCSPEC
whereami_path_t getExecutablePath()
{
whereami_string_t path;
int dirname_length = -1;
int length = getExecutablePath(0, 0, 0);
if (length != -1)
{
path.resize(length);
getExecutablePath(&path[0], length, &dirname_length);
}
#if defined(WHEREAMI_CXX11)
return whereami_path_t(std::move(path), dirname_length);
#else
return whereami_path_t(path, dirname_length);
#endif
}
WAI_FUNCSPEC
whereami_path_t getModulePath()
{
whereami_string_t path;
int dirname_length = -1;
int length = getModulePath(0, 0, 0);
if (length != -1)
{
path.resize(length);
getModulePath(&path[0], length, &dirname_length);
}
#if defined(WHEREAMI_CXX11)
return whereami_path_t(std::move(path), dirname_length);
#else
return whereami_path_t(path, dirname_length);
#endif
}
} // namespace whereami

67
src/whereami++.h Normal file
View File

@ -0,0 +1,67 @@
// (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
// https://github.com/gpakosz/whereami
#ifndef WHEREAMIPP_H
#define WHEREAMIPP_H
#if !defined(WHEREAMI_STRING_T)
#include <string>
typedef std::string whereami_string_t;
#else
typedef WHEREAMI_STRING_T whereami_string_t;
#endif
#if !defined(WHEREAMI_DISABLE_OSTREAM)
#include <ostream>
#endif
#if (defined (__cplusplus) && (__cplusplus > 199711L)) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706))
#define WHEREAMI_CXX11
#endif
namespace whereami {
class whereami_path_t
{
public:
#if defined(WHEREAMI_CXX11)
operator whereami_string_t() &&;
operator whereami_string_t() const &;
#else
operator const whereami_string_t&() const;
#endif
whereami_string_t dirname() const;
whereami_string_t basename() const;
private:
whereami_path_t();
#if defined(WHEREAMI_CXX11)
whereami_path_t(whereami_string_t&& path, int dirname_length) noexcept;
#else
whereami_path_t(whereami_string_t& path, int dirname_length);
#endif
friend whereami_path_t getExecutablePath();
friend whereami_path_t getModulePath();
#if !defined(WHEREAMI_DISABLE_OSTREAM)
friend std::ostream& operator<<(std::ostream& os, const whereami_path_t& path);
#endif
whereami_string_t path;
int dirname_length;
};
/**
* Returns the path to the current executable.
*/
whereami_path_t getExecutablePath();
/**
* Returns the path to the current module.
*/
whereami_path_t getModulePath();
} // namespace whereami
#endif // #ifndef WHEREAMIPP_H

View File

@ -12,6 +12,13 @@
extern "C" { extern "C" {
#endif #endif
#ifndef WAI_FUNCSPEC
#define WAI_FUNCSPEC
#endif
#ifndef WAI_PREFIX
#define WAI_PREFIX(function) wai_##function
#endif
#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) #if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
#include <stdlib.h> #include <stdlib.h>
#endif #endif

View File

@ -40,7 +40,7 @@ WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
/** /**
* Returns the path to the current module * Returns the path to the current module.
* *
* Usage: * Usage:
* - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve