aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README.md1
-rw-r--r--backend/ninja/Ninja.cpp42
-rw-r--r--include/Conf.hpp4
-rw-r--r--include/FileUtil.hpp1
-rw-r--r--include/env.hpp2
-rwxr-xr-xscripts/mingw_ldd.py54
-rwxr-xr-xscripts/mingw_package.py31
-rwxr-xr-xscripts/package.py2
-rw-r--r--src/Conf.cpp6
-rw-r--r--src/FileUtil.cpp29
-rw-r--r--src/PkgConfig.cpp2
-rw-r--r--src/main.cpp29
13 files changed, 158 insertions, 46 deletions
diff --git a/.gitignore b/.gitignore
index 3a593c3..a0c1f8d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@ compile_commands.json
tests/sibs-build/
tests/compile_commands.json
cmake_msvc/
+scripts/__pycache__ \ No newline at end of file
diff --git a/README.md b/README.md
index 6bee538..d9f2d4c 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,7 @@ Libraries that are downloaded are available at: https://github.com/DEC05EBA/libr
# Cross compilation
Cross compilation currently only works from linux64 to win64 by using mingw-w64. You need to install `mingw-w64-gcc` and optionally `mingw-w64-pkg-config` if you want to use mingw-w64 system installed packages.
Cross compilation does currently not work if you have zig files as zig doesn't support libc when cross compiling at the moment.
+You can run `scripts/mingw_package.py` to automatically copy dynamic library dependencies of your executable to the same directory as the executable, so the library can be found when running the executable on windows; this also allows you to bundle your application and distribute it without external dependencies.
# IDE support
Sibs generates a compile_commands.json in the project root directory when executing `sibs build` and tools that support clang completion can be used, such as YouCompleteMe.
There are several editors that support YouCompleteMe, including Vim, Emacs and Visual Studio Code. Visual studio code now also supports clang completion with C/C++ extension by Microsoft; the extension will ask you which compile_commands.json file you want to use and you can choose the compile_commands.json in the project root directory.
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index 27608cc..bad224a 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -972,7 +972,12 @@ namespace backend
ninja::NinjaArg::createRaw("-pipe"),
ninja::NinjaArg::createRaw("-D_FILE_OFFSET_BITS=64"),
ninja::NinjaArg::createRaw("-Winvalid-pch"),
- ninja::NinjaArg::createRaw("-fstack-protector"),
+ });
+
+ if(config.getCompiler() != Compiler::MINGW_W64)
+ compileCCommand.push_back(ninja::NinjaArg::createRaw("-fstack-protector"));
+
+ compileCCommand.insert(compileCCommand.end(), {
ninja::NinjaArg::createRaw("-MMD"),
ninja::NinjaArg("-I" + config.getPackageName() + "@exe"),
ninja::NinjaArg::createRaw("$globalIncDir")
@@ -1243,10 +1248,9 @@ namespace backend
}
else
{
- // By statically compiling when using mingw w64, we dont have to bundle our application with several runtime dlls
if(config.getCompiler() == Compiler::MINGW_W64)
{
- packagingFlags = "-static -static-libgcc -static-libstdc++";
+ packagingFlags = "-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic";
}
}
@@ -1346,6 +1350,22 @@ namespace backend
});
}
#endif
+ if(config.getCompiler() == Compiler::MINGW_W64)
+ {
+ buildExeArgs.insert(buildExeArgs.end(), {
+ ninja::NinjaArg::createRaw("-lws2_32"),
+ ninja::NinjaArg::createRaw("-lwldap32"),
+ ninja::NinjaArg::createRaw("-lcrypt32"),
+ ninja::NinjaArg::createRaw("-ladvapi32"),
+ ninja::NinjaArg::createRaw("-lgdi32"),
+ ninja::NinjaArg::createRaw("-luser32"),
+ ninja::NinjaArg::createRaw("-luserenv"),
+ ninja::NinjaArg::createRaw("-lopengl32"),
+ ninja::NinjaArg::createRaw("-lglu32"),
+ ninja::NinjaArg::createRaw("-lwinpthread"),
+ ninja::NinjaArg::createRaw("-lshell32")
+ });
+ }
break;
}
case Compiler::MSVC:
@@ -1546,6 +1566,22 @@ namespace backend
});
}
#endif
+ if(config.getCompiler() == Compiler::MINGW_W64)
+ {
+ buildDynamicArgs.insert(buildDynamicArgs.end(), {
+ ninja::NinjaArg::createRaw("-lws2_32"),
+ ninja::NinjaArg::createRaw("-lwldap32"),
+ ninja::NinjaArg::createRaw("-lcrypt32"),
+ ninja::NinjaArg::createRaw("-ladvapi32"),
+ ninja::NinjaArg::createRaw("-lgdi32"),
+ ninja::NinjaArg::createRaw("-luser32"),
+ ninja::NinjaArg::createRaw("-luserenv"),
+ ninja::NinjaArg::createRaw("-lopengl32"),
+ ninja::NinjaArg::createRaw("-lglu32"),
+ ninja::NinjaArg::createRaw("-lwinpthread"),
+ ninja::NinjaArg::createRaw("-lshell32")
+ });
+ }
break;
}
case Compiler::MSVC:
diff --git a/include/Conf.hpp b/include/Conf.hpp
index 15c8471..3cd8cd5 100644
--- a/include/Conf.hpp
+++ b/include/Conf.hpp
@@ -198,13 +198,13 @@ namespace sibs
#if OS_TYPE == OS_TYPE_WINDOWS
#ifdef SIBS_ENV_32BIT
const Platform SYSTEM_PLATFORM = PLATFORM_WIN32;
- #define SYSTEM_PLATFORM_NAME "win32"
+ #define SYSTEM_PLATFORM_NAME L"win32"
#define CONFIG_SYSTEM_PLATFORM CONFIGS_GENERIC_OFFSET + 0
#define CONFIG_STATIC_DEBUG_PLATFORM CONFIGS_GENERIC_OFFSET + 1
#define CONFIG_STATIC_RELEASE_PLATFORM CONFIGS_GENERIC_OFFSET + 2
#else
const Platform SYSTEM_PLATFORM = PLATFORM_WIN64;
- #define SYSTEM_PLATFORM_NAME "win64"
+ #define SYSTEM_PLATFORM_NAME L"win64"
#define CONFIG_SYSTEM_PLATFORM CONFIGS_GENERIC_OFFSET + 3
#define CONFIG_STATIC_DEBUG_PLATFORM CONFIGS_GENERIC_OFFSET + 4
#define CONFIG_STATIC_RELEASE_PLATFORM CONFIGS_GENERIC_OFFSET + 5
diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp
index 0106c19..3e2e302 100644
--- a/include/FileUtil.hpp
+++ b/include/FileUtil.hpp
@@ -60,7 +60,6 @@ namespace sibs
Result<FileString> getRealPath(const _tinydir_char_t *path);
bool pathEquals(const std::string &path, const std::string &otherPath);
Result<u64> getFileLastModifiedTime(const _tinydir_char_t *path);
- Result<bool> copyFile(const FileString &src, const FileString &dst);
}
#endif //SIBS_FILEUTIL_HPP
diff --git a/include/env.hpp b/include/env.hpp
index 33e8068..d8b444b 100644
--- a/include/env.hpp
+++ b/include/env.hpp
@@ -30,7 +30,7 @@
#define WIN32_LEAN_AND_MEAN
#endif
- #include <Windows.h>
+ #include <windows.h>
#endif
#ifdef __linux__
diff --git a/scripts/mingw_ldd.py b/scripts/mingw_ldd.py
new file mode 100755
index 0000000..f678176
--- /dev/null
+++ b/scripts/mingw_ldd.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# WTFPL - Do What the Fuck You Want to Public License
+from __future__ import print_function
+import pefile
+import os
+import sys
+
+
+def get_dependency(filename):
+ deps = []
+ pe = pefile.PE(filename)
+ for imp in pe.DIRECTORY_ENTRY_IMPORT:
+ deps.append(imp.dll.decode())
+ return deps
+
+
+def dep_tree(root, prefix=None):
+ if not prefix:
+ arch = get_arch(root)
+ #print('Arch =', arch)
+ prefix = '/usr/'+arch+'-w64-mingw32/bin'
+ #print('Using default prefix', prefix)
+ dep_dlls = dict()
+
+ def dep_tree_impl(root, prefix):
+ for dll in get_dependency(root):
+ if dll in dep_dlls:
+ continue
+ full_path = os.path.join(prefix, dll)
+ if os.path.exists(full_path):
+ dep_dlls[dll] = full_path
+ dep_tree_impl(full_path, prefix=prefix)
+ else:
+ dep_dlls[dll] = 'not found'
+
+ dep_tree_impl(root, prefix)
+ return (dep_dlls)
+
+
+def get_arch(filename):
+ type2arch= {pefile.OPTIONAL_HEADER_MAGIC_PE: 'i686',
+ pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: 'x86_64'}
+ pe = pefile.PE(filename)
+ try:
+ return type2arch[pe.PE_TYPE]
+ except KeyError:
+ sys.stderr.write('Error: unknown architecture')
+ sys.exit(1)
+
+if __name__ == '__main__':
+ filename = sys.argv[1]
+ for dll, full_path in dep_tree(filename).items():
+ print(' ' * 7, dll, '=>', full_path)
+
diff --git a/scripts/mingw_package.py b/scripts/mingw_package.py
new file mode 100755
index 0000000..b304128
--- /dev/null
+++ b/scripts/mingw_package.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import mingw_ldd
+import shutil
+
+def usage():
+ print("usage: mingw-package.py <executable_path>")
+ exit(1)
+
+def main():
+ if len(sys.argv) != 2:
+ usage()
+
+ executable_path = sys.argv[1]
+ if not os.path.isfile(executable_path):
+ print("arg executable_path is not a file or it's a directory")
+ exit(2)
+ executable_path = os.path.realpath(executable_path)
+ executable_dir = os.path.dirname(executable_path)
+
+ print("Checking dynamic library dependencies of %s..." % executable_path)
+ deps = mingw_ldd.dep_tree(executable_path)
+ for dll, full_path in deps.items():
+ if full_path != "not found":
+ print("Copying %s to %s" % (dll, executable_dir))
+ shutil.copyfile(full_path, os.path.join(executable_dir, dll))
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/scripts/package.py b/scripts/package.py
index e3a6c52..6e861d9 100755
--- a/scripts/package.py
+++ b/scripts/package.py
@@ -95,7 +95,7 @@ def remove_blacklisted_libs(libs):
return new_libs
def main():
- if len(sys.argv) <= 4:
+ if len(sys.argv) != 5:
usage()
script_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
diff --git a/src/Conf.cpp b/src/Conf.cpp
index aabb957..38774e0 100644
--- a/src/Conf.cpp
+++ b/src/Conf.cpp
@@ -486,12 +486,12 @@ namespace sibs
return Result<bool>::Err(errMsg);
}
- if (!containsPlatform(config.getPlatforms(), SYSTEM_PLATFORM))
+ if (!containsPlatform(config.getPlatforms(), config.platform))
{
string errMsg = "The project ";
errMsg += config.getPackageName();
- errMsg += " does not support your platform (";
- errMsg += asString(SYSTEM_PLATFORM);
+ errMsg += " does not support your target platform (";
+ errMsg += asString(config.platform);
errMsg += ")";
return Result<bool>::Err(errMsg);
}
diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp
index e317304..ae24996 100644
--- a/src/FileUtil.cpp
+++ b/src/FileUtil.cpp
@@ -1,6 +1,5 @@
#include "../include/FileUtil.hpp"
#include <cstdio>
-#include <fstream>
#if OS_FAMILY == OS_FAMILY_POSIX
#include <unistd.h>
@@ -8,7 +7,7 @@
#include <pwd.h>
#include <fcntl.h>
#else
-#include <UserEnv.h>
+#include <userenv.h>
// Copied from linux libc sys/stat.h:
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
@@ -498,30 +497,4 @@ namespace sibs
return pathIndex == path.size() && otherPathIndex == otherPath.size();
}
-
- Result<bool> copyFile(const FileString &src, const FileString &dst)
- {
- ifstream srcFile(src.c_str(), ios::binary);
- if(!srcFile)
- {
- string errMsg = "Failed to open file ";
- errMsg += toUtf8(src);
- errMsg += ", reason: ";
- errMsg += strerror(errno);
- return Result<bool>::Err(errMsg);
- }
-
- ofstream dstFile(dst.c_str(), ios::binary);
- if(!dstFile)
- {
- string errMsg = "Failed to create/overwrite file ";
- errMsg += toUtf8(dst);
- errMsg += ", reason: ";
- errMsg += strerror(errno);
- return Result<bool>::Err(errMsg);
- }
-
- dstFile << srcFile.rdbuf();
- return Result<bool>::Ok(true);
- }
}
diff --git a/src/PkgConfig.cpp b/src/PkgConfig.cpp
index 9efc238..e8f742c 100644
--- a/src/PkgConfig.cpp
+++ b/src/PkgConfig.cpp
@@ -4,7 +4,7 @@
using namespace std;
-static sibs::FileString pkgConfigPath = "pkg-config";
+static sibs::FileString pkgConfigPath = TINYDIR_STRING("pkg-config");
// TODO: Do not use pkg-config program. The same functionality can easily be achieved
// by reading files in /usr/share/pkgconfig
diff --git a/src/main.cpp b/src/main.cpp
index 3ffb264..29f6ba3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1144,22 +1144,31 @@ static int packageProject(int argc, const _tinydir_char_t **argv)
case PackagingType::BUNDLE:
case PackagingType::BUNDLE_INSTALL:
{
- const char *bundleType = nullptr;
+ const _tinydir_char_t *bundleType = nullptr;
switch(packagingType)
{
case PackagingType::BUNDLE:
- bundleType = "--bundle";
+ bundleType = TINYDIR_STRING("--bundle");
break;
case PackagingType::BUNDLE_INSTALL:
- bundleType = "--bundle-install";
+ bundleType = TINYDIR_STRING("--bundle-install");
break;
}
- string packagePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/package"));
- string executablePath = toUtf8(projectPath + TINYDIR_STRING("/sibs-build/release/") + sibsConfig.getPackageName());
+ FileString packagePath = projectPath + TINYDIR_STRING("/sibs-build/package");
+ FileString executablePath = projectPath + TINYDIR_STRING("/sibs-build/release/") + toFileString(sibsConfig.getPackageName());
printf("Creating a package from project and dependencies...\n");
// args: executable_path program_version destination_path <--bundle|--bundle-install>
- FileString cmd = "python3 \"" + packageScriptPath + "\" \"" + executablePath + "\" \"" + sibsConfig.version + "\" \"" + packagePath + "\" " + bundleType;
+ FileString cmd = TINYDIR_STRING("python3 \"") +
+ packageScriptPath +
+ TINYDIR_STRING("\" \"") +
+ executablePath +
+ TINYDIR_STRING("\" \"") +
+ toFileString(sibsConfig.version) +
+ TINYDIR_STRING("\" \"") +
+ packagePath +
+ TINYDIR_STRING("\" ") +
+ bundleType;
Result<ExecResult> bundleResult = exec(cmd.c_str(), true);
if(!bundleResult)
{
@@ -1413,3 +1422,11 @@ int wmain(int argc, const _tinydir_char_t **argv)
usage();
return 0;
}
+
+// Mingw needs this
+#if OS_FAMILY == OS_FAMILY_WINDOWS
+int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ return wmain(__argc, (const _tinydir_char_t**)__wargv);
+}
+#endif \ No newline at end of file