Browse Source

Merge pull request #636 from Faless/build/tools_pr

Android/iOS build, Scons boilerplate for building projects.
Fabio Alessandrelli 3 years ago
parent
commit
9d5caf6baa
3 changed files with 112 additions and 270 deletions
  1. 71 110
      .github/workflows/ci.yml
  2. 39 14
      SConstruct
  3. 2 146
      test/SConstruct

+ 71 - 110
.github/workflows/ci.yml

@@ -2,9 +2,52 @@ name: Continuous integration
 on: [push, pull_request]
 
 jobs:
-  linux:
-    name: Build (Linux, GCC)
-    runs-on: ubuntu-18.04
+  build:
+    name: ${{ matrix.name }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - name: 🐧 Linux (GCC)
+            os: ubuntu-18.04
+            platform: linux
+            artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
+            artifact-path: bin/libgodot-cpp.linux.release.64.a
+
+          - name: 🏁 Windows (x86_64, MSVC)
+            os: windows-2019
+            platform: windows
+            artifact-name: godot-cpp-windows-msvc2019-x86_64-release
+            artifact-path: bin/libgodot-cpp.windows.release.64.lib
+
+          - name: 🏁 Windows (x86_64, MinGW)
+            os: windows-2019
+            platform: windows
+            artifact-name: godot-cpp-linux-mingw-x86_64-release
+            artifact-path: bin/libgodot-cpp.windows.release.64.a
+            flags: use_mingw=yes
+
+          - name: 🍎 macOS (universal)
+            os: macos-11
+            platform: osx
+            artifact-name: godot-cpp-macos-universal-release
+            artifact-path: bin/libgodot-cpp.osx.release.universal.a
+            flags: macos_arch=universal
+
+          - name: 🤖 Android (arm64)
+            os: ubuntu-18.04
+            platform: android
+            artifact-name: godot-cpp-android-arm64-release
+            artifact-path: bin/libgodot-cpp.android.release.arm64v8.a
+            flags: android_arch=arm64v8
+
+          - name: 🍏 iOS (arm64)
+            os: macos-11
+            platform: ios
+            artifact-name: godot-cpp-ios-arm64-release
+            artifact-path: bin/libgodot-cpp.ios.release.arm64.a
+
     steps:
       - name: Checkout
         uses: actions/checkout@v2
@@ -16,26 +59,44 @@ jobs:
         with:
           python-version: '3.x'
 
-      - name: Install dependencies
+      - name: Linux dependencies
+        if: ${{ matrix.platform == 'linux' }}
         run: |
           sudo apt-get update -qq
           sudo apt-get install -qqq build-essential pkg-config
+
+      - name: Install scons
+        run: |
           python -m pip install scons
 
-      - name: Build godot-cpp
+      - name: Windows GCC dependency
+        if: ${{ matrix.platform == 'windows' }}
+        # Install GCC from Scoop as the default supplied GCC doesn't work ("Error 1").
         run: |
-          scons target=release generate_bindings=yes -j $(nproc)
+          Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
+          scoop install gcc
+          g++ --version
+          gcc --version
 
-      - name: Build test project
+      - name: Build godot-cpp (debug)
+        run: |
+          scons platform=${{ matrix.platform }} target=debug generate_bindings=yes ${{ matrix.flags }} -j2
+
+      - name: Build test without rebuilding godot-cpp (debug)
+        run: |
+          cd test
+          scons platform=${{ matrix.platform }} target=debug ${{ matrix.flags }} build_library=no -j2
+
+      - name: Build test and godot-cpp (release)
         run: |
           cd test
-          scons target=release -j $(nproc)
+          scons platform=${{ matrix.platform }} target=release ${{ matrix.flags }} -j2
 
       - name: Upload artifact
         uses: actions/upload-artifact@v2
         with:
-          name: godot-cpp-linux-glibc2.27-x86_64-release
-          path: bin/libgodot-cpp.linux.release.64.a
+          name: ${{ matrix.artifact-name }}
+          path: ${{ matrix.artifact-path }}
           if-no-files-found: error
 
   linux-cmake:
@@ -86,106 +147,6 @@ jobs:
           cd test && cmake -DCMAKE_BUILD_TYPE=Release -GNinja .
           cmake --build . -j $(nproc)
 
-  windows-msvc:
-    name: Build (Windows, MSVC)
-    runs-on: windows-2019
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v2
-        with:
-          submodules: recursive
-
-      - name: Set up Python (for SCons)
-        uses: actions/setup-python@v2
-        with:
-          python-version: '3.x'
-
-      - name: Install dependencies
-        run: |
-          python -m pip install scons
-
-      - name: Build godot-cpp
-        run: |
-          scons target=release generate_bindings=yes -j $env:NUMBER_OF_PROCESSORS
-
-      - name: Build test project
-        run: |
-          cd test
-          scons target=release -j $env:NUMBER_OF_PROCESSORS
-
-      - name: Upload artifact
-        uses: actions/upload-artifact@v2
-        with:
-          name: godot-cpp-windows-msvc2019-x86_64-release
-          path: bin/libgodot-cpp.windows.release.64.lib
-          if-no-files-found: error
-
-  windows-mingw:
-    name: Build (Windows, MinGW)
-    runs-on: windows-2019
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v2
-        with:
-          submodules: recursive
-
-      - name: Set up Python (for SCons)
-        uses: actions/setup-python@v2
-        with:
-          python-version: '3.x'
-
-      - name: Install dependencies
-        run: |
-          python -m pip install scons
-
-      - name: Build godot-cpp
-        # Install GCC from Scoop as the default supplied GCC doesn't work ("Error 1").
-        run: |
-          Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
-          scoop install gcc
-          g++ --version
-          gcc --version
-          scons target=release generate_bindings=yes use_mingw=yes -j $env:NUMBER_OF_PROCESSORS
-
-      #- name: Build test project (TODO currently not supported, leaving uncommented as a reminder to fix this)
-      #  run: |
-      #    cd test
-      #    scons target=release use_mingw=yes -j $env:NUMBER_OF_PROCESSORS
-
-      - name: Upload artifact
-        uses: actions/upload-artifact@v2
-        with:
-          name: godot-cpp-linux-mingw-x86_64-release
-          path: bin/libgodot-cpp.windows.release.64.a
-          if-no-files-found: error
-
-  macos:
-    name: Build (macOS, Clang, universal / x86_64 + arm64)
-    runs-on: macos-11
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v2
-        with:
-          submodules: recursive
-
-      - name: Set up Python (for SCons)
-        uses: actions/setup-python@v2
-        with:
-          python-version: '3.x'
-
-      - name: Install dependencies
-        run: |
-          python -m pip install scons
-
-      - name: Build godot-cpp
-        run: |
-          scons target=release generate_bindings=yes -j $(sysctl -n hw.logicalcpu)
-
-      - name: Build test project
-        run: |
-          cd test
-          scons target=release -j $(sysctl -n hw.logicalcpu)
-
   static-checks:
     name: Static Checks (clang-format)
     runs-on: ubuntu-20.04

+ 39 - 14
SConstruct

@@ -144,6 +144,9 @@ opts.Add(
 )
 opts.Add(BoolVariable("generate_template_get_node", "Generate a template version of the Node class's get_node.", True))
 
+opts.Add(BoolVariable("build_library", "Build the godot-cpp library.", True))
+opts.Add("build_projects", "List of projects to build (comma-separated list of paths).", "")
+
 opts.Update(env)
 Help(opts.GenerateHelpText(env))
 
@@ -165,6 +168,13 @@ if host_platform == "windows" and env["platform"] != "android":
 
     opts.Update(env)
 
+# Require C++17
+if host_platform == "windows" and env["platform"] == "windows" and not env["use_mingw"]:
+    # MSVC
+    env.Append(CCFLAGS=["/std:c++17"])
+else:
+    env.Append(CCFLAGS=["-std=c++17"])
+
 if env["target"] == "debug":
     env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"])
 
@@ -172,7 +182,7 @@ if env["platform"] == "linux" or env["platform"] == "freebsd":
     if env["use_llvm"]:
         env["CXX"] = "clang++"
 
-    env.Append(CCFLAGS=["-fPIC", "-std=c++17", "-Wwrite-strings"])
+    env.Append(CCFLAGS=["-fPIC", "-Wwrite-strings"])
     env.Append(LINKFLAGS=["-Wl,-R,'$$ORIGIN'"])
 
     if env["target"] == "debug":
@@ -201,8 +211,6 @@ elif env["platform"] == "osx":
         env.Append(LINKFLAGS=["-arch", env["macos_arch"]])
         env.Append(CCFLAGS=["-arch", env["macos_arch"]])
 
-    env.Append(CCFLAGS=["-std=c++17"])
-
     if env["macos_deployment_target"] != "default":
         env.Append(CCFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]])
         env.Append(LINKFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]])
@@ -245,14 +253,13 @@ elif env["platform"] == "ios":
     env["CXX"] = compiler_path + "clang++"
     env["AR"] = compiler_path + "ar"
     env["RANLIB"] = compiler_path + "ranlib"
+    env["SHLIBSUFFIX"] = ".dylib"
 
-    env.Append(CCFLAGS=["-std=c++17", "-arch", env["ios_arch"], "-isysroot", sdk_path])
+    env.Append(CCFLAGS=["-arch", env["ios_arch"], "-isysroot", sdk_path])
     env.Append(
         LINKFLAGS=[
             "-arch",
             env["ios_arch"],
-            "-framework",
-            "Cocoa",
             "-Wl,-undefined,dynamic_lookup",
             "-isysroot",
             sdk_path,
@@ -292,14 +299,21 @@ elif env["platform"] == "windows":
         # Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff.
         env = Environment(ENV=os.environ, tools=["mingw"])
         opts.Update(env)
-        # env = env.Clone(tools=['mingw'])
 
+        # Still need to use C++17.
+        env.Append(CCFLAGS=["-std=c++17"])
+        # Don't want lib prefixes
+        env["IMPLIBPREFIX"] = ""
+        env["SHLIBPREFIX"] = ""
+
+        # Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other).
         env["SPAWN"] = mySpawn
+        env.Replace(ARFLAGS=["q"])
 
     # Native or cross-compilation using MinGW
     if host_platform == "linux" or host_platform == "freebsd" or host_platform == "osx" or env["use_mingw"]:
         # These options are for a release build even using target=debug
-        env.Append(CCFLAGS=["-O3", "-std=c++17", "-Wwrite-strings"])
+        env.Append(CCFLAGS=["-O3", "-Wwrite-strings"])
         env.Append(
             LINKFLAGS=[
                 "--static",
@@ -314,9 +328,10 @@ elif env["platform"] == "android":
         # Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff.
         env = Environment(ENV=os.environ, tools=["mingw"])
         opts.Update(env)
-        # env = env.Clone(tools=['mingw'])
 
+        # Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other).
         env["SPAWN"] = mySpawn
+        env.Replace(ARFLAGS=["q"])
 
     # Verify NDK root
     if not "ANDROID_NDK_ROOT" in env:
@@ -382,11 +397,13 @@ elif env["platform"] == "android":
     env["CC"] = toolchain + "/bin/clang"
     env["CXX"] = toolchain + "/bin/clang++"
     env["AR"] = toolchain + "/bin/" + arch_info["tool_path"] + "-ar"
+    env["SHLIBSUFFIX"] = ".so"
 
     env.Append(
         CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"]
     )  # , '-fPIE', '-fno-addrsig', '-Oz'])
     env.Append(CCFLAGS=arch_info["ccflags"])
+    env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
 
     if env["target"] == "debug":
         env.Append(CCFLAGS=["-Og", "-g"])
@@ -474,8 +491,16 @@ elif env["platform"] == "javascript":
 elif env["platform"] == "osx":
     arch_suffix = env["macos_arch"]
 
-library = env.StaticLibrary(
-    target="bin/" + "libgodot-cpp.{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["LIBSUFFIX"]),
-    source=sources,
-)
-Default(library)
+library = None
+env["OBJSUFFIX"] = ".{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["OBJSUFFIX"])
+library_name = "libgodot-cpp.{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["LIBSUFFIX"])
+
+if env["build_library"]:
+    library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources)
+    Default(library)
+
+env["SHLIBSUFFIX"] = "{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["SHLIBSUFFIX"])
+env.Append(CPPPATH=[env.Dir(f) for f in ["gen/include", "include", "godot-headers"]])
+env.Append(LIBPATH=[env.Dir("bin")])
+env.Append(LIBS=library_name)
+Return("env")

+ 2 - 146
test/SConstruct

@@ -2,79 +2,7 @@
 import os
 import sys
 
-# default values, adapt them to your setup
-default_library_name = "libgdexample"
-default_target_path = "demo/bin/"
-
-# Local dependency paths, adapt them to your setup
-cpp_bindings_path = "../"
-# cpp_bindings_path = "godot-cpp/"
-godot_headers_path = cpp_bindings_path + "godot-headers/"
-cpp_library = "libgodot-cpp"
-
-# Try to detect the host platform automatically.
-# This is used if no `platform` argument is passed
-if sys.platform.startswith("linux"):
-    host_platform = "linux"
-elif sys.platform.startswith("freebsd"):
-    host_platform = "freebsd"
-elif sys.platform == "darwin":
-    host_platform = "osx"
-elif sys.platform == "win32" or sys.platform == "msys":
-    host_platform = "windows"
-else:
-    raise ValueError("Could not detect platform automatically, please specify with " "platform=<platform>")
-
-env = Environment(ENV=os.environ)
-
-opts = Variables([], ARGUMENTS)
-
-# Define our options
-opts.Add(EnumVariable("target", "Compilation target", "debug", allowed_values=("debug", "release"), ignorecase=2))
-opts.Add(
-    EnumVariable(
-        "platform",
-        "Compilation platform",
-        host_platform,
-        # We'll need to support these in due times
-        # allowed_values=("linux", "freebsd", "osx", "windows", "android", "ios", "javascript"),
-        allowed_values=("linux", "windows", "osx"),
-        ignorecase=2,
-    )
-)
-opts.Add(EnumVariable("bits", "Target platform bits", "64", ("32", "64")))
-opts.Add(BoolVariable("use_llvm", "Use the LLVM / Clang compiler", "no"))
-opts.Add(EnumVariable("macos_arch", "Target macOS architecture", "universal", ["universal", "x86_64", "arm64"]))
-opts.Add(PathVariable("target_path", "The path where the lib is installed.", default_target_path, PathVariable.PathAccept))
-opts.Add(PathVariable("target_name", "The library name.", default_library_name, PathVariable.PathAccept))
-
-# only support 64 at this time..
-bits = 64
-
-# Updates the environment with the option variables.
-opts.Update(env)
-# Generates help for the -h scons option.
-Help(opts.GenerateHelpText(env))
-
-# This makes sure to keep the session environment variables on Windows.
-# This way, you can run SCons in a Visual Studio 2017 prompt and it will find
-# all the required tools
-if host_platform == "windows" and env["platform"] != "android":
-    if env["bits"] == "64":
-        env = Environment(TARGET_ARCH="amd64")
-    elif env["bits"] == "32":
-        env = Environment(TARGET_ARCH="x86")
-
-    opts.Update(env)
-
-# Process some arguments
-if env["use_llvm"]:
-    env["CC"] = "clang"
-    env["CXX"] = "clang++"
-
-if env["platform"] == "":
-    print("No valid target platform selected.")
-    quit()
+env = SConscript("../SConstruct")
 
 # For the reference:
 # - CCFLAGS are compilation flags shared between C and C++
@@ -84,82 +12,10 @@ if env["platform"] == "":
 # - CPPDEFINES are for pre-processor defines
 # - LINKFLAGS are for linking flags
 
-if env["target"] == "debug":
-    env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"])
-
-# Check our platform specifics
-if env["platform"] == "osx":
-    env["target_path"] += "{}.{}.framework/".format(env["target_name"], env["target"])
-    cpp_library += ".osx"
-
-    if env["bits"] == "32":
-        raise ValueError("Only 64-bit builds are supported for the macOS target.")
-
-    if env["macos_arch"] == "universal":
-        env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
-        env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
-    else:
-        env.Append(LINKFLAGS=["-arch", env["macos_arch"]])
-        env.Append(CCFLAGS=["-arch", env["macos_arch"]])
-
-    env.Append(CXXFLAGS=["-std=c++17"])
-    if env["target"] == "debug":
-        env.Append(CCFLAGS=["-g", "-O2"])
-    else:
-        env.Append(CCFLAGS=["-g", "-O3"])
-
-    arch_suffix = env["macos_arch"]
-
-elif env["platform"] in ("x11", "linux"):
-    cpp_library += ".linux"
-    env.Append(CCFLAGS=["-fPIC"])
-    env.Append(CXXFLAGS=["-std=c++17"])
-    if env["target"] == "debug":
-        env.Append(CCFLAGS=["-g3", "-Og"])
-    else:
-        env.Append(CCFLAGS=["-g", "-O3"])
-
-    arch_suffix = str(bits)
-elif env["platform"] == "windows":
-    cpp_library += ".windows"
-    # This makes sure to keep the session environment variables on windows,
-    # that way you can run scons in a vs 2017 prompt and it will find all the required tools
-    env.Append(ENV=os.environ)
-
-    env.Append(CPPDEFINES=["WIN32", "_WIN32", "_WINDOWS", "_CRT_SECURE_NO_WARNINGS"])
-    env.Append(CCFLAGS=["-W3", "-GR"])
-    env.Append(CXXFLAGS=["-std:c++17"])
-    if env["target"] == "debug":
-        env.Append(CPPDEFINES=["_DEBUG"])
-        env.Append(CCFLAGS=["-EHsc", "-MDd", "-ZI", "-FS"])
-        env.Append(LINKFLAGS=["-DEBUG"])
-    else:
-        env.Append(CPPDEFINES=["NDEBUG"])
-        env.Append(CCFLAGS=["-O2", "-EHsc", "-MD"])
-
-    if not(env["use_llvm"]):
-        env.Append(CPPDEFINES=["TYPED_METHOD_BIND"])
-
-    arch_suffix = str(bits)
-
-# suffix our godot-cpp library
-cpp_library += "." + env["target"] + "." + arch_suffix
-
-# make sure our binding library is properly includes
-env.Append(CPPPATH=[".", godot_headers_path, cpp_bindings_path + "include/", cpp_bindings_path + "gen/include/"])
-env.Append(LIBPATH=[cpp_bindings_path + "bin/"])
-env.Append(LIBS=[cpp_library])
-
 # tweak this if you want to use different folders, or more folders, to store your source code in.
 env.Append(CPPPATH=["src/"])
 sources = Glob("src/*.cpp")
 
-if env["platform"] == "osx":
-    target_name = "{}.{}".format(env["target_name"], env["target"])
-else:
-    target_name = "{}.{}.{}.{}".format(env["target_name"], env["platform"], env["target"], arch_suffix)
-
-print(target_name)
-library = env.SharedLibrary(target=env["target_path"] + target_name, source=sources)
+library = env.SharedLibrary("demo/bin/libgdexample" + env["SHLIBSUFFIX"], source=sources)
 
 Default(library)