replace build system with cmake

no more makefile :)
This commit is contained in:
Lily Tsuru 2024-07-19 22:01:05 -04:00
parent 9a9d0043f2
commit 326d3e5161
20 changed files with 146 additions and 232 deletions

3
.gitignore vendored
View file

@ -4,4 +4,5 @@
**/obj/ **/obj/
# on your own machine, please. # on your own machine, please.
/speech2/compile_commands.json /speech2/build
/speech2/build-debug

View file

@ -1,14 +1,6 @@
build: build:
dotnet build -c Release cd speech2; cmake --toolchain cmake/clangcl-winxp.cmake -GNinja -Bbuild; cd ..
make -C speech2 CONFIG=Release -j$(nproc) cd speech2; cd build; ninja; cd ..; cd ..;
cp speech2/bin/x86/Release/speech2.dll SAPIServer/bin/Release/net40/windows-x86
cp speech2/bin/x86/Release/speech2.pdb SAPIServer/bin/Release/net40/windows-x86
build-debug:
dotnet build -c Debug
make -C speech2 CONFIG=Debug -j$(nproc)
cp speech2/bin/x86/Debug/speech2.dll SAPIServer/bin/Debug/net40/windows-x86
cp speech2/bin/x86/Debug/speech2.pdb SAPIServer/bin/Debug/net40/windows-x86
clean: clean:
rm -rf SAPIServer/bin SAPIServer/obj rm -rf SAPIServer/bin SAPIServer/obj

View file

@ -1,14 +1,16 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
project(testprog) project(speech2)
xp_init() enable_language(ASM)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(Policies)
include(ProjectFuncs)
add_subdirectory(src)
add_executable(testprog
testprog.cpp
)
# use the static multithreaded C library
set_property(TARGET testprog PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

View file

@ -1,30 +0,0 @@
include build/arch.mk
include build/configs.mk
NAME = speech2
TYPE = dll
# Any C++ file in src/ is automatically picked up.
CXXSRCS = $(wildcard src/*.cpp) $(wildcard src/*/*.cpp)
# Required libraries.
LIBS = kernel32.lib shell32.lib user32.lib uuid.lib ole32.lib
.PHONY: all clean matrix
include build/rules.mk
all: $(BUILD_PRODUCT)
clean:
echo -e "\e[91mCleaning... \e[0m"
rm -rf $(BINDIR)/ $(OBJS)
# A fun make trick. This allows for verbose compilation if desired.
# Set V=1 or anything, and it'll be verbose.
$V.SILENT:
# Include dependency files generated by compilation.
# `make clean` keeps them so we can reuse, however they can
# still optionally be blown away.
-include $(OBJS:.o=.d)

View file

@ -1,30 +0,0 @@
include build/arch.mk
include build/configs.mk
NAME = testprog
TYPE = exe
# Any C++ file in src/ is automatically picked up.
CXXSRCS = testprog.cpp
# Required libraries.
LIBS = kernel32.lib shell32.lib user32.lib uuid.lib ole32.lib
.PHONY: all clean matrix
include build/rules.mk
all: $(BUILD_PRODUCT)
clean:
echo -e "\e[91mCleaning... \e[0m"
rm -rf $(BINDIR)/ $(OBJS)
# A fun make trick. This allows for verbose compilation if desired.
# Set V=1 or anything, and it'll be verbose.
$V.SILENT:
# Include dependency files generated by compilation.
# `make clean` keeps them so we can reuse, however they can
# still optionally be blown away.
-include $(OBJS:.o=.d)

View file

@ -1,26 +0,0 @@
x86_Valid=yes
x86_TRIPLET=i686-pc-windows-msvc
# Only supported arch.
ifeq ($(ARCH),)
ARCH = x86
endif
ifeq ($(VCDIR),)
$(error Please set VCDIR in your environment to an appropiate path)
endif
ifneq ($($(ARCH)_Valid),yes)
$(error Please select a valid target)
endif
CC = clang -target $($(ARCH)_TRIPLET)
CXX = clang -target $($(ARCH)_TRIPLET)
LD = lld-link
# This is $(WINDRES) thanks to the fact I
# depended on the (relatively low quality)
# MinGW toolchain. Thank God For LLVM.
WINDRES = llvm-rc

View file

@ -1,43 +0,0 @@
# Base compiler flags. Only change if you *explicitly* know what you're doing.
CXXRTDIR = $(VCDIR)/crt
UCRTDIR = $(VCDIR)/ucrt
PSDKDIR = $(VCDIR)/winsdk
Release_RTLIBS = libcmt.lib libucrt.lib libvcruntime.lib libcpmt.lib
Debug_RTLIBS = libcmtd.lib libucrtd.lib libvcruntimed.lib libcpmtd.lib
# I really should rename this x_x
CLANG_FLAGS = -fms-extensions -fms-compatibility-version=19 -isystem $(CXXRTDIR)/include -isystem $(UCRTDIR)/include -isystem $(PSDKDIR)/include/shared -isystem $(PSDKDIR)/include/um
BASE_FLAGS = -MMD -gcodeview -fvisibility=hidden $(CLANG_FLAGS) -march=pentium-mmx -Iinclude -Isrc -Ithird_party -mstack-alignment=4 -D_WIN32_WINNT=0x0501
BASE_CCFLAGS = $(BASE_FLAGS) -std=gnu17
BASE_CXXFLAGS = $(BASE_FLAGS) -std=c++20
BASE_LDFLAGS_SHARED = /dll
BASE_LDFLAGS = /nodefaultlib /version:5.1 /machine:i386 /subsystem:windows,5.1 /libpath:$(CXXRTDIR)/lib/x86 /libpath:$(UCRTDIR)/lib /libpath:$(PSDKDIR)/lib
# TODO: Figure out what optimizations are safe and don't break the stack
Release_Valid = yes
Release_CCFLAGS = -O0 -DNDEBUG
Release_CXXFLAGS = -O0 -DNDEBUG
Release_LDFLAGS = /debug /pdb:$(BINDIR)/$(NAME).pdb
Debug_Valid = yes
Debug_CCFLAGS = -O0 -DDEBUG # -D_DEBUG
Debug_CXXFLAGS = -O0 -DDEBUG # -D_DEBUG -D_ITERATOR_DEBUG_LEVEL=0
Debug_LDFLAGS = /debug /pdb:$(BINDIR)/$(NAME).pdb
# select a default configuration or validate configuration
ifeq ($(CONFIG),)
CONFIG = Release
endif
ifneq ($($(CONFIG)_Valid),yes)
$(error Please select a valid configuration)
endif
# define the directories used for output products here.
BINDIR = bin/$(ARCH)/$(CONFIG)
OBJDIR = obj/$(ARCH)/$(CONFIG)

View file

@ -1,46 +0,0 @@
# TODO: Handle C sources and deduplicate.
VPATH = $(dir $(CXXSRCS))
OBJS = $(addprefix $(OBJDIR)/,$(notdir $(CXXSRCS:.cpp=.o)))
# Build types
ifeq ($(TYPE),dll)
BUILD_PRODUCT = $(BINDIR)/$(NAME).dll
$(BINDIR)/$(NAME).dll: $(BINDIR)/ $(OBJDIR)/ $(OBJS)
echo -e "\e[92mLinking DLL $@\e[0m"
$(LD) $(BASE_LDFLAGS_SHARED) $(BASE_LDFLAGS) $($(CONFIG)_LDFLAGS) $($(CONFIG)_RTLIBS) $(LIBS) $(OBJS) /out:$@
else
ifeq ($(TYPE),exe)
BUILD_PRODUCT = $(BINDIR)/$(NAME).exe
$(BINDIR)/$(NAME).exe: $(BINDIR)/ $(OBJDIR)/ $(OBJS)
echo -e "\e[92mLinking EXE $@\e[0m"
$(LD) $(BASE_LDFLAGS) $($(CONFIG)_LDFLAGS) $($(CONFIG)_RTLIBS) $(LIBS) $(OBJS) /out:$@
endif
endif
$(OBJDIR)/%.o: %.c
echo -e "\e[94mCompiling C source file $< ($@)\e[0m"
$(CC) -c $(BASE_CCFLAGS) $($(CONFIG)_CCFLAGS) $< -o $@
$(OBJDIR)/%.o: %.cpp
echo -e "\e[94mCompiling C++ source file $< ($@)\e[0m"
$(CC) -c $(BASE_CXXFLAGS) $($(CONFIG)_CXXFLAGS) $< -o $@
$(OBJDIR)/%.o: %.S
echo -e "\e[94mAssembling $< ($@)\e[0m"
$(CC) -xassembler-with-cpp -c $(BASE_CCFLAGS) $($(CONFIG)_CCFLAGS) $< -o $@
$(OBJDIR)/%.o: %.rc
echo -e "\e[94mCompiling Windows resource script $<\e[0m"
$(WINDRES) -Iinclude $< -o $@
# dir rules
$(BINDIR)/:
echo -e "\e[95mMKDIR $@\e[0m"
mkdir -p $(BINDIR)
$(OBJDIR)/:
echo -e "\e[95mMKDIR $@\e[0m"
mkdir -p $(OBJDIR)

View file

@ -0,0 +1,22 @@
# CMake policy configuration
# Macro to enable new CMake policy.
# Makes this file a *LOT* shorter.
macro (_new_cmake_policy policy)
if(POLICY ${policy})
#message(STATUS "Enabling new policy ${policy}")
cmake_policy(SET ${policy} NEW)
endif()
endmacro()
_new_cmake_policy(CMP0026) # CMake 3.0: Disallow use of the LOCATION property for build targets.
_new_cmake_policy(CMP0042) # CMake 3.0+ (2.8.12): MacOS "@rpath" in target's install name
_new_cmake_policy(CMP0046) # warn about non-existent dependencies
_new_cmake_policy(CMP0048) # CMake 3.0+: project() command now maintains VERSION
_new_cmake_policy(CMP0054) # CMake 3.1: Only interpret if() arguments as variables or keywords when unquoted.
_new_cmake_policy(CMP0056) # try_compile() linker flags
_new_cmake_policy(CMP0066) # CMake 3.7: try_compile(): use per-config flags, like CMAKE_CXX_FLAGS_RELEASE
_new_cmake_policy(CMP0067) # CMake 3.8: try_compile(): honor language standard variables (like C++11)
_new_cmake_policy(CMP0068) # CMake 3.9+: `RPATH` settings on macOS do not affect `install_name`.
_new_cmake_policy(CMP0075) # CMake 3.12+: Include file check macros honor `CMAKE_REQUIRED_LIBRARIES`
_new_cmake_policy(CMP0077) # CMake 3.13+: option() honors normal variables.

View file

@ -0,0 +1,14 @@
function(speech2_target target)
target_compile_definitions(${target} PRIVATE "$<$<CONFIG:DEBUG>:SPEECH2_DEBUG>")
target_compile_features(${target} PRIVATE cxx_std_20)
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/third_party ${CMAKE_CURRENT_BINARY_DIR})
# use the static multithreaded C library
set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# TODO option for this.
target_link_options(${target} PRIVATE
-Wl,/safeseh:no
-Xlinker /subsystem:console,${CMAKE_SYSTEM_VERSION}
)
endfunction()

View file

@ -28,7 +28,7 @@ set(CMAKE_C_COMPILER "clang" CACHE FILEPATH "")
set(CMAKE_CXX_COMPILER "clang++" CACHE FILEPATH "") set(CMAKE_CXX_COMPILER "clang++" CACHE FILEPATH "")
set(CMAKE_LINKER "lld-link" CACHE FILEPATH "") set(CMAKE_LINKER "lld-link" CACHE FILEPATH "")
set(CMAKE_ASM_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}")
set(CMAKE_C_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}") set(CMAKE_C_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}")
set(CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_INIT} -fomit-frame-pointer") set(CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_INIT} -fomit-frame-pointer")
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}") set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}")

View file

@ -1,2 +0,0 @@
make clean
bear -- make

View file

@ -0,0 +1,20 @@
add_subdirectory(sapi4)
xp_init()
add_executable(sapiserver
main.cpp
winxp_compat_fwd.asm
winxp_compat.cpp
)
speech2_target(sapiserver)
target_link_libraries(sapiserver PRIVATE
speech2_sapi4
uuid.lib
ole32.lib
)

28
speech2/src/main.cpp Normal file
View file

@ -0,0 +1,28 @@
#include <stdio.h>
#include <windows.h>
#include <memory>
#include "speechapi.hpp"
int main() {
CoInitialize(nullptr);
auto api = std::unique_ptr<ISpeechAPI>(ISpeechAPI::CreateSapi4());
if(auto hr = api->Initialize(); FAILED(hr)) {
printf("Failed to initialize speech API\n");
return 1;
}
if(auto hr = api->SelectVoice("Sam"); FAILED(hr)) {
printf("Failed to select voice\n");
return 1;
}
printf("Selected voice\n");
CoUninitialize();
return 0;
}

View file

@ -0,0 +1,8 @@
add_library(speech2_sapi4
api_sapi4.cpp
guid_sapi4.cpp
audio_buffer.cpp
)
speech2_target(speech2_sapi4)

View file

@ -6,9 +6,6 @@
#include "sapi4/include/speech.h" #include "sapi4/include/speech.h"
#include "speechapi.hpp" #include "speechapi.hpp"
// stupid hacky but Whatevers
struct SpeechAPI_SAPI4 : public ISpeechAPI { struct SpeechAPI_SAPI4 : public ISpeechAPI {
virtual ~SpeechAPI_SAPI4() { virtual ~SpeechAPI_SAPI4() {
printf("~SpeechAPI_SAPI4\n"); printf("~SpeechAPI_SAPI4\n");
@ -31,32 +28,19 @@ struct SpeechAPI_SAPI4 : public ISpeechAPI {
pEnum->Reset(); pEnum->Reset();
printf("speech2: SpeechAPI_Sapi4::Initalize() created enum\n");
printf("speech2: SpeechAPI_Sapi4::Initalize() starting enumvoices\n");
// Fill out voices // Fill out voices
EnumVoices(); EnumVoices();
printf("speech2: SpeechAPI_Sapi4::Initalize() end enumvoices\n");
printf("speech2: SpeechAPI_Sapi4::Initalize() end\n");
return S_OK; return S_OK;
} }
void EnumVoices() { void EnumVoices() {
static TTSMODEINFO found{}; TTSMODEINFO found{};
while(!pEnum->Next(1, &found, nullptr)) { while(!pEnum->Next(1, &found, nullptr)) {
auto ptr = _strdup(found.szModeName); voices.push_back({found.gModeID, found.szModeName});
printf("EnumVoices() voice %s\n", found.szModeName);
voices.push_back({found.gModeID, ptr});
} }
printf("EnumVoices() end\n");
pEnum->Reset(); pEnum->Reset();
} }
@ -66,6 +50,7 @@ struct SpeechAPI_SAPI4 : public ISpeechAPI {
HRESULT SelectVoiceImpl(const GUID& guid) { HRESULT SelectVoiceImpl(const GUID& guid) {
pAudioOut = new AudioOutBuffer(); pAudioOut = new AudioOutBuffer();
pAudioOut->AddRef();
if(pCentral) if(pCentral)
pCentral->Release(); pCentral->Release();

View file

@ -1,22 +1,14 @@
#include <windows.h> #include <windows.h>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
/// base class for access to text-to-speech APIs. /// base class for access to text-to-speech APIs.
struct ISpeechAPI { struct ISpeechAPI {
struct VoiceInfo { struct VoiceInfo {
GUID guid{}; // Optional. May not be filled out if th e GUID guid{}; // Optional. May not be filled out if the API doesn't do guids
char* voiceName; std::string voiceName;
//VoiceInfo(const VoiceInfo&) = delete;
//VoiceInfo(VoiceInfo&&) = delete;
~VoiceInfo() {
// Make this a lot less stupid at some point.
if(voiceName)
free(voiceName);
}
}; };
virtual ~ISpeechAPI() = default; virtual ~ISpeechAPI() = default;

View file

@ -0,0 +1,28 @@
#include <windows.h>
typedef BOOL(WINAPI* PFN_INITIALIZECRITICALSECTIONEX)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags);
extern "C" {
PFN_INITIALIZECRITICALSECTIONEX pfnInitalizeCriticalSectionEx = nullptr;
BOOL WINAPI _InitalizeCriticalSectionEx_xp(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags) {
// We ignore dwFlags, but pass dwSpinCount to InitializeCriticalSectionAndSpinCount,
// which DOES exist on XP.
static_cast<void>(dwFlags);
return InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount);
}
BOOL WINAPI LibInitalizeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags) {
if(!pfnInitalizeCriticalSectionEx) {
pfnInitalizeCriticalSectionEx =
reinterpret_cast<PFN_INITIALIZECRITICALSECTIONEX>(GetProcAddress(GetModuleHandle("kernel32.dll"), "InitializeCriticalSectionEx"));
// Compatibilty.
if(!pfnInitalizeCriticalSectionEx)
pfnInitalizeCriticalSectionEx = _InitalizeCriticalSectionEx_xp;
}
return pfnInitalizeCriticalSectionEx(lpCriticalSection, dwSpinCount, dwFlags);
}
}

View file

@ -0,0 +1,5 @@
// This file declares forwarders for Windows imports which the newer VS 2022 CRT requires.
.globl "__imp__InitializeCriticalSectionEx@12"
"__imp__InitializeCriticalSectionEx@12":
.long "_LibInitalizeCriticalSectionEx@12"

View file

@ -1,6 +0,0 @@
#include <stdio.h>
int main() {
printf("Hello, C++20 on Windows XP~\n");
return 0;
}