From 260d2ad84dcb5be213e67e71b0eb141516f15ca3 Mon Sep 17 00:00:00 2001 From: Joseph Aquino Date: Wed, 2 Jul 2025 15:34:14 -0400 Subject: [PATCH] major update -added support for building with ninja and added corresponding shell scripts -added EntityView class to iterate over entities of the same tag -entities are now grouped together in memory by tag rather than all together -moved globals.h into utility.h -moved EntityTag and EntityIndex into utility.h --- .gitignore | 4 +- .idea/.gitignore | 8 + .idea/editor.xml | 102 +++ .idea/misc.xml | 18 + .idea/vcs.xml | 6 + build-ninja.sh | 5 + build => build.sh | 0 clean-ninja.sh | 7 + clean => clean.sh | 0 include/Entities.h | 3 +- include/Entities/Components.h | 10 +- include/Entities/Entity.h | 26 +- include/Entities/EntityManager.h | 14 +- include/Entities/EntityMemoryPool.h | 3 - include/Entities/EntityView.h | 83 ++ include/Globals.h | 7 - include/SwapBackVector.hpp | 236 ----- include/SwapBackVectorIterator.hpp | 112 --- include/log.h | 9 + include/utility.h | 50 +- premake5.lua | 40 +- run => run.sh | 0 src/Classes/Entity.cpp | 12 +- src/Classes/EntityManager.cpp | 12 + src/Classes/EntityMemoryPool.cpp | 16 +- src/Classes/EntityView.cpp | 123 +++ src/main.cpp | 18 +- vendor/premake5/ninja/.github/dependabot.yml | 13 + .../ninja/.github/workflows/macos.yml | 41 + .../ninja/.github/workflows/ubuntu.yml | 45 + .../ninja/.github/workflows/windows.yml | 44 + vendor/premake5/ninja/LICENSE | 22 + vendor/premake5/ninja/README.md | 43 + vendor/premake5/ninja/_manifest.lua | 4 + vendor/premake5/ninja/_preload.lua | 60 ++ vendor/premake5/ninja/ninja.lua | 845 ++++++++++++++++++ .../tests/console_app/includepath/main.cpp | 11 + .../console_app/includepath/premake5.lua | 22 + .../console_app/includepath/test1/test1.c | 7 + .../console_app/includepath/test1/test1.h | 11 + .../console_app/includepath/test2/test2.cpp | 7 + .../console_app/includepath/test2/test2.h | 3 + .../ninja/tests/console_app/simple/main.cpp | 13 + .../tests/console_app/simple/premake5.lua | 21 + .../ninja/tests/console_app/simple/test 3.c | 7 + .../ninja/tests/console_app/simple/test 3.h | 11 + .../ninja/tests/console_app/simple/test1.c | 7 + .../ninja/tests/console_app/simple/test1.h | 11 + .../ninja/tests/console_app/simple/test2.cpp | 7 + .../ninja/tests/console_app/simple/test2.h | 3 + vendor/premake5/ninja/tests/run_tests.py | 270 ++++++ .../tests/shared_lib/simple/premake5.lua | 22 + .../ninja/tests/shared_lib/simple/test1.cpp | 7 + .../ninja/tests/shared_lib/simple/test1.h | 13 + .../ninja/tests/shared_lib/withapp/main.cpp | 11 + .../tests/shared_lib/withapp/premake5.lua | 59 ++ .../tests/shared_lib/withapp/test1/test1.cpp | 7 + .../tests/shared_lib/withapp/test1/test1.h | 13 + .../tests/shared_lib/withapp/test2/test2.cpp | 7 + .../tests/shared_lib/withapp/test2/test2.h | 13 + .../tests/static_lib/simple/premake5.lua | 21 + .../ninja/tests/static_lib/simple/test1.c | 7 + .../ninja/tests/static_lib/simple/test1.h | 11 + .../ninja/tests/static_lib/withapp/main.cpp | 11 + .../tests/static_lib/withapp/premake5.lua | 64 ++ .../tests/static_lib/withapp/test1/test1.c | 7 + .../tests/static_lib/withapp/test1/test1.h | 11 + .../tests/static_lib/withapp/test2/test2.cpp | 7 + .../tests/static_lib/withapp/test2/test2.h | 3 + .../ninja/tests/windowed_app/simple/main.cpp | 16 + .../tests/windowed_app/simple/premake5.lua | 24 + .../ninja/tests/windowed_app/simple/test1.c | 7 + .../ninja/tests/windowed_app/simple/test1.h | 11 + .../ninja/tests/windowed_app/simple/test2.cpp | 7 + .../ninja/tests/windowed_app/simple/test2.h | 3 + 75 files changed, 2377 insertions(+), 437 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/editor.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100755 build-ninja.sh rename build => build.sh (100%) create mode 100755 clean-ninja.sh rename clean => clean.sh (100%) create mode 100644 include/Entities/EntityView.h delete mode 100644 include/Globals.h delete mode 100644 include/SwapBackVector.hpp delete mode 100644 include/SwapBackVectorIterator.hpp create mode 100644 include/log.h rename run => run.sh (100%) create mode 100644 src/Classes/EntityView.cpp create mode 100644 vendor/premake5/ninja/.github/dependabot.yml create mode 100644 vendor/premake5/ninja/.github/workflows/macos.yml create mode 100644 vendor/premake5/ninja/.github/workflows/ubuntu.yml create mode 100644 vendor/premake5/ninja/.github/workflows/windows.yml create mode 100644 vendor/premake5/ninja/LICENSE create mode 100644 vendor/premake5/ninja/README.md create mode 100644 vendor/premake5/ninja/_manifest.lua create mode 100644 vendor/premake5/ninja/_preload.lua create mode 100644 vendor/premake5/ninja/ninja.lua create mode 100644 vendor/premake5/ninja/tests/console_app/includepath/main.cpp create mode 100644 vendor/premake5/ninja/tests/console_app/includepath/premake5.lua create mode 100644 vendor/premake5/ninja/tests/console_app/includepath/test1/test1.c create mode 100644 vendor/premake5/ninja/tests/console_app/includepath/test1/test1.h create mode 100644 vendor/premake5/ninja/tests/console_app/includepath/test2/test2.cpp create mode 100644 vendor/premake5/ninja/tests/console_app/includepath/test2/test2.h create mode 100644 vendor/premake5/ninja/tests/console_app/simple/main.cpp create mode 100644 vendor/premake5/ninja/tests/console_app/simple/premake5.lua create mode 100644 vendor/premake5/ninja/tests/console_app/simple/test 3.c create mode 100644 vendor/premake5/ninja/tests/console_app/simple/test 3.h create mode 100644 vendor/premake5/ninja/tests/console_app/simple/test1.c create mode 100644 vendor/premake5/ninja/tests/console_app/simple/test1.h create mode 100644 vendor/premake5/ninja/tests/console_app/simple/test2.cpp create mode 100644 vendor/premake5/ninja/tests/console_app/simple/test2.h create mode 100644 vendor/premake5/ninja/tests/run_tests.py create mode 100644 vendor/premake5/ninja/tests/shared_lib/simple/premake5.lua create mode 100644 vendor/premake5/ninja/tests/shared_lib/simple/test1.cpp create mode 100644 vendor/premake5/ninja/tests/shared_lib/simple/test1.h create mode 100644 vendor/premake5/ninja/tests/shared_lib/withapp/main.cpp create mode 100644 vendor/premake5/ninja/tests/shared_lib/withapp/premake5.lua create mode 100644 vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.cpp create mode 100644 vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.h create mode 100644 vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.cpp create mode 100644 vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.h create mode 100644 vendor/premake5/ninja/tests/static_lib/simple/premake5.lua create mode 100644 vendor/premake5/ninja/tests/static_lib/simple/test1.c create mode 100644 vendor/premake5/ninja/tests/static_lib/simple/test1.h create mode 100644 vendor/premake5/ninja/tests/static_lib/withapp/main.cpp create mode 100644 vendor/premake5/ninja/tests/static_lib/withapp/premake5.lua create mode 100644 vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.c create mode 100644 vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.h create mode 100644 vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.cpp create mode 100644 vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.h create mode 100644 vendor/premake5/ninja/tests/windowed_app/simple/main.cpp create mode 100644 vendor/premake5/ninja/tests/windowed_app/simple/premake5.lua create mode 100644 vendor/premake5/ninja/tests/windowed_app/simple/test1.c create mode 100644 vendor/premake5/ninja/tests/windowed_app/simple/test1.h create mode 100644 vendor/premake5/ninja/tests/windowed_app/simple/test2.cpp create mode 100644 vendor/premake5/ninja/tests/windowed_app/simple/test2.h diff --git a/.gitignore b/.gitignore index 6647f99..634cd24 100644 --- a/.gitignore +++ b/.gitignore @@ -381,4 +381,6 @@ Makefile *.o -*.d \ No newline at end of file +*.d + +*.ninja* \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 0000000..e54e87a --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,102 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..53624c9 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/build-ninja.sh b/build-ninja.sh new file mode 100755 index 0000000..3b32607 --- /dev/null +++ b/build-ninja.sh @@ -0,0 +1,5 @@ +#! /bin/bash + +./vendor/premake5/premake5 ecc +./vendor/premake5/premake5 ninja +ninja $1 \ No newline at end of file diff --git a/build b/build.sh similarity index 100% rename from build rename to build.sh diff --git a/clean-ninja.sh b/clean-ninja.sh new file mode 100755 index 0000000..b5e1ed7 --- /dev/null +++ b/clean-ninja.sh @@ -0,0 +1,7 @@ +#! /bin/bash +if [ -z "$1" ] || [ $# -eq 0 ] + then + ninja debug -t clean && ninja release -t clean + else + ninja $1 -t clean +fi \ No newline at end of file diff --git a/clean b/clean.sh similarity index 100% rename from clean rename to clean.sh diff --git a/include/Entities.h b/include/Entities.h index dc2779e..4a41691 100644 --- a/include/Entities.h +++ b/include/Entities.h @@ -5,4 +5,5 @@ #include #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/include/Entities/Components.h b/include/Entities/Components.h index b9c7241..9067825 100644 --- a/include/Entities/Components.h +++ b/include/Entities/Components.h @@ -3,8 +3,6 @@ //#include #include -#include -#include class Component { @@ -15,18 +13,14 @@ public: class Transform : public Component { -//potential optimization - remove angle variable -//added time for calculations but possible speed increase from cache freindliness public: sf::Vector2f position{}; - float speed{}; - sf::Angle facing{}; + sf::Vector2f speed{}; Transform() = default; - Transform(sf::Vector2f position_in, float speed_in, sf::Angle facing_in) + Transform(sf::Vector2f position_in, sf::Vector2f speed_in) : position(position_in) , speed(speed_in) - , facing(facing_in) { } }; diff --git a/include/Entities/Entity.h b/include/Entities/Entity.h index 28b81dd..0406579 100644 --- a/include/Entities/Entity.h +++ b/include/Entities/Entity.h @@ -1,25 +1,21 @@ #pragma once -#include -//#include - -using EntityIndex = uint16_t; - -enum EntityTag : uint8_t -{ - none, - - tagCount -}; - +#include class EntityManager; +class EntityViewIterator; +class EntityViewConstIterator; class Entity { -private: +//private: +public: friend class EntityManager; - Entity(); + friend class EntityViewIterator; + friend class EntityViewConstIterator; + + Entity() = delete; + Entity(EntityIndex); public: template @@ -34,6 +30,8 @@ public: template void addComponent(const T&&); + EntityIndex id() const; + EntityTag tag() const; bool isAlive() const; diff --git a/include/Entities/EntityManager.h b/include/Entities/EntityManager.h index 5fa3905..0697b55 100644 --- a/include/Entities/EntityManager.h +++ b/include/Entities/EntityManager.h @@ -1,9 +1,19 @@ #pragma once +#include "Entities/Entity.h" +#include "Entities/EntityView.h" +#include "utility.h" #include +#include class EntityManager { private: - -}; \ No newline at end of file + EntityView getEntiites(EntityTag); + + inline Entity player(); +private: + Entity m_player{0}; + std::array m_numEntitiesByTag{}; + u16 m_numEntities{}; +}; diff --git a/include/Entities/EntityMemoryPool.h b/include/Entities/EntityMemoryPool.h index 61ca55a..c61498b 100644 --- a/include/Entities/EntityMemoryPool.h +++ b/include/Entities/EntityMemoryPool.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -20,8 +19,6 @@ private: ComponentVectorTuple m_components; std::vector m_tags; std::vector m_aliveStates; - size_t m_entityCount; // for debugging purposes, should not be included in release version - bool m_holePresent{false}; private: EntityMemoryPool(); diff --git a/include/Entities/EntityView.h b/include/Entities/EntityView.h new file mode 100644 index 0000000..71f9e80 --- /dev/null +++ b/include/Entities/EntityView.h @@ -0,0 +1,83 @@ +#pragma once + +#include "utility.h" +#include + +class EntityView; + +class EntityViewIterator +{ + friend class EntityView; + + EntityViewIterator(EntityIndex); + + EntityViewIterator& operator++(); + + EntityViewIterator operator++(int); + + EntityViewIterator& operator--(); + + EntityViewIterator operator--(int); + + Entity operator*(); + + Entity operator[](int); + Entity* operator->(); + + bool operator==(EntityViewIterator); + bool operator!=(EntityViewIterator); + +private: + Entity m_currentEntity; +}; + +class EntityViewConstIterator +{ + friend class EntityView; + + EntityViewConstIterator(EntityIndex index); + + EntityViewConstIterator& operator++(); + + EntityViewConstIterator operator++(int); + + EntityViewConstIterator& operator--(); + + EntityViewConstIterator operator--(int); + + const Entity operator*(); + + const Entity operator[](int index); + + const Entity* operator->(); + + + bool operator==(EntityViewConstIterator); + bool operator!=(EntityViewConstIterator); + +private: + Entity m_currentEntity; +}; + +class EntityView +{ +public: + friend class EntityManager; + EntityView() = delete; + EntityView(EntityIndex, EntityIndex); + + using iterator = EntityViewIterator; + using const_iterator = EntityViewConstIterator; + + iterator begin() { return iterator(m_start); } + iterator end() { return iterator(m_start + m_size); } + + + + const_iterator cbegin() const { return const_iterator(m_start); } + const_iterator cend() const { return const_iterator(m_start + m_size); } +private: + EntityIndex m_start; + EntityIndex m_size; +}; + diff --git a/include/Globals.h b/include/Globals.h deleted file mode 100644 index a601224..0000000 --- a/include/Globals.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include - -namespace Global -{ - inline constexpr size_t MAX_ENTITIES {10'000u}; -} \ No newline at end of file diff --git a/include/SwapBackVector.hpp b/include/SwapBackVector.hpp deleted file mode 100644 index 0cbcf09..0000000 --- a/include/SwapBackVector.hpp +++ /dev/null @@ -1,236 +0,0 @@ -#pragma once - -#include "Globals.h" -#include -#include -#include -#include -#include -#include -#include -#include - - -template -class SwapBackVector -{ -public: - //iterator typedefs - using iterator_category = std::forward_iterator_tag; - using difference_type = std::ptrdiff_t; - using data_type = T; - using iterator = SwapBackVectorIterator>; - using const_iterator = SwapBackVectorConstIterator>; - -public: - SwapBackVector() - { - m_data = new T[capacity_in]; - } - - ~SwapBackVector() - { - delete[] m_data; - } - - SwapBackVector(const SwapBackVector& other) - { - m_nextValidIndex = other.m_nextValidIndex; - for (int i = 0; i < m_nextValidIndex; i++) - { - m_data[i] = other.m_data[i]; - } - } - - SwapBackVector(SwapBackVector&& other) - { - m_data = other.m_data; - other.m_data = nullptr; - m_nextValidIndex = other.m_nextValidIndex; - } - - SwapBackVector& operator=(const SwapBackVector& rhs) - { - if (this == &rhs) return this; - - m_nextValidIndex = rhs.m_nextValidIndex; - for (int i = 0; i < m_nextValidIndex; i++) - { - m_data[i] = rhs.m_data[i]; - } - return *this; - } - - SwapBackVector& operator=(SwapBackVector&& rhs) - { - if (this == &rhs) return this; - - delete[] m_data; - m_data = rhs.m_data; - rhs.m_data = nullptr; - - return *this; - } - -public: - T& operator[](EntityIndex index) - { - assert(index < m_nextValidIndex && "ASSERT ERROR -> SwapBackVector.hpp: attempting to index beyond next valid index"); - return m_data[index]; - } - - const T& operator[](EntityIndex index) const - { - assert(index < m_nextValidIndex && "ASSERT ERROR -> SwapBackVector.hpp: attempting to index beyond next valid index"); - return m_data[index]; - } - -public: - T* data() { return m_data; } - - const T* data() const { return m_data; } - - void remove(EntityIndex index) - { - if (index >= m_nextValidIndex) return; - - m_data[index] = m_data[m_nextValidIndex - 1]; - m_nextValidIndex--; - } - - void push() - { - assert(capacity_in > m_nextValidIndex); - - m_data[m_nextValidIndex] = T(); - m_nextValidIndex++; - } - - void push(const T& data) - { - assert(capacity_in > m_nextValidIndex); - - m_data[m_nextValidIndex] = data; - m_nextValidIndex++; - } - inline EntityIndex size() const { return m_nextValidIndex; } - - inline constexpr EntityIndex capacity() const { return capacity_in; } - - iterator begin() { return iterator(m_data); } - - iterator end() { return iterator(m_data + m_nextValidIndex); } - - const_iterator cbegin() const { return const_iterator(m_data); } - - const_iterator cend() const { return const_iterator(m_data + m_nextValidIndex); } - -private: - T* m_data; - EntityIndex m_nextValidIndex{}; -}; - - -//bool specialization -template -class SwapBackVector -{ -public: - SwapBackVector() - { - m_data = new uint8_t[(capacity_in / 8) + 1]; - } - - ~SwapBackVector() - { - delete[] m_data; - } - - SwapBackVector(const SwapBackVector& other) = delete; - SwapBackVector(SwapBackVector&& other) = delete; - - SwapBackVector& operator=(const SwapBackVector& rhs) = delete; - SwapBackVector& operator=(SwapBackVector&& rhs) = delete; - -public: - bool operator[](EntityIndex index) - { - //assert(index < m_nextValidIndex && "ASSERT ERROR -> SwapBackVector.hpp: attempting to index beyond next valid index"); - EntityIndex clusterIndex = index / 8u; - EntityIndex stateIndex = index % 8u; - return m_data[clusterIndex] & (1 << stateIndex); - } - - friend std::ostream& operator<<(std::ostream&, const SwapBackVector&); -public: - void remove(EntityIndex index) - { - if (index >= m_nextValidIndex) return; - - readAt(m_nextValidIndex - 1) ? setTrueAt(index) : setFalseAt(index); - m_nextValidIndex--; - } - - void push() - { - assert(capacity_in > m_nextValidIndex); - - setFalseAt(m_nextValidIndex); - m_nextValidIndex++; - } - - void push(bool state) - { - assert(capacity_in > m_nextValidIndex); - - state ? setTrueAt(m_nextValidIndex) : setFalseAt(m_nextValidIndex); - m_nextValidIndex++; - } - - bool readAt(EntityIndex index) const - { - EntityIndex clusterIndex = index / 8u; - EntityIndex stateIndex = index % 8u; - return m_data[clusterIndex] & 1 << stateIndex; - } - - void setTrueAt(EntityIndex index) - { - EntityIndex clusterIndex = index / 8u; - EntityIndex stateIndex = index % 8u; - m_data[clusterIndex] |= 1 << stateIndex; - } - - void setFalseAt(EntityIndex index) - { - EntityIndex clusterIndex = index / 8u; - EntityIndex stateIndex = index % 8u; - m_data[clusterIndex] &= ~(1 << stateIndex); - } - - inline EntityIndex size() const { return m_nextValidIndex; } - - inline constexpr EntityIndex capacity() const { return capacity_in; } - -private: - uint8_t* m_data; - EntityIndex m_nextValidIndex{}; -}; - -inline std::ostream& operator<<(std::ostream& out, const SwapBackVector& vec) -{ - for(size_t i = 0; i < (vec.size() / 8) + 1; i++) - { - out << std::bitset<8>(vec.m_data[i]) << " "; - } - out << "\n"; - return out; -} - -//Entity specialization -template -class SwapBackVector -{ - -}; - diff --git a/include/SwapBackVectorIterator.hpp b/include/SwapBackVectorIterator.hpp deleted file mode 100644 index 9861f16..0000000 --- a/include/SwapBackVectorIterator.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -//#include "SwapBackVector.hpp" -#include -#include -//#include -//#include -//#include - -template -class SwapBackVectorIterator -{ -public: - using data_type = typename SwapBackVector::data_type; - using pointer = data_type*; - using reference = data_type&; - -public: - SwapBackVectorIterator(pointer ptr) - : m_ptr(ptr) - {} - - SwapBackVectorIterator& operator++() - { - m_ptr++; - return *this; - } - - SwapBackVectorIterator operator++(int) - { - SwapBackVectorIterator it = *this; - ++(*this); - return it; - } - - SwapBackVectorIterator& operator--() - { - m_ptr--; - return *this; - } - - SwapBackVectorIterator operator--(int) - { - SwapBackVectorIterator it = *this; - --(*this); - return it; - } - - reference operator[](int index) { return m_ptr[index]; } - - pointer operator->() { return m_ptr; } - - reference operator*() { return *m_ptr; } - - bool operator==(const SwapBackVectorIterator& rhs) { return m_ptr == rhs.m_ptr; } - bool operator!=(const SwapBackVectorIterator& rhs) { return !(m_ptr == rhs.m_ptr); } -private: - data_type* m_ptr; -}; - - - -template -class SwapBackVectorConstIterator -{ -public: - using data_type = typename SwapBackVector::data_type; - using pointer = const data_type*; - using reference = const data_type&; - -public: - SwapBackVectorConstIterator(pointer ptr) - : m_ptr(ptr) - {} - - SwapBackVectorConstIterator& operator++() - { - m_ptr++; - return *this; - } - - SwapBackVectorConstIterator operator++(int) - { - SwapBackVectorConstIterator it = *this; - ++(*this); - return it; - } - - SwapBackVectorConstIterator& operator--() - { - m_ptr--; - return *this; - } - - SwapBackVectorConstIterator operator--(int) - { - SwapBackVectorConstIterator it = *this; - --(*this); - return it; - } - - reference operator[](int index) { return m_ptr[index]; } - - pointer operator->() { return m_ptr; } - - reference operator*() { return *m_ptr; } - - bool operator==(const SwapBackVectorConstIterator& rhs) { return m_ptr == rhs.m_ptr; } - bool operator!=(const SwapBackVectorConstIterator& rhs) { return !(m_ptr == rhs.m_ptr); } -private: - data_type* m_ptr; -}; diff --git a/include/log.h b/include/log.h new file mode 100644 index 0000000..941e055 --- /dev/null +++ b/include/log.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#ifdef LOG_ENABLE +#define LOG(x) std::cout << x << "\n" +#else +#define LOG(x) +#endif \ No newline at end of file diff --git a/include/utility.h b/include/utility.h index a372240..dbc2c65 100644 --- a/include/utility.h +++ b/include/utility.h @@ -1,24 +1,56 @@ #pragma once -#include - #include -#include +#include #include +using u8 = uint8_t; +using u16 = uint16_t; +using u32 = uint32_t; +using u64 = uint64_t; +using s8 = int8_t; +using s16 = int16_t; +using s32 = int32_t; +using s64 = int64_t; + +using EntityIndex = u16; + +enum EntityTag : u8 +{ + player, + tile, + enemy, + tagCount +}; + + + namespace util { using namespace std::string_view_literals; + + inline constexpr EntityIndex MAX_ENTITIES {60'000u}; + inline constexpr EntityIndex MAX_TILES {1'000u}; + inline constexpr EntityIndex MAX_ENEMIES {1'000u}; + // used for imgui - inline constexpr std::array tagStringsC = + inline constexpr std::array tagStringsC = { - "none" + "player" }; - inline constexpr std::array tagStrings = + inline constexpr std::array tagStrings = { - "none"sv + "player"sv }; - -} \ No newline at end of file + + inline constexpr std::array tagStart = + { + 0,//player + 1,//tile start + MAX_TILES,//enemy start + }; +} + + diff --git a/premake5.lua b/premake5.lua index 7e87b04..2cd2ad0 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,4 +1,5 @@ require "ecc/ecc" +require "ninja/ninja" workspace "fake-mario" architecture "x64" @@ -27,8 +28,9 @@ local vs_includedir = "$(SolutionDir)include" local includedir = "%{wks.location}/include" project "fake-mario" - cppdialect "C++17" language "C++" + cppdialect "C++17" + systemversion "latest" files { @@ -42,11 +44,11 @@ project "fake-mario" "vendor/imgui/imgui-SFML.cpp" } + --visual studio-- filter {"action:vs*", "system:windows"} targetdir (vs_bindir) objdir (vs_intdir) - staticruntime "on" includedirs { vs_includedir, @@ -60,6 +62,7 @@ project "fake-mario" filter {"action:vs*", "system:windows", "configurations:release"} libdirs {vs_libreldir} + --not visual studio on windows-- filter {"not action:vs*", "system:windows"} targetdir (bindir) @@ -77,17 +80,14 @@ project "fake-mario" libdirs {libreldir} - - --platform specific settings-- + --windows specific settings-- filter{"system:windows"} - systemversion "latest" defines "SFML_STATIC" defines "PLATFORM_WINDOWS" + staticruntime "on" filter {"system:windows", "configurations:debug"} - kind "ConsoleApp" defines{"_DEBUG", "_CONSOLE"} - runtime "Debug" links { "sfml-graphics-s-d", @@ -108,12 +108,7 @@ project "fake-mario" } filter {"system:windows", "configurations:release"} - kind "WindowedApp" - optimize "Speed" - inlining "Auto" - entrypoint "mainCRTStartup" defines{"NDEBUG"} - runtime "Release" links { "sfml-graphics-s", @@ -133,17 +128,17 @@ project "fake-mario" "winmm" } + + --linux specific settings filter {"system:linux"} targetdir (bindir) objdir (intdir) + defines "PLATFORM_LINUX" includedirs { includedir, - sfmldir .. "/include", imguidir } - systemversion "latest" - defines "PLATFORM_LINUX" links { "sfml-graphics", @@ -154,15 +149,18 @@ project "fake-mario" "OpenGL", } - filter {"system:linux" , "configurations:debug"} - kind "ConsoleApp" + + --config settings + filter "configurations:debug" + defines"LOG_ENABLE" symbols "on" runtime "Debug" - - filter {"system:linux" , "configurations:release"} - kind "WindowedApp" + kind "ConsoleApp" + + filter "configurations:release" optimize "Speed" inlining "Auto" - entrypoint "mainCRTStartup" symbols "off" runtime "Release" + kind "WindowedApp" + entrypoint "mainCRTStartup" diff --git a/run b/run.sh similarity index 100% rename from run rename to run.sh diff --git a/src/Classes/Entity.cpp b/src/Classes/Entity.cpp index 043afae..dea76b0 100644 --- a/src/Classes/Entity.cpp +++ b/src/Classes/Entity.cpp @@ -3,7 +3,12 @@ #include #include -//#include + +Entity::Entity(EntityIndex id_in) + : m_id(id_in) +{ + +} template bool Entity::hasComponent() const @@ -31,6 +36,11 @@ void Entity::addComponent(const T&& data) component.active = true; } +EntityIndex Entity::id() const +{ + return m_id; +} + EntityTag Entity::tag() const { return EntityMemoryPool::instance().getTag(m_id); diff --git a/src/Classes/EntityManager.cpp b/src/Classes/EntityManager.cpp index 571c3ef..4a99138 100644 --- a/src/Classes/EntityManager.cpp +++ b/src/Classes/EntityManager.cpp @@ -1,4 +1,16 @@ +#include "Entities/EntityView.h" +#include "utility.h" #include #include +inline constexpr EntityIndex PLAYER_INDEX = 0; +inline Entity EntityManager::player() +{ + return m_player; +} + +EntityView EntityManager::getEntiites(EntityTag tag) +{ + return EntityView(util::tagStart[tag], m_numEntitiesByTag[tag]); +} \ No newline at end of file diff --git a/src/Classes/EntityMemoryPool.cpp b/src/Classes/EntityMemoryPool.cpp index 9e7a471..baec869 100644 --- a/src/Classes/EntityMemoryPool.cpp +++ b/src/Classes/EntityMemoryPool.cpp @@ -1,16 +1,14 @@ #include #include -#include -//#include #include +#include EntityMemoryPool::EntityMemoryPool() { - std::apply([=](auto&&... args) {((args.reserve(Global::MAX_ENTITIES)), ...); }, m_components); - m_tags.reserve(Global::MAX_ENTITIES); - m_aliveStates.reserve(Global::MAX_ENTITIES); - + std::apply([=](auto&&... args) {((args.reserve(util::MAX_ENTITIES)), ...); }, m_components); + m_tags.reserve(util::MAX_ENTITIES); + m_aliveStates.reserve(util::MAX_ENTITIES); } EntityMemoryPool& EntityMemoryPool::instance() @@ -45,4 +43,10 @@ EntityTag EntityMemoryPool::getTag(EntityIndex id) const bool EntityMemoryPool::getAlive(EntityIndex id) const { return m_aliveStates[id]; +} + +void EntityMemoryPool::removeEntity(EntityIndex id) +{ + m_aliveStates[id] = false; + return; } \ No newline at end of file diff --git a/src/Classes/EntityView.cpp b/src/Classes/EntityView.cpp new file mode 100644 index 0000000..9375981 --- /dev/null +++ b/src/Classes/EntityView.cpp @@ -0,0 +1,123 @@ + +#include +#include "utility.h" + +EntityView::EntityView(EntityIndex start, EntityIndex size) + : m_start(start) + , m_size(size) +{ + +} + + +//non-const iterator +EntityViewIterator::EntityViewIterator(EntityIndex index) + : m_currentEntity(index) +{ + +} + +EntityViewIterator& EntityViewIterator::operator++() +{ + m_currentEntity.m_id++; + return *this; +} + +EntityViewIterator EntityViewIterator::operator++(int) +{ + m_currentEntity.m_id++; + return m_currentEntity.m_id - 1; +} + +EntityViewIterator& EntityViewIterator::operator--() +{ + m_currentEntity.m_id--; + return *this; +} + +EntityViewIterator EntityViewIterator::operator--(int) +{ + m_currentEntity.m_id--; + return m_currentEntity.m_id + 1; +} + +Entity EntityViewIterator::operator*() +{ + return m_currentEntity; +} + +Entity EntityViewIterator::operator[](int index) +{ + return m_currentEntity.m_id + index; +} + +Entity* EntityViewIterator::operator->() +{ + return &m_currentEntity; +} + +bool EntityViewIterator::operator==(EntityViewIterator other) +{ + return m_currentEntity.m_id == other->m_id; +} + +bool EntityViewIterator::operator!=(EntityViewIterator other) +{ + return m_currentEntity.m_id != other->m_id; +} + +//const iterator +EntityViewConstIterator::EntityViewConstIterator(EntityIndex index) + : m_currentEntity(index) +{ + +} + +EntityViewConstIterator& EntityViewConstIterator::operator++() +{ + m_currentEntity.m_id++; + return *this; +} + +EntityViewConstIterator EntityViewConstIterator::operator++(int) +{ + m_currentEntity.m_id++; + return m_currentEntity.m_id - 1; +} + +EntityViewConstIterator& EntityViewConstIterator::operator--() +{ + m_currentEntity.m_id--; + return *this; +} + +EntityViewConstIterator EntityViewConstIterator::operator--(int) +{ + m_currentEntity.m_id--; + return m_currentEntity.m_id + 1; +} + +const Entity EntityViewConstIterator::operator*() +{ + return m_currentEntity; +} + +const Entity EntityViewConstIterator::operator[](int index) +{ + return m_currentEntity.m_id + index; +} + +const Entity* EntityViewConstIterator::operator->() +{ + return &m_currentEntity; +} + +bool EntityViewConstIterator::operator==(EntityViewConstIterator other) +{ + return m_currentEntity.m_id == other->m_id; +} + +bool EntityViewConstIterator::operator!=(EntityViewConstIterator other) +{ + return m_currentEntity.m_id != other->m_id; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index d120f8c..d463fa1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,29 +1,15 @@ -#include "Globals.h" -#include "SwapBackVector.hpp" + #include #include #include -//#include #include #include #include +#include int main() { - SwapBackVector arr; - - arr.push(true); - arr.push(true); - arr.push(); - - arr.setTrueAt(0); - - std::cout << arr; - // for (auto x : arr) - // { - // std::cout << x << "\n"; - // } auto window = sf::RenderWindow(sf::VideoMode({ 1920u, 1080u }), "Fake Mario"); window.setFramerateLimit(144); diff --git a/vendor/premake5/ninja/.github/dependabot.yml b/vendor/premake5/ninja/.github/dependabot.yml new file mode 100644 index 0000000..d80af56 --- /dev/null +++ b/vendor/premake5/ninja/.github/dependabot.yml @@ -0,0 +1,13 @@ +# Keep GitHub Actions up to date with GitHub's Dependabot... dependabot.yml +# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + groups: + github-actions: + patterns: + - "*" # Group all Actions updates into a single larger pull request + schedule: + interval: weekly diff --git a/vendor/premake5/ninja/.github/workflows/macos.yml b/vendor/premake5/ninja/.github/workflows/macos.yml new file mode 100644 index 0000000..3d768de --- /dev/null +++ b/vendor/premake5/ninja/.github/workflows/macos.yml @@ -0,0 +1,41 @@ +name: macos + +on: + workflow_dispatch: + push: + paths: + - '.github/workflows/macos.yml' + - 'tests/**' + - '**/*.lua' + + pull_request: + paths: + - '.github/workflows/macos.yml' + - 'tests/**' + - '**/*.lua' + +jobs: + macos: + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: mymindstorm/setup-emsdk@v14 + + - name: install premake5 + uses: Jarod42/install-premake5@v6 + + - name: install ninja + uses: seanmiddleditch/gha-setup-ninja@v6 + + - name: Versions + run: | + python --version + premake5 --version + ninja --version + + - name: test projects + run: cd tests && python run_tests.py + diff --git a/vendor/premake5/ninja/.github/workflows/ubuntu.yml b/vendor/premake5/ninja/.github/workflows/ubuntu.yml new file mode 100644 index 0000000..a658e5c --- /dev/null +++ b/vendor/premake5/ninja/.github/workflows/ubuntu.yml @@ -0,0 +1,45 @@ +name: ubuntu + +on: + workflow_dispatch: + push: + paths: + - '.github/workflows/ubuntu.yml' + - 'tests/**' + - '**/*.lua' + + pull_request: + paths: + - '.github/workflows/ubuntu.yml' + - 'tests/**' + - '**/*.lua' + +jobs: + ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: mymindstorm/setup-emsdk@v14 + + - name: install premake5 + uses: Jarod42/install-premake5@v6 + + - name: apt-get update + run: sudo apt-get update -y + + - name: apt-get install ninja-build + run: | + sudo apt-get install -y ninja-build + + - name: Versions + run: | + python --version + premake5 --version + ninja --version + + - name: test projects + run: cd tests && python run_tests.py + diff --git a/vendor/premake5/ninja/.github/workflows/windows.yml b/vendor/premake5/ninja/.github/workflows/windows.yml new file mode 100644 index 0000000..7ca4b7a --- /dev/null +++ b/vendor/premake5/ninja/.github/workflows/windows.yml @@ -0,0 +1,44 @@ +name: windows + +on: + workflow_dispatch: + push: + paths: + - '.github/workflows/windows.yml' + - 'tests/**' + - '**/*.lua' + + pull_request: + paths: + - '.github/workflows/windows.yml' + - 'tests/**' + - '**/*.lua' + +jobs: + windows: + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: mymindstorm/setup-emsdk@v14 + + - name: install premake5 + uses: Jarod42/install-premake5@v6 + + - name: install ninja + uses: seanmiddleditch/gha-setup-ninja@v6 + + - name: Versions + run: | + python --version + premake5 --version + ninja --version + + - name: Add cl.exe to PATH + uses: ilammy/msvc-dev-cmd@v1 + + - name: test projects + run: cd tests && python run_tests.py + shell: bash diff --git a/vendor/premake5/ninja/LICENSE b/vendor/premake5/ninja/LICENSE new file mode 100644 index 0000000..b71e184 --- /dev/null +++ b/vendor/premake5/ninja/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Dmitry Ivanov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/premake5/ninja/README.md b/vendor/premake5/ninja/README.md new file mode 100644 index 0000000..a897467 --- /dev/null +++ b/vendor/premake5/ninja/README.md @@ -0,0 +1,43 @@ +# premake-ninja + +[Premake](https://github.com/premake/premake-core) module to support [Ninja](https://github.com/martine/ninja), because it's awesome. + +## Usage (little reminder) +1. Put these files in a "premake-ninja" subdirectory of [Premake search paths](https://premake.github.io/docs/Locating-Scripts/).
+ +2. Adapt your premake5.lua script, or better: create/adapt your [premake-system.lua](https://premake.github.io/docs/System-Scripts/) + +```lua +require "premake-ninja/ninja" +``` + +3. Generate ninja files + +```sh +premake5 ninja +``` +On msys2 (mingw) +```sh +premake5 ninja --cc=gcc --shell=posix +``` + +4. Run ninja + +For each project - configuration pair, we create separate .ninja file. For solution we create build.ninja file which imports other .ninja files with subninja command. + +Build.ninja file sets phony targets for configuration names so you can build them from command line. And default target is the first configuration name in your project (usually default). + +General from: +```sh +ninja $(YourProjectName)_$(ConfigName) +``` +as example: +```sh +ninja myapp_Release +``` + +### Tested on ![ubuntu-badge](https://github.com/jimon/premake-ninja/actions/workflows/ubuntu.yml/badge.svg) ![windows-badge](https://github.com/jimon/premake-ninja/actions/workflows/windows.yml/badge.svg) ![macos-badge](https://github.com/jimon/premake-ninja/actions/workflows/macos.yml/badge.svg) + +### Extra Tests + +Part of integration tests of several generators in https://github.com/Jarod42/premake-sample-projects ![Premake5 ubuntu ninja badge](https://github.com/Jarod42/premake-sample-projects/actions/workflows/premake5-ubuntu-ninja.yml/badge.svg)![Premake5 window ninja badge](https://github.com/Jarod42/premake-sample-projects/actions/workflows/premake5-windows-ninja.yml/badge.svg) diff --git a/vendor/premake5/ninja/_manifest.lua b/vendor/premake5/ninja/_manifest.lua new file mode 100644 index 0000000..31fb223 --- /dev/null +++ b/vendor/premake5/ninja/_manifest.lua @@ -0,0 +1,4 @@ +return { + "_preload.lua", + "ninja.lua", +} diff --git a/vendor/premake5/ninja/_preload.lua b/vendor/premake5/ninja/_preload.lua new file mode 100644 index 0000000..aeb1177 --- /dev/null +++ b/vendor/premake5/ninja/_preload.lua @@ -0,0 +1,60 @@ +-- +-- Name: premake-ninja/_preload.lua +-- Purpose: Define the ninja action. +-- Author: Dmitry Ivanov +-- Created: 2015/07/04 +-- Copyright: (c) 2015 Dmitry Ivanov +-- + + local p = premake + + newaction + { + -- Metadata for the command line and help system + trigger = "ninja", + shortname = "ninja", + description = "Ninja is a small build system with a focus on speed", + + -- The capabilities of this action + valid_kinds = {"ConsoleApp", "WindowedApp", "SharedLib", "StaticLib", "None"}, -- Not supported: Makefile, Packaging, SharedItems, Utility + valid_languages = {"C", "C++"}, + valid_tools = {cc = { "gcc", "clang", "msc", "emcc" }}, + + toolset = iif(os.target() == "windows", "msc-v142", -- Visual Studio 2019 + iif(os.target() == "macosx", "clang", "gcc")), + + -- Workspace and project generation logic + onWorkspace = function(wks) + p.eol("\r\n") + p.indent(" ") + p.generate(wks, "build.ninja", p.modules.ninja.generateWorkspace) + end, + onProject = function(prj) + p.eol("\r\n") + p.indent(" ") + p.modules.ninja.generateProject(prj) + end, + onBranch = function(prj) + p.eol("\r\n") + p.indent(" ") + p.modules.ninja.generateProject(prj) + end, + onCleanSolution = function(sln) + -- TODO + end, + onCleanProject = function(prj) + -- TODO + end, + onCleanTarget = function(prj) + -- TODO + end, + } + + +-- +-- Decide when the full module should be loaded. +-- + + return function(cfg) + return (_ACTION == "ninja") + end diff --git a/vendor/premake5/ninja/ninja.lua b/vendor/premake5/ninja/ninja.lua new file mode 100644 index 0000000..6c6aa55 --- /dev/null +++ b/vendor/premake5/ninja/ninja.lua @@ -0,0 +1,845 @@ +-- +-- Name: premake-ninja/ninja.lua +-- Purpose: Define the ninja action. +-- Author: Dmitry Ivanov +-- Created: 2015/07/04 +-- Copyright: (c) 2015 Dmitry Ivanov +-- + +local p = premake +local tree = p.tree +local project = p.project +local config = p.config +local fileconfig = p.fileconfig + +-- Some toolset fixes/helper +p.tools.clang.objectextension = ".o" +p.tools.gcc.objectextension = ".o" +p.tools.msc.objectextension = ".obj" + +p.tools.clang.tools.rc = p.tools.clang.tools.rc or "windres" + +p.tools.msc.gettoolname = function(cfg, name) + local map = {cc = "cl", cxx = "cl", ar = "lib", rc = "rc"} + return map[name] +end + +-- Ninja module +premake.modules.ninja = {} +local ninja = p.modules.ninja + +ninja.handlers = {} + +function ninja.register_handler(kind, compilation_rules, target_rules) + ninja.handlers[kind] = { compilation_rules = compilation_rules, target_rules = target_rules } +end + +local function get_key(cfg, name) + local name = name or cfg.project.name + + if cfg.platform then + return name .. "_" .. cfg.buildcfg .. "_" .. cfg.platform + else + return name .. "_" .. cfg.buildcfg + end +end + +local build_cache = {} + +function ninja.add_build(cfg, out, implicit_outputs, command, inputs, implicit_inputs, dependencies, vars) + implicit_outputs = ninja.list(table.translate(implicit_outputs, ninja.esc)) + if #implicit_outputs > 0 then + implicit_outputs = " |" .. implicit_outputs + else + implicit_outputs = "" + end + + inputs = ninja.list(table.translate(inputs, ninja.esc)) + + implicit_inputs = ninja.list(table.translate(implicit_inputs, ninja.esc)) + if #implicit_inputs > 0 then + implicit_inputs = " |" .. implicit_inputs + else + implicit_inputs = "" + end + + dependencies = ninja.list(table.translate(dependencies, ninja.esc)) + if #dependencies > 0 then + dependencies = " ||" .. dependencies + else + dependencies = "" + end + build_line = "build " .. ninja.esc(out) .. implicit_outputs .. ": " .. command .. inputs .. implicit_inputs .. dependencies + + local cached = build_cache[out] + if cached ~= nil then + if build_line == cached.build_line + and table.equals(vars or {}, cached.vars or {}) + then + -- custom_command/copy rule are identical for each configuration (contrary to other rules) + -- So we can compare extra parameter + if command == "custom_command" or command == "copy" then + p.outln("# INFO: Rule ignored, same as " .. cached.cfg_key) + else + local cfg_key = get_key(cfg) + p.warn(cached.cfg_key .. " and " .. cfg_key .. " both generate (differently?) " .. out .. ". Ignoring " .. cfg_key) + p.outln("# WARNING: Rule ignored, using the one from " .. cached.cfg_key) + end + else + local cfg_key = get_key(cfg) + p.warn(cached.cfg_key .. " and " .. cfg_key .. " both generate differently " .. out .. ". Ignoring " .. cfg_key) + p.outln("# ERROR: Rule ignored, using the one from " .. cached.cfg_key) + end + p.outln("# " .. build_line) + for i, var in ipairs(vars or {}) do + p.outln("# " .. var) + end + return + end + p.outln(build_line) + for i, var in ipairs(vars or {}) do + p.outln(" " .. var) + end + build_cache[out] = { + cfg_key = get_key(cfg), + build_line = build_line, + vars = vars + } +end + +function ninja.esc(value) + value = value:gsub("%$", "$$") -- TODO maybe there is better way + value = value:gsub(":", "$:") + value = value:gsub("\n", "$\n") + value = value:gsub(" ", "$ ") + return value +end + +function ninja.quote(value) + value = value:gsub("\\", "\\\\") + value = value:gsub("'", "\\'") + value = value:gsub("\"", "\\\"") + + return "\"" .. value .. "\"" +end + +-- in some cases we write file names in rule commands directly +-- so we need to propely escape them +function ninja.shesc(value) + if type(value) == "table" then + local result = {} + local n = #value + for i = 1, n do + table.insert(result, ninja.shesc(value[i])) + end + return result + end + + if value:find(' ') or value:find('"') or value:find('(', 1, true) or value:find(')') or value:find('|') or value:find('&') then + return ninja.quote(value) + end + return value +end + +function ninja.can_generate(prj) + return p.action.supports(prj.kind) and prj.kind ~= p.NONE +end + +-- generate solution that will call ninja for projects +function ninja.generateWorkspace(wks) + local oldGetDefaultSeparator = path.getDefaultSeparator + path.getDefaultSeparator = function() return "/" end + + p.outln("# solution build file") + p.outln("# generated with premake ninja") + p.outln("") + + p.outln("# build projects") + local cfgs = {} -- key is concatenated name or variant name, value is string of outputs names + local key = "" + local cfg_first = nil + local cfg_first_lib = nil + local subninjas = {} + + for prj in p.workspace.eachproject(wks) do + if ninja.can_generate(prj) then + for cfg in p.project.eachconfig(prj) do + key = get_key(cfg) + + if not cfgs[cfg.buildcfg] then cfgs[cfg.buildcfg] = {} end + table.insert(cfgs[cfg.buildcfg], key) + + -- set first configuration name + if wks.defaultplatform == nil then + if (cfg_first == nil) and (cfg.kind == p.CONSOLEAPP or cfg.kind == p.WINDOWEDAPP) then + cfg_first = key + end + end + if (cfg_first_lib == nil) and (cfg.kind == p.STATICLIB or cfg.kind == p.SHAREDLIB) then + cfg_first_lib = key + end + if prj.name == wks.startproject then + if wks.defaultplatform == nil then + cfg_first = key + elseif cfg.platform == wks.defaultplatform then + if cfg_first == nil then + cfg_first = key + end + end + end + + -- include other ninja file + table.insert(subninjas, ninja.esc(ninja.projectCfgFilename(cfg, true))) + p.outln("subninja " .. ninja.esc(ninja.projectCfgFilename(cfg, true))) + end + end + end + + if cfg_first == nil then cfg_first = cfg_first_lib end + + p.outln("") + + p.outln("# targets") + for cfg, outputs in spairs(cfgs) do + p.outln("build " .. ninja.esc(cfg) .. ": phony" .. ninja.list(table.translate(outputs, ninja.esc))) + end + p.outln("") + + if wks.editorintegration then + -- we need to filter out the 'file' argument, since we already output + -- the script separately. + local args = {} + for _, arg in ipairs(_ARGV) do + if not (arg:startswith("--file") or arg:startswith("/file")) then + table.insert(args, arg); + end + end + table.sort(args) + + p.outln('# Rule') + p.outln('rule premake') + p.outln(' command = ' .. ninja.shesc(p.workspace.getrelative(wks, _PREMAKE_COMMAND)) .. ' --file=$in ' .. table.concat(ninja.shesc(args), ' ')) + p.outln(' generator = true') + p.outln(' restat = true') + p.outln("") + p.outln('build build.ninja ' .. table.concat(subninjas, " ") .. ': premake ' .. p.workspace.getrelative(wks, _MAIN_SCRIPT)) + p.outln("") + end + + if cfg_first then + p.outln("# default target") + p.outln("default " .. ninja.esc(cfg_first)) + p.outln("") + end + + path.getDefaultSeparator = oldGetDefaultSeparator +end + +function ninja.list(value) + if #value > 0 then + return " " .. table.concat(value, " ") + else + return "" + end +end + +local function shouldcompileasc(filecfg) + if filecfg.compileas and filecfg.compileas ~= "Default" then + return p.languages.isc(filecfg.compileas) + end + return path.iscfile(filecfg.abspath) +end + +local function shouldcompileascpp(filecfg) + if filecfg.compileas and filecfg.compileas ~= "Default" then + return p.languages.iscpp(filecfg.compileas) + end + return path.iscppfile(filecfg.abspath) +end + +local function getFileDependencies(cfg) + local dependencies = {} + if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then + dependencies = {"prebuild_" .. get_key(cfg)} + end + for i = 1, #cfg.dependson do + + local dependpostfix = "" + if cfg.platform then + dependpostfix = "_" .. cfg.platform + end + + table.insert(dependencies, cfg.dependson[i] .. "_" .. cfg.buildcfg .. dependpostfix) + end + return dependencies +end + +local function getcflags(toolset, cfg, filecfg) + p.escaper(ninja.shesc) + local buildopt = ninja.list(filecfg.buildoptions) + local cppflags = ninja.list(toolset.getcppflags(filecfg)) + local cflags = ninja.list(toolset.getcflags(filecfg)) + local defines = ninja.list(table.join(toolset.getdefines(filecfg.defines, filecfg), toolset.getundefines(filecfg.undefines))) + local includes = ninja.list(toolset.getincludedirs(cfg, filecfg.includedirs, filecfg.externalincludedirs, filecfg.frameworkdirs, filecfg.includedirsafter)) + local forceincludes = ninja.list(toolset.getforceincludes(cfg)) + p.escaper(nil) + + return buildopt .. cppflags .. cflags .. defines .. includes .. forceincludes +end + +local function getcxxflags(toolset, cfg, filecfg) + p.escaper(ninja.shesc) + local buildopt = ninja.list(filecfg.buildoptions) + local cppflags = ninja.list(toolset.getcppflags(filecfg)) + local cxxflags = ninja.list(toolset.getcxxflags(filecfg)) + local defines = ninja.list(table.join(toolset.getdefines(filecfg.defines, filecfg), toolset.getundefines(filecfg.undefines))) + local includes = ninja.list(toolset.getincludedirs(cfg, filecfg.includedirs, filecfg.externalincludedirs, filecfg.frameworkdirs, filecfg.includedirsafter)) + local forceincludes = ninja.list(toolset.getforceincludes(cfg)) + p.escaper(nil) + + return buildopt .. cppflags .. cxxflags .. defines .. includes .. forceincludes +end + +local function getldflags(toolset, cfg) + local ldflags = ninja.list(table.join(toolset.getLibraryDirectories(cfg), + toolset.getrunpathdirs(cfg, table.join(cfg.runpathdirs, config.getsiblingtargetdirs(cfg))), + toolset.getldflags(cfg), cfg.linkoptions)) + + -- experimental feature, change install_name of shared libs + --if (toolset == p.tools.clang) and (cfg.kind == p.SHAREDLIB) and ninja.endsWith(cfg.buildtarget.name, ".dylib") then + -- ldflags = ldflags .. " -install_name " .. cfg.buildtarget.name + --end + + return ldflags +end + +local function getresflags(toolset, cfg, filecfg) + p.escaper(ninja.shesc) + local defines = ninja.list(toolset.getdefines(table.join(filecfg.defines, filecfg.resdefines), filecfg)) + local includes = ninja.list(toolset.getincludedirs(cfg, table.join(filecfg.externalincludedirs, filecfg.includedirsafter, filecfg.includedirs, filecfg.resincludedirs), {}, {}, {})) + local options = ninja.list(cfg.resoptions) + p.escaper(nil) + + return defines .. includes .. options +end + +local function prebuild_rule(cfg) + if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then + local commands = {} + if cfg.prebuildmessage then + commands = {os.translateCommandsAndPaths("{ECHO} " .. cfg.prebuildmessage, cfg.workspace.basedir, cfg.workspace.location)} + end + commands = table.join(commands, os.translateCommandsAndPaths(cfg.prebuildcommands, cfg.workspace.basedir, cfg.workspace.location)) + if (#commands > 1) then + commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) + else + commands = commands[1] + end + p.outln("rule run_prebuild") + p.outln(" command = " .. commands) + p.outln(" description = prebuild") + p.outln("") + end +end + +local function prelink_rule(cfg) + if #cfg.prelinkcommands > 0 or cfg.prelinkmessage then + local commands = {} + if cfg.prelinkmessage then + commands = {os.translateCommandsAndPaths("{ECHO} " .. cfg.prelinkmessage, cfg.workspace.basedir, cfg.workspace.location)} + end + commands = table.join(commands, os.translateCommandsAndPaths(cfg.prelinkcommands, cfg.workspace.basedir, cfg.workspace.location)) + if (#commands > 1) then + commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) + else + commands = commands[1] + end + p.outln("rule run_prelink") + p.outln(" command = " .. commands) + p.outln(" description = prelink") + p.outln("") + end +end + +local function postbuild_rule(cfg) + if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then + local commands = {} + if cfg.postbuildmessage then + commands = {os.translateCommandsAndPaths("{ECHO} " .. cfg.postbuildmessage, cfg.workspace.basedir, cfg.workspace.location)} + end + commands = table.join(commands, os.translateCommandsAndPaths(cfg.postbuildcommands, cfg.workspace.basedir, cfg.workspace.location)) + if (#commands > 1) then + commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) + else + commands = commands[1] + end + p.outln("rule run_postbuild") + p.outln(" command = " .. commands) + p.outln(" description = postbuild") + p.outln("") + end +end + +local function c_cpp_compilation_rules(cfg, toolset, pch) + ---------------------------------------------------- figure out toolset executables + local cc = toolset.gettoolname(cfg, "cc") + local cxx = toolset.gettoolname(cfg, "cxx") + local ar = toolset.gettoolname(cfg, "ar") + local link = toolset.gettoolname(cfg, iif(cfg.language == "C", "cc", "cxx")) + local rc = toolset.gettoolname(cfg, "rc") + + -- all paths need to be relative to the workspace output location, + -- and not relative to the project output location. + -- override the toolset getrelative function to achieve this + + local getrelative = p.tools.getrelative + p.tools.getrelative = function(cfg, value) + return p.workspace.getrelative(cfg.workspace, value) + end + + local all_cflags = getcflags(toolset, cfg, cfg) + local all_cxxflags = getcxxflags(toolset, cfg, cfg) + local all_ldflags = getldflags(toolset, cfg) + local all_resflags = getresflags(toolset, cfg, cfg) + + if toolset == p.tools.msc then + p.outln("CFLAGS=" .. all_cflags) + p.outln("rule cc") + p.outln(" command = " .. cc .. " $CFLAGS" .. " /nologo /showIncludes -c /Tc$in /Fo$out") + p.outln(" description = cc $out") + p.outln(" deps = msvc") + p.outln("") + p.outln("CXXFLAGS=" .. all_cxxflags) + p.outln("rule cxx") + p.outln(" command = " .. cxx .. " $CXXFLAGS" .. " /nologo /showIncludes -c /Tp$in /Fo$out") + p.outln(" description = cxx $out") + p.outln(" deps = msvc") + p.outln("") + p.outln("CFLAGS=" .. all_cflags) + p.outln("rule clangtidy_cc") + p.outln(" command = clang-tidy $in -- -x c $CFLAGS &&$") + p.outln(" " .. cc .. " $CFLAGS" .. " /nologo /showIncludes -c /Tc$in /Fo$out") + p.outln(" description = cc $out") + p.outln(" deps = msvc") + p.outln("") + p.outln("CXXFLAGS=" .. all_cxxflags) + p.outln("rule clangtidy_cxx") + p.outln(" command = clang-tidy $in -- -x c++ $CFLAGS &&$") + p.outln(" " .. cxx .. " $CXXFLAGS" .. " /nologo /showIncludes -c /Tp$in /Fo$out") + p.outln(" description = cxx $out") + p.outln(" deps = msvc") + p.outln("") + p.outln("RESFLAGS = " .. all_resflags) + p.outln("rule rc") + p.outln(" command = " .. rc .. " /nologo /fo$out $in $RESFLAGS") + p.outln(" description = rc $out") + p.outln("") + if cfg.kind == p.STATICLIB then + p.outln("rule ar") + p.outln(" command = " .. ar .. " $in /nologo -OUT:$out") + p.outln(" description = ar $out") + p.outln("") + else + p.outln("rule link") + p.outln(" command = " .. link .. " $in" .. ninja.list(ninja.shesc(toolset.getlinks(cfg, true))) .. " /link" .. all_ldflags .. " /nologo /out:$out") + p.outln(" description = link $out") + p.outln("") + end + elseif toolset == p.tools.clang or toolset == p.tools.gcc or toolset == p.tools.emcc then + local force_include_pch = "" + if pch then + force_include_pch = " -include " .. ninja.shesc(pch.placeholder) + p.outln("rule build_pch") + p.outln(" command = " .. iif(cfg.language == "C", cc .. all_cflags .. " -x c-header", cxx .. all_cxxflags .. " -x c++-header") .. " -H -MF $out.d -c -o $out $in") + p.outln(" description = build_pch $out") + p.outln(" depfile = $out.d") + p.outln(" deps = gcc") + end + p.outln("CFLAGS=" .. all_cflags) + p.outln("rule cc") + p.outln(" command = " .. cc .. " $CFLAGS" .. force_include_pch .. " -x c -MF $out.d -c -o $out $in") + p.outln(" description = cc $out") + p.outln(" depfile = $out.d") + p.outln(" deps = gcc") + p.outln("") + p.outln("CXXFLAGS=" .. all_cxxflags) + p.outln("rule cxx") + p.outln(" command = " .. cxx .. " $CXXFLAGS" .. force_include_pch .. " -x c++ -MF $out.d -c -o $out $in") + p.outln(" description = cxx $out") + p.outln(" depfile = $out.d") + p.outln(" deps = gcc") + p.outln("") + p.outln("CFLAGS=" .. all_cflags) + p.outln("rule clangtidy_cc") + p.outln(" command = clang-tidy $in -- -x c $CFLAGS" .. force_include_pch .. " &&$") + p.outln(" " .. cc .. " $CFLAGS" .. force_include_pch .. " -x c -MF $out.d -c -o $out $in") + p.outln(" description = cc $out") + p.outln(" depfile = $out.d") + p.outln(" deps = gcc") + p.outln("") + p.outln("CXXFLAGS=" .. all_cxxflags) + p.outln("rule clangtidy_cxx") + p.outln(" command = clang-tidy $in -- -x c++ $CFLAGS" .. force_include_pch .. " &&$") + p.outln(" " .. cxx .. " $CXXFLAGS" .. force_include_pch .. " -x c++ -MF $out.d -c -o $out $in") + p.outln(" description = cxx $out") + p.outln(" depfile = $out.d") + p.outln(" deps = gcc") + p.outln("") + p.outln("RESFLAGS = " .. all_resflags) + + if rc then + p.outln("rule rc") + p.outln(" command = " .. rc .. " -i $in -o $out $RESFLAGS") + p.outln(" description = rc $out") + p.outln("") + end + + if ar and cfg.kind == p.STATICLIB then + p.outln("rule ar") + p.outln(" command = " .. ar .. " rcs $out $in") + p.outln(" description = ar $out") + p.outln("") + else + local groups = iif(cfg.linkgroups == premake.ON, {"-Wl,--start-group ", " -Wl,--end-group"}, {"", ""}) + p.outln("rule link") + p.outln(" command = " .. link .. " -o $out " .. groups[1] .. "$in" .. ninja.list(ninja.shesc(toolset.getlinks(cfg, true, true))) .. all_ldflags .. groups[2]) + p.outln(" description = link $out") + p.outln("") + end + end + + p.tools.getrelative = getrelative +end + +local function custom_command_rule() + p.outln("rule custom_command") + p.outln(" command = $CUSTOM_COMMAND") + p.outln(" description = $CUSTOM_DESCRIPTION") + p.outln("") +end + +local function copy_rule() + p.outln("rule copy") + p.outln(" command = " .. os.translateCommands("{COPYFILE} $in $out")) + p.outln(" description = copy $in $out") + p.outln("") +end + +local function collect_generated_files(prj, cfg) + local generated_files = {} + tree.traverse(project.getsourcetree(prj), { + onleaf = function(node, depth) + function append_to_generated_files(filecfg) + local outputs = project.getrelative(prj.workspace, filecfg.buildoutputs) + generated_files = table.join(generated_files, outputs) + end + local filecfg = fileconfig.getconfig(node, cfg) + if not filecfg or filecfg.flags.ExcludeFromBuild then + return + end + local rule = p.global.getRuleForFile(node.name, prj.rules) + if fileconfig.hasCustomBuildRule(filecfg) then + append_to_generated_files(filecfg) + elseif rule then + local environ = table.shallowcopy(filecfg.environ) + + if rule.propertydefinition then + p.rule.prepareEnvironment(rule, environ, cfg) + p.rule.prepareEnvironment(rule, environ, filecfg) + end + local rulecfg = p.context.extent(rule, environ) + append_to_generated_files(rulecfg) + end + end, + }, false, 1) + return generated_files +end + +local function pch_build(cfg, pch) + local pch_dependency = {} + if pch then + pch_dependency = { pch.gch } + ninja.add_build(cfg, pch.gch, {}, "build_pch", {pch.input}, {}, {}, {}) + end + return pch_dependency +end + +local function custom_command_build(prj, cfg, filecfg, filename, file_dependencies) + local outputs = project.getrelative(prj.workspace, filecfg.buildoutputs) + local output = outputs[1] + table.remove(outputs, 1) + local commands = {} + if filecfg.buildmessage then + commands = {os.translateCommandsAndPaths("{ECHO} " .. filecfg.buildmessage, prj.workspace.basedir, prj.workspace.location)} + end + commands = table.join(commands, os.translateCommandsAndPaths(filecfg.buildcommands, prj.workspace.basedir, prj.workspace.location)) + if (#commands > 1) then + commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) + else + commands = commands[1] + end + + ninja.add_build(cfg, output, outputs, "custom_command", {filename}, project.getrelative(prj.workspace, filecfg.buildinputs), file_dependencies, + {"CUSTOM_COMMAND = " .. commands, "CUSTOM_DESCRIPTION = custom build " .. ninja.shesc(output)}) +end + +local function compile_file_build(cfg, filecfg, toolset, pch_dependency, regular_file_dependencies, objfiles, extrafiles) + local obj_dir = project.getrelative(cfg.workspace, cfg.objdir) + local filepath = project.getrelative(cfg.workspace, filecfg.abspath) + local has_custom_settings = fileconfig.hasFileSettings(filecfg) + local use_clangtidy = filecfg.clangtidy or (filecfg.clangtidy == nil and cfg.clangtidy) + + if filecfg.buildaction == "None" then + return + elseif filecfg.buildaction == "Copy" then + local target = project.getrelative(cfg.workspace, path.join(cfg.targetdir, filecfg.name)) + ninja.add_build(cfg, target, {}, "copy", {filepath}, {}, {}, {}) + extrafiles[#extrafiles + 1] = target + elseif shouldcompileasc(filecfg) then + local objfilename = obj_dir .. "/" .. filecfg.objname .. (toolset.objectextension or ".o") + objfiles[#objfiles + 1] = objfilename + local cflags = {} + if has_custom_settings then + cflags = {"CFLAGS = $CFLAGS " .. getcflags(toolset, cfg, filecfg)} + end + ninja.add_build(cfg, objfilename, {}, iif(use_clangtidy, "clangtidy_cc", "cc"), {filepath}, pch_dependency, regular_file_dependencies, cflags) + elseif shouldcompileascpp(filecfg) then + local objfilename = obj_dir .. "/" .. filecfg.objname .. (toolset.objectextension or ".o") + objfiles[#objfiles + 1] = objfilename + local cxxflags = {} + if has_custom_settings then + cxxflags = {"CXXFLAGS = $CXXFLAGS " .. getcxxflags(toolset, cfg, filecfg)} + end + ninja.add_build(cfg, objfilename, {}, iif(use_clangtidy, "clangtidy_cxx", "cxx"), {filepath}, pch_dependency, regular_file_dependencies, cxxflags) + elseif path.isresourcefile(filecfg.abspath) then + local objfilename = obj_dir .. "/" .. filecfg.basename .. ".res" + objfiles[#objfiles + 1] = objfilename + local resflags = {} + if has_custom_settings then + resflags = {"RESFLAGS = $RESFLAGS " .. getresflags(toolset, cfg, filecfg)} + end + local rc = toolset.gettoolname(cfg, "rc") + if rc then + ninja.add_build(cfg, objfilename, {}, "rc", {filepath}, {}, {}, resflags) + else + p.warnOnce(filepath, string.format("Ignored resource: '%s'", filepath)) + end + end +end + +local function files_build(prj, cfg, toolset, pch_dependency, regular_file_dependencies, file_dependencies) + local objfiles = {} + local extrafiles = {} + tree.traverse(project.getsourcetree(prj), { + onleaf = function(node, depth) + local filecfg = fileconfig.getconfig(node, cfg) + if not filecfg or filecfg.flags.ExcludeFromBuild then + return + end + local rule = p.global.getRuleForFile(node.name, prj.rules) + local filepath = project.getrelative(cfg.workspace, node.abspath) + + if fileconfig.hasCustomBuildRule(filecfg) then + custom_command_build(prj, cfg, filecfg, filepath, file_dependencies) + elseif rule then + local environ = table.shallowcopy(filecfg.environ) + + if rule.propertydefinition then + p.rule.prepareEnvironment(rule, environ, cfg) + p.rule.prepareEnvironment(rule, environ, filecfg) + end + local rulecfg = p.context.extent(rule, environ) + custom_command_build(prj, cfg, rulecfg, filepath, file_dependencies) + else + compile_file_build(cfg, filecfg, toolset, pch_dependency, regular_file_dependencies, objfiles, extrafiles) + end + end, + }, false, 1) + p.outln("") + + return objfiles, extrafiles +end + +local function generated_files_build(cfg, generated_files, key) + local final_dependency = {} + if #generated_files > 0 then + p.outln("# generated files") + ninja.add_build(cfg, "generated_files_" .. key, {}, "phony", generated_files, {}, {}, {}) + final_dependency = {"generated_files_" .. key} + end + return final_dependency +end + +-- generate project + config build file +function ninja.generateProjectCfg(cfg) + local oldGetDefaultSeparator = path.getDefaultSeparator + path.getDefaultSeparator = function() return "/" end + + local prj = cfg.project + local key = get_key(cfg) + local toolset, toolset_version = p.tools.canonical(cfg.toolset) + + if not toolset then + p.error("Unknown toolset " .. cfg.toolset) + end + + -- Some toolset fixes + cfg.gccprefix = cfg.gccprefix or "" + + p.outln("# project build file") + p.outln("# generated with premake ninja") + p.outln("") + + -- premake-ninja relies on scoped rules + -- and they were added in ninja v1.6 + p.outln("ninja_required_version = 1.6") + p.outln("") + + local is_c_or_cpp = cfg.language == p.C or cfg.language == p.CPP; + + ---------------------------------------------------- figure out settings + local pch = nil + if is_c_or_cpp then + if toolset ~= p.tools.msc then + pch = p.tools.gcc.getpch(cfg) + if pch then + pch = { + input = pch, + placeholder = project.getrelative(cfg.workspace, path.join(cfg.objdir, path.getname(pch))), + gch = project.getrelative(cfg.workspace, path.join(cfg.objdir, path.getname(pch) .. ".gch")) + } + end + end + end + + ---------------------------------------------------- write rules + p.outln("# core rules for " .. cfg.name) + prebuild_rule(cfg) + prelink_rule(cfg) + postbuild_rule(cfg) + + if is_c_or_cpp then + c_cpp_compilation_rules(cfg, toolset, pch) + else + local handler = ninja.handlers[cfg.language] + if not handler then + p.error("expected registered ninja handler action for target " .. cfg.language) + end + handler.compilation_rules(cfg, toolset) + end + + copy_rule() + custom_command_rule() + + ---------------------------------------------------- build all files + p.outln("# build files") + + local pch_dependency = is_c_or_cpp and pch_build(cfg, pch) or {} + + local generated_files = collect_generated_files(prj, cfg) + + local file_dependencies = getFileDependencies(cfg) + local regular_file_dependencies = table.join(iif(#generated_files > 0, {"generated_files_" .. key}, {}), file_dependencies) + + local obj_dir = project.getrelative(cfg.workspace, cfg.objdir) + local objfiles, extrafiles = files_build(prj, cfg, toolset, pch_dependency, regular_file_dependencies, file_dependencies) + local final_dependency = generated_files_build(cfg, generated_files, key) + + ---------------------------------------------------- build final target + if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then + p.outln("# prebuild") + ninja.add_build(cfg, "prebuild_" .. get_key(cfg), {}, "run_prebuild", {}, {}, {}, {}) + end + local prelink_dependency = {} + if #cfg.prelinkcommands > 0 or cfg.prelinkmessage then + p.outln("# prelink") + ninja.add_build(cfg, "prelink_" .. get_key(cfg), {}, "run_prelink", {}, objfiles, final_dependency, {}) + prelink_dependency = { "prelink_" .. get_key(cfg) } + end + if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then + p.outln("# postbuild") + ninja.add_build(cfg, "postbuild_" .. get_key(cfg), {}, "run_postbuild", {}, {ninja.outputFilename(cfg)}, {}, {}) + end + + if is_c_or_cpp then + -- we don't pass getlinks(cfg) through dependencies + -- because system libraries are often not in PATH so ninja can't find them + local libs = table.translate(config.getlinks(cfg, "siblings", "fullpath"), + function (p) return project.getrelative(cfg.workspace, path.join(cfg.project.location, p)) end) + local cfg_output = ninja.outputFilename(cfg) + local extra_outputs = {} + local command_rule = "" + if cfg.kind == p.STATICLIB then + p.outln("# link static lib") + command_rule = "ar" + elseif cfg.kind == p.SHAREDLIB then + p.outln("# link shared lib") + command_rule = "link" + extra_outputs = iif(os.target() == "windows", {path.replaceextension(cfg_output, ".lib"), path.replaceextension(cfg_output, ".exp")}, {}) + elseif (cfg.kind == p.CONSOLEAPP) or (cfg.kind == p.WINDOWEDAPP) then + p.outln("# link executable") + command_rule = "link" + else + p.error("ninja action doesn't support this kind of target " .. cfg.kind) + end + + local deps = table.join(final_dependency, extrafiles, prelink_dependency) + ninja.add_build(cfg, cfg_output, extra_outputs, command_rule, table.join(objfiles, libs), {}, deps, {}) + outputs = {cfg_output} + else + local handler = ninja.handlers[cfg.language] + if not handler then + p.error("expected registered ninja handler action for target " .. cfg.language) + end + outputs = handler.target_rules(cfg, toolset) + end + + p.outln("") + if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then + ninja.add_build(cfg, key, {}, "phony", {"postbuild_" .. get_key(cfg)}, {}, {}, {}) + else + ninja.add_build(cfg, key, {}, "phony", outputs, {}, {}, {}) + end + p.outln("") + + path.getDefaultSeparator = oldGetDefaultSeparator +end + +-- return name of output binary relative to build folder +function ninja.outputFilename(cfg) + return project.getrelative(cfg.workspace, cfg.buildtarget.directory) .. "/" .. cfg.buildtarget.name +end + +-- return name of build file for configuration +function ninja.projectCfgFilename(cfg, relative) + if relative ~= nil then + relative = project.getrelative(cfg.workspace, cfg.location) .. "/" + else + relative = "" + end + return relative .. get_key(cfg, cfg.project.filename) .. ".ninja" +end + +-- check if string starts with string +function ninja.startsWith(str, starts) + return str:sub(0, starts:len()) == starts +end + +-- check if string ends with string +function ninja.endsWith(str, ends) + return str:sub(-ends:len()) == ends +end + +-- generate all build files for every project configuration +function ninja.generateProject(prj) + if not ninja.can_generate(prj) then + return + end + for cfg in project.eachconfig(prj) do + p.generate(cfg, ninja.projectCfgFilename(cfg), ninja.generateProjectCfg) + end +end + +include("_preload.lua") + +return ninja diff --git a/vendor/premake5/ninja/tests/console_app/includepath/main.cpp b/vendor/premake5/ninja/tests/console_app/includepath/main.cpp new file mode 100644 index 0000000..7e050fa --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/includepath/main.cpp @@ -0,0 +1,11 @@ +#include +#include "test1.h" +#include "test2.h" + +int main() +{ + printf("hello world !\n"); + test1(); + test2(); + return 0; +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/includepath/premake5.lua b/vendor/premake5/ninja/tests/console_app/includepath/premake5.lua new file mode 100644 index 0000000..da58659 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/includepath/premake5.lua @@ -0,0 +1,22 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj" + kind "ConsoleApp" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"**.cpp", "**.c", "**.h"} + includedirs {"test1", "test2"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/console_app/includepath/test1/test1.c b/vendor/premake5/ninja/tests/console_app/includepath/test1/test1.c new file mode 100644 index 0000000..cb8dc1b --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/includepath/test1/test1.c @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/includepath/test1/test1.h b/vendor/premake5/ninja/tests/console_app/includepath/test1/test1.h new file mode 100644 index 0000000..8e3f361 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/includepath/test1/test1.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test1(); + +#ifdef __cplusplus +} +#endif diff --git a/vendor/premake5/ninja/tests/console_app/includepath/test2/test2.cpp b/vendor/premake5/ninja/tests/console_app/includepath/test2/test2.cpp new file mode 100644 index 0000000..56ba9c9 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/includepath/test2/test2.cpp @@ -0,0 +1,7 @@ +#include "test2.h" +#include + +void test2() +{ + printf("hello from test2 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/includepath/test2/test2.h b/vendor/premake5/ninja/tests/console_app/includepath/test2/test2.h new file mode 100644 index 0000000..f43be8f --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/includepath/test2/test2.h @@ -0,0 +1,3 @@ +#pragma once + +void test2(); \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/simple/main.cpp b/vendor/premake5/ninja/tests/console_app/simple/main.cpp new file mode 100644 index 0000000..8664e36 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/main.cpp @@ -0,0 +1,13 @@ +#include +#include "test1.h" +#include "test2.h" +#include "test 3.h" + +int main() +{ + printf("hello world !\n"); + test1(); + test2(); + test3(); + return 0; +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/simple/premake5.lua b/vendor/premake5/ninja/tests/console_app/simple/premake5.lua new file mode 100644 index 0000000..f2c6edb --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/premake5.lua @@ -0,0 +1,21 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj" + kind "ConsoleApp" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"**.cpp", "**.c", "**.h"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/console_app/simple/test 3.c b/vendor/premake5/ninja/tests/console_app/simple/test 3.c new file mode 100644 index 0000000..f59b780 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/test 3.c @@ -0,0 +1,7 @@ +#include "test 3.h" +#include + +void test3() +{ + printf("hello from test3 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/simple/test 3.h b/vendor/premake5/ninja/tests/console_app/simple/test 3.h new file mode 100644 index 0000000..65794a7 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/test 3.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test3(); + +#ifdef __cplusplus +} +#endif diff --git a/vendor/premake5/ninja/tests/console_app/simple/test1.c b/vendor/premake5/ninja/tests/console_app/simple/test1.c new file mode 100644 index 0000000..cb8dc1b --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/test1.c @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/simple/test1.h b/vendor/premake5/ninja/tests/console_app/simple/test1.h new file mode 100644 index 0000000..8e3f361 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/test1.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test1(); + +#ifdef __cplusplus +} +#endif diff --git a/vendor/premake5/ninja/tests/console_app/simple/test2.cpp b/vendor/premake5/ninja/tests/console_app/simple/test2.cpp new file mode 100644 index 0000000..56ba9c9 --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/test2.cpp @@ -0,0 +1,7 @@ +#include "test2.h" +#include + +void test2() +{ + printf("hello from test2 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/console_app/simple/test2.h b/vendor/premake5/ninja/tests/console_app/simple/test2.h new file mode 100644 index 0000000..f43be8f --- /dev/null +++ b/vendor/premake5/ninja/tests/console_app/simple/test2.h @@ -0,0 +1,3 @@ +#pragma once + +void test2(); \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/run_tests.py b/vendor/premake5/ninja/tests/run_tests.py new file mode 100644 index 0000000..47ef726 --- /dev/null +++ b/vendor/premake5/ninja/tests/run_tests.py @@ -0,0 +1,270 @@ +# unittests for premake-ninja + +import os +import sys +import time +import shutil +import platform +import unittest +import subprocess + +# we are changing working directory often in this tests, so let's save current one +current_cwd = os.getcwd() + +# if set, will override compiler name when premake is executed +override_compiler = None + +# finds the file in path +def which(cmd, mode = os.F_OK | os.X_OK, path = None): + if sys.version_info[0:2] >= (3, 3): + return shutil.which(cmd, mode, path) + else: + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + if not os.curdir in path: + path.insert(0, os.curdir) + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None + +# ----------------------------------------------------- helper class +class Helper(unittest.TestCase): + # removes build directory in test folder + def clear(self, build_dir): + if os.path.exists(build_dir): + shutil.rmtree(build_dir) + + # enters test, and clears it + def enter_test(self, test, build_dir = "build"): + self.build_dir = build_dir + os.chdir(current_cwd) # if previous test failed then we need to restore cwd + os.chdir(test) + self.clear(build_dir) + + # clears test and exit from it + def exit_test(self, build_dir = "build"): + # for some reason call/check_call are not waiting for executable to completely finish + # so let's wait a bit so we can remove folder safely + time.sleep(0.3) + self.clear(build_dir) + os.chdir(current_cwd) + + # call premake in the test + def premake(self): + if override_compiler: + args = ["premake5", "--scripts=../../..", "--cc=" + override_compiler, "ninja"] + if override_compiler == "emcc": + args += ["--os=emscripten"] + self.assertEqual(subprocess.call(args), 0, "looks like premake failed") + else: + self.assertEqual(subprocess.call(["premake5", "--scripts=../../..", "ninja"]), 0, "looks like premake failed") + + # call ninja in the test + def ninja(self, target = None): + args = ["ninja", "-C", "build"] + if target is not None: + args.append(target) + self.assertEqual(subprocess.call(args), 0, "looks like ninja failed") + + # get out name with ext and prefix + def out_name(self, path, ext = None, prefix = None): + if (ext == None) and (prefix == None): + return path + base_path = os.path.dirname(path) + base_name_and_ext = os.path.splitext(os.path.basename(path)) + if prefix == None: + prefix = "" + if ext == None: + ext = base_name_and_ext[1] + return base_path + "/" + prefix + base_name_and_ext[0] + ext + + # check if executable exist + def out_exist(self, path): + print(f"Looking for {path} in {os.listdir(os.path.dirname(path))}") + sys.stdout.flush() + self.assertTrue( + os.path.exists(path) or + os.path.exists(self.out_name(path, ".exe")) or + os.path.exists(self.out_name(path, ".app")) or + os.path.exists(self.out_name(path, ".lib")) or + os.path.exists(self.out_name(path, ".a", "lib")) or + os.path.exists(self.out_name(path, ".dll")) or + os.path.exists(self.out_name(path, ".so", "lib")) or + os.path.exists(self.out_name(path, ".dylib", "lib")) or + os.path.exists(self.out_name(path, ".wasm")) + ) + print(f"Found {path}") + sys.stdout.flush() + # check if executable doesn't exist + def out_not_exist(self, path): + self.assertFalse( + os.path.exists(path) or + os.path.exists(self.out_name(path, ".exe")) or + os.path.exists(self.out_name(path, ".app")) or + os.path.exists(self.out_name(path, ".lib")) or + os.path.exists(self.out_name(path, ".a", "lib")) or + os.path.exists(self.out_name(path, ".dll")) or + os.path.exists(self.out_name(path, ".so", "lib")) or + os.path.exists(self.out_name(path, ".dylib", "lib")) or + os.path.exists(self.out_name(path, ".wasm")) + ) + + # check if executable exist + def exe(self, path): + if os.path.exists(path): + current_cwd = os.getcwd() + os.chdir(self.build_dir) + executable = os.path.relpath(path, self.build_dir) + subprocess.check_call([executable], env={'LD_LIBRARY_PATH': os.path.dirname(executable), 'DYLD_LIBRARY_PATH': os.path.dirname(executable)}) + os.chdir(current_cwd) + elif os.path.exists(path + ".exe"): + subprocess.check_call([path + ".exe"]) + elif os.path.exists(path + ".app"): + subprocess.check_call([path + ".app"]) + elif os.path.exists(self.out_name(path, ".lib")) or os.path.exists(self.out_name(path, ".a", "lib")) or os.path.exists(self.out_name(path, ".dll")) or os.path.exists(self.out_name(path, ".so", "lib")) or os.path.exists(self.out_name(path, ".dylib", "lib")): + pass + else: + self.assertTrue(False, "executable '" + path + "' doesn't exist") + + # check basic flow, run debug and release executables + def check_basics(self, out_debug, out_release, build_dir = "build"): + # build dir should not exist before premake is called + self.assertFalse(os.path.exists(build_dir)) + + # call premake + # build dir should exist afterwards, but executables shouldn't + self.premake() + self.assertTrue(os.path.exists(build_dir)) + self.out_not_exist(out_debug) + self.out_not_exist(out_release) + + # call ninja, by default ninja should build debug target + # so debug executable should exist, and release shouldn't + self.ninja() + self.out_exist(out_debug) + self.out_not_exist(out_release) + + # let's build debug target explicitly, and still release executable shouldn't exist + self.ninja("debug") + self.out_exist(out_debug) + self.out_not_exist(out_release) + + # let's build release target explicitly, all basic executables should exist now + self.ninja("release") + self.out_exist(out_debug) + self.out_exist(out_release) + + # run executables to check if they are valid + if override_compiler != "emcc": + self.exe(out_debug) + self.exe(out_release) + +# ----------------------------------------------------- console app tests +class TestConsoleApp(Helper): + # test simple app + def test_simple(self): + self.enter_test("console_app/simple") + self.check_basics("build/bin_debug/ninjatestprj", "build/bin_release/ninjatestprj") + self.exit_test() + + # test include path app + def test_include_path(self): + self.enter_test("console_app/includepath") + self.check_basics("build/bin_debug/ninjatestprj", "build/bin_release/ninjatestprj") + self.exit_test() + +# ----------------------------------------------------- static lib tests +class TestStaticLib(Helper): + # test simple app + def test_simple(self): + self.enter_test("static_lib/simple") + self.check_basics("build/bin_debug/ninjatestprj", "build/bin_release/ninjatestprj") + self.exit_test() + + # test static lib with app + def test_withapp(self): + self.enter_test("static_lib/withapp") + self.check_basics("build/bin_debug/ninjatestprj_app", "build/bin_release/ninjatestprj_app") + self.out_exist("build/bin_debug/ninjatestprj_lib test1") + self.out_exist("build/bin_release/ninjatestprj_lib test1") + self.out_exist("build/bin_debug/ninjatestprj_lib_test2") + self.out_exist("build/bin_release/ninjatestprj_lib_test2") + self.exit_test() + +# ----------------------------------------------------- shared lib tests +class TestSharedLib(Helper): + # test simple app + def test_simple(self): + # Skip shared library tests on Emscripten since this is an advanced feature not supported by Premake yet. + if override_compiler == "emcc": + return + self.enter_test("shared_lib/simple") + self.check_basics("build/bin_debug/ninjatestprj", "build/bin_release/ninjatestprj") + self.exit_test() + + # test shared lib with app + def test_withapp(self): + # Skip shared library tests on Emscripten since this is an advanced feature not supported by Premake yet. + if override_compiler == "emcc": + return + self.enter_test("shared_lib/withapp") + self.check_basics("build/bin_debug/ninjatestprj_app", "build/bin_release/ninjatestprj_app") + self.out_exist("build/bin_debug/ninjatestprj_lib_test1") + self.out_exist("build/bin_release/ninjatestprj_lib_test1") + self.out_exist("build/bin_debug/ninjatestprj_lib_test2") + self.out_exist("build/bin_release/ninjatestprj_lib_test2") + self.exit_test() + +# ----------------------------------------------------- windowed app tests +class TestWindowedApp(Helper): + # test simple app + def test_simple(self): + self.enter_test("windowed_app/simple") + self.check_basics("build/bin_debug/ninjatestprj", "build/bin_release/ninjatestprj") + self.exit_test() + +# ----------------------------------------------------- entry point +if __name__ == "__main__": + print("-------------------------- test default setup") + r = unittest.main(exit = False) + if not r.result.wasSuccessful(): + sys.exit(1) + + if platform.system() == "Windows" and which("gcc"): + print("-------------------------- found gcc on windows") + override_compiler = "gcc" + unittest.main() + + if which("emcc"): + print("-------------------------- found emcc") + override_compiler = "emcc" + unittest.main() diff --git a/vendor/premake5/ninja/tests/shared_lib/simple/premake5.lua b/vendor/premake5/ninja/tests/shared_lib/simple/premake5.lua new file mode 100644 index 0000000..e4e91c6 --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/simple/premake5.lua @@ -0,0 +1,22 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj" + kind "SharedLib" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"**.cpp", "**.c", "**.h"} + defines {"DLL_EXPORT"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/shared_lib/simple/test1.cpp b/vendor/premake5/ninja/tests/shared_lib/simple/test1.cpp new file mode 100644 index 0000000..69c0200 --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/simple/test1.cpp @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +TESTLIB void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/shared_lib/simple/test1.h b/vendor/premake5/ninja/tests/shared_lib/simple/test1.h new file mode 100644 index 0000000..913e032 --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/simple/test1.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef _WIN32 + #ifdef DLL_EXPORT + #define TESTLIB __declspec(dllexport) + #else + #define TESTLIB __declspec(dllimport) + #endif +#else + #define TESTLIB +#endif + +TESTLIB void test1(); diff --git a/vendor/premake5/ninja/tests/shared_lib/withapp/main.cpp b/vendor/premake5/ninja/tests/shared_lib/withapp/main.cpp new file mode 100644 index 0000000..7e050fa --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/withapp/main.cpp @@ -0,0 +1,11 @@ +#include +#include "test1.h" +#include "test2.h" + +int main() +{ + printf("hello world !\n"); + test1(); + test2(); + return 0; +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/shared_lib/withapp/premake5.lua b/vendor/premake5/ninja/tests/shared_lib/withapp/premake5.lua new file mode 100644 index 0000000..507802c --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/withapp/premake5.lua @@ -0,0 +1,59 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj_app" + kind "ConsoleApp" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"main.cpp"} + includedirs {"test1", "test2"} + links {"ninjatestprj_lib_test1", "ninjatestprj_lib_test2"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" + +project "ninjatestprj_lib_test1" + kind "SharedLib" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"test1/**.cpp", "test1/**.c", "test1/**.h"} + includedirs {"test1"} + defines {"DLL_EXPORT"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" + +project "ninjatestprj_lib_test2" + kind "SharedLib" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"test2/**.cpp", "test2/**.c", "test2/**.h"} + includedirs {"test2"} + defines {"DLL_EXPORT2"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.cpp b/vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.cpp new file mode 100644 index 0000000..69c0200 --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.cpp @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +TESTLIB void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.h b/vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.h new file mode 100644 index 0000000..913e032 --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/withapp/test1/test1.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef _WIN32 + #ifdef DLL_EXPORT + #define TESTLIB __declspec(dllexport) + #else + #define TESTLIB __declspec(dllimport) + #endif +#else + #define TESTLIB +#endif + +TESTLIB void test1(); diff --git a/vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.cpp b/vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.cpp new file mode 100644 index 0000000..edb7a6c --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.cpp @@ -0,0 +1,7 @@ +#include "test2.h" +#include + +TESTLIB2 void test2() +{ + printf("hello from test2 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.h b/vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.h new file mode 100644 index 0000000..af7340f --- /dev/null +++ b/vendor/premake5/ninja/tests/shared_lib/withapp/test2/test2.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef _WIN32 + #ifdef DLL_EXPORT2 + #define TESTLIB2 __declspec(dllexport) + #else + #define TESTLIB2 __declspec(dllimport) + #endif +#else + #define TESTLIB2 +#endif + +TESTLIB2 void test2(); \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/static_lib/simple/premake5.lua b/vendor/premake5/ninja/tests/static_lib/simple/premake5.lua new file mode 100644 index 0000000..32d66d2 --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/simple/premake5.lua @@ -0,0 +1,21 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj" + kind "StaticLib" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"**.cpp", "**.c", "**.h"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/static_lib/simple/test1.c b/vendor/premake5/ninja/tests/static_lib/simple/test1.c new file mode 100644 index 0000000..cb8dc1b --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/simple/test1.c @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/static_lib/simple/test1.h b/vendor/premake5/ninja/tests/static_lib/simple/test1.h new file mode 100644 index 0000000..8e3f361 --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/simple/test1.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test1(); + +#ifdef __cplusplus +} +#endif diff --git a/vendor/premake5/ninja/tests/static_lib/withapp/main.cpp b/vendor/premake5/ninja/tests/static_lib/withapp/main.cpp new file mode 100644 index 0000000..7e050fa --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/withapp/main.cpp @@ -0,0 +1,11 @@ +#include +#include "test1.h" +#include "test2.h" + +int main() +{ + printf("hello world !\n"); + test1(); + test2(); + return 0; +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/static_lib/withapp/premake5.lua b/vendor/premake5/ninja/tests/static_lib/withapp/premake5.lua new file mode 100644 index 0000000..df4fe4a --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/withapp/premake5.lua @@ -0,0 +1,64 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj_app" + kind "ConsoleApp" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"main.cpp"} + includedirs {"test1", "test2"} + links {"ninjatestprj_lib test1", "ninjatestprj_lib_test2"} + + filter {"system:windows"} + links { "user32", "gdi32" } + + filter {"system:linux"} + links { "pthread" } + -- todo add system libs for os x and linux + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" + +project "ninjatestprj_lib test1" + kind "StaticLib" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"test1/**.cpp", "test1/**.c", "test1/**.h"} + includedirs {"test1"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" + +project "ninjatestprj_lib_test2" + kind "StaticLib" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"test2/**.cpp", "test2/**.c", "test2/**.h"} + includedirs {"test2"} + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.c b/vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.c new file mode 100644 index 0000000..cb8dc1b --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.c @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.h b/vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.h new file mode 100644 index 0000000..8e3f361 --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/withapp/test1/test1.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test1(); + +#ifdef __cplusplus +} +#endif diff --git a/vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.cpp b/vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.cpp new file mode 100644 index 0000000..56ba9c9 --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.cpp @@ -0,0 +1,7 @@ +#include "test2.h" +#include + +void test2() +{ + printf("hello from test2 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.h b/vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.h new file mode 100644 index 0000000..f43be8f --- /dev/null +++ b/vendor/premake5/ninja/tests/static_lib/withapp/test2/test2.h @@ -0,0 +1,3 @@ +#pragma once + +void test2(); \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/windowed_app/simple/main.cpp b/vendor/premake5/ninja/tests/windowed_app/simple/main.cpp new file mode 100644 index 0000000..ddcfdcf --- /dev/null +++ b/vendor/premake5/ninja/tests/windowed_app/simple/main.cpp @@ -0,0 +1,16 @@ +#include +#include "test1.h" +#include "test2.h" + +#ifdef _WIN32 +#include +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) +#else +int main() +#endif +{ + printf("hello world !\n"); + test1(); + test2(); + return 0; +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/windowed_app/simple/premake5.lua b/vendor/premake5/ninja/tests/windowed_app/simple/premake5.lua new file mode 100644 index 0000000..7af6497 --- /dev/null +++ b/vendor/premake5/ninja/tests/windowed_app/simple/premake5.lua @@ -0,0 +1,24 @@ +require "ninja" + +solution "ninjatestsln" + location "build" + configurations {"debug", "release"} + +project "ninjatestprj" + kind "WindowedApp" + location "build" + language "C++" + targetdir "build/bin_%{cfg.buildcfg}" + + files {"**.cpp", "**.c", "**.h"} + + filter "system:windows" + entrypoint "WinMainCRTStartup" + + filter "configurations:debug" + defines {"DEBUG"} + symbols "On" + + filter "configurations:release" + defines {"NDEBUG"} + optimize "On" diff --git a/vendor/premake5/ninja/tests/windowed_app/simple/test1.c b/vendor/premake5/ninja/tests/windowed_app/simple/test1.c new file mode 100644 index 0000000..cb8dc1b --- /dev/null +++ b/vendor/premake5/ninja/tests/windowed_app/simple/test1.c @@ -0,0 +1,7 @@ +#include "test1.h" +#include + +void test1() +{ + printf("hello from test1 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/windowed_app/simple/test1.h b/vendor/premake5/ninja/tests/windowed_app/simple/test1.h new file mode 100644 index 0000000..8e3f361 --- /dev/null +++ b/vendor/premake5/ninja/tests/windowed_app/simple/test1.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test1(); + +#ifdef __cplusplus +} +#endif diff --git a/vendor/premake5/ninja/tests/windowed_app/simple/test2.cpp b/vendor/premake5/ninja/tests/windowed_app/simple/test2.cpp new file mode 100644 index 0000000..56ba9c9 --- /dev/null +++ b/vendor/premake5/ninja/tests/windowed_app/simple/test2.cpp @@ -0,0 +1,7 @@ +#include "test2.h" +#include + +void test2() +{ + printf("hello from test2 !\n"); +} \ No newline at end of file diff --git a/vendor/premake5/ninja/tests/windowed_app/simple/test2.h b/vendor/premake5/ninja/tests/windowed_app/simple/test2.h new file mode 100644 index 0000000..f43be8f --- /dev/null +++ b/vendor/premake5/ninja/tests/windowed_app/simple/test2.h @@ -0,0 +1,3 @@ +#pragma once + +void test2(); \ No newline at end of file