#include "ni_common.h"
#include "tac_common.h"
-#include <algorithm>
-#include <cstdio>
-#include <cstring>
#include <vector>
+#include <stdlib.h>
+#include <sys/time.h>
-std::vector<std::string> getCmdArgs(char** begin, char** end)
-{
- std::vector<std::string> list;
- for (char** itr = begin+1; itr != end; itr++) {
- if (strncmp(*itr, "--", 2) != 0) {
- list.push_back(*itr);
- }
- }
- return list;
-}
-
-static void help(const char *argv0)
-{
- const char* helpDesc =
- "Usage: %s [OPTIONS] COMMAND <paths or pkg name>\n"
+void DisplayUsage() {
+ fprintf(stdout,
+ "\n"
+ "Dotnet Tool Version: 1.0\n"
"\n"
"Commands:\n"
- " --help - Display this screen\n"
- " --ni-system - Create NI under System DLLs\n"
- " --ni-dll - Create NI for DLL\n"
- " --ni-pkg - Create NI for package\n"
- " --ni-pkg-dll - Create NI for DLL in package\n"
- " --ni-dir - Create NI for directory\n"
- " --ni-reset-system - Remove System NI files\n"
- " --ni-reset-pkg - Remove App NI files\n"
- " --ni-reset-dir - Remove NI for directory\n"
- " --ni-regen-all-app - Re-generate All App NI files\n"
- " --tac-regen-all - Re-generate All TAC files\n"
- " --tac-restore-db - Restore TAC Database\n"
- " --tac-disable-pkg - Disable TAC for package\n"
- " --tac-enable-pkg - Enable TAC for package\n"
+ " -h, --help - Show this help message\n"
+ " --ni-system - Create NI under System DLLs\n"
+ " --ni-dll - Create NI for DLL\n"
+ " --ni-pkg - Create NI for package\n"
+ " --ni-pkg-dll - Create NI for DLL in package\n"
+ " --ni-dir - Create NI for directory\n"
+ " --ni-reset-system - Remove System NI files\n"
+ " --ni-reset-pkg - Remove App NI files\n"
+ " --ni-reset-dir - Remove NI for directory\n"
+ " --ni-regen-all-app - Re-generate All App NI files\n"
+ " --tac-regen-all - Re-generate All TAC files\n"
+ " --tac-restore-db - Restore TAC Database\n"
+ " --tac-disable-pkg - Disable TAC for package\n"
+ " --tac-enable-pkg - Enable TAC for package\n"
+ " --ibc-dir - Specify a directory containing IBC files\n"
"\n"
"Options:\n"
- " --r2r - Generate a Ready-To-Run image (disables /FragileNonVersionable)\n"
- " --compatibility - Compatibility mode for older versions of crossgen\n"
- " (replaces /r with /Trusted_Platform_Assemblies)\n"
- " --verbose - Display verbose information\n"
- " --instrument - Generate an instrumented image for profiling (enables /Tuning)\n"
+ " --r2r - Generate a Ready-To-Run image (disable: /FragileNonVersionable)\n"
+ " --compatibility - Compatibility mode for older versions of crossgen\n"
+ " (replaces /r with /Trusted_Platform_Assemblies)\n"
+ " --verbose - Display verbose information\n"
+ " --instrument - Generate an instrumented image for profiling (enable: /Tuning)\n"
+ "\n"
+ "Usage: dotnettool [options] [command] [arguments]\n"
"\n"
"Example:\n"
"1. Create native image for dlls and exes under platform directories\n"
- " # %s --ni-system\n"
+ " # dotnettool --ni-system\n"
"2. Create native image for dll\n"
- " # %s --ni-dll /usr/bin/Tizen.Runtime.dll\n"
+ " # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
"3. Create native image under the package's bin and lib directory\n"
- " # %s --ni-pkg org.tizen.FormsGallery\n"
+ " # dotnettool --ni-pkg org.tizen.FormsGallery\n"
"4. Regenerate native images for all installed .net packages with ready-to-run option\n"
- " # %s --r2r --ni-regen-all-app\n\n";
- printf(helpDesc, argv0, argv0, argv0, argv0, argv0);
+ " # dotnettool --r2r --ni-regen-all-app\n"
+ "5. Create native image for dll based on the IBC data\n"
+ " # dotnettool --ibc-dir /tmp/ibcdata/ --ni-dll /usr/bin/Tizen.Runtime.dll\n"
+ "\n");
}
int main(int argc, char* argv[])
{
- DWORD flags = 0;
- bool pkgMode = false;
- bool dllMode = false;
- bool dirMode = false;
- bool rmPkgMode = false;
- bool rmDirMode = false;
- bool pkgDllMode = false;
- bool disableTacMode = false;
- bool enableTacMode = false;
+ argc--;
+ argv++;
+
+ long starttime;
+ long endtime;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
+
+ if (argc <= 0) {
+ DisplayUsage();
+ return -1;
+ }
NiCommonOption option = {std::string(), std::string(), std::string()};
if (initNICommon(&option) != NI_ERROR_NONE) {
return -1;
}
- // Parse optional switches first.
- if (cmdOptionExists(argv, argv+argc, "--r2r")) {
- flags |= NI_FLAGS_ENABLER2R;
- }
- if (cmdOptionExists(argv, argv+argc, "--compatibility")) {
- flags |= NI_FLAGS_COMPATIBILITY;
- }
- if (cmdOptionExists(argv, argv+argc, "--instrument")) {
- flags |= NI_FLAGS_INSTRUMENT;
- }
- if (cmdOptionExists(argv, argv+argc, "--verbose")) {
- flags |= NI_FLAGS_VERBOSE;
+ //sh-3.2# dotnettool --[r2r|compatibility|instrument|verbose]
+ DWORD flags = 0;
+ std::vector<std::string> args;
+ for (char** it = argv; it != argv+argc; it++) {
+ if (!strncmp(*it, "-?", 2) || !strncmp(*it, "-h", 2) || !strncmp(*it, "--help", 6)) {
+ DisplayUsage();
+ return 0;
+ } else if (!strncmp(*it, "--r2r", 5)) {
+ flags |= NI_FLAGS_ENABLER2R;
+ } else if (!strncmp(*it, "--compatibility", 15)) {
+ flags |= NI_FLAGS_COMPATIBILITY;
+ } else if (!strncmp(*it, "--instrument", 12)) {
+ flags |= NI_FLAGS_INSTRUMENT;
+ } else if (!strncmp(*it, "--verbose", 9)) {
+ flags |= NI_FLAGS_VERBOSE;
+ } else {
+ args.push_back(*it);
+ }
}
- // The following commands are mutually exclusive.
- if (cmdOptionExists(argv, argv+argc, "--help")) {
- help(argv[0]);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-system")) {
- createNiPlatform(flags);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-dll")) {
- dllMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-pkg")) {
- pkgMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-dir")) {
- dirMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-system")) {
- removeNiPlatform();
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-pkg")) {
- rmPkgMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-dir")) {
- rmDirMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-pkg-dll")) {
- pkgDllMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-regen-all-app")) {
- regenerateAppNI(flags);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-regen-all")) {
- regenerateTACNI(flags);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-restore-db")) {
- restoreTACDB();
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-disable-pkg")) {
- disableTacMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-enable-pkg")) {
- enableTacMode = true;
- } else {
- help(argv[0]);
- return 0;
+ //sh-3.2# dotnettool --ibc-dir [ibcDirectory]
+ for (auto it = args.begin(); it != args.end(); ) {
+ if (*it == "--ibc-dir") {
+ it = args.erase(it);
+
+ std::string ibcFilePath = std::string(*it);
+ if (!isDirectoryExist(ibcFilePath)) {
+ fprintf(stderr, "IBC path is missing or not exist\n");
+ return -1;
+ }
+
+ setenv("COMPlus_IBCFileDir", const_cast<char *>(ibcFilePath.c_str()), 1);
+ setenv("COMPlus_UseIBCFile", const_cast<char *>("1"), 1);
+ } else {
+ ++it;
+ }
}
- std::vector<std::string> args = getCmdArgs(argv, argv+argc);
+ std::vector<std::string>::iterator it = args.begin();
+ std::string cmd = std::string(*it);
+ it = args.erase(it);
- if (args.size() < 1) {
- if (pkgMode || rmPkgMode || disableTacMode || enableTacMode) {
- fprintf(stderr, "Package name is missed\n");
- } else if (dllMode) {
- fprintf(stderr, "DLL path is missing.\n");
- } else if (rmDirMode) {
- fprintf(stderr, "Directory path is missing.\n");
+ //sh-3.2# dotnettool --ni-system
+ if (cmd == "--ni-system") {
+ int ret = createNiPlatform(flags);
+ if (ret != NI_ERROR_NONE) {
+ fprintf(stderr, "Failed to generate system NI\n");
}
- help(argv[0]);
- return -1;
- } else if (args.size() < 2) {
- if (pkgDllMode) {
- fprintf(stderr, "Package name or DLL path is missing.\n");
- help(argv[0]);
- return -1;
+ }
+ //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
+ else if (cmd == "--ni-dll") {
+ if (args.size() < 1) {
+ fprintf(stderr, "DLL path is missing\n");
+ }
+ while (it != args.end()) {
+ std::string dll = std::string(*it);
+ int ret = createNiDll(dll, flags);
+ if (ret != NI_ERROR_NONE) {
+ fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
+ break;
+ }
+ it = args.erase(it);
}
}
-
- if (pkgMode) {
- for (const std::string pkg : args) {
+ //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--ni-pkg") {
+ if (args.size() < 1) {
+ fprintf(stderr, "Package name is missing\n");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
// if there is AOTed dlls under package root, that is skiped.
int ret = createNiUnderPkgRoot(pkg, flags);
if (ret == NI_ERROR_INVALID_PACKAGE) {
fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
+ break;
} else if (ret != NI_ERROR_NONE) {
fprintf(stderr, "Failed to generate NI file [%s]\n", pkg.c_str());
- return -1;
+ break;
}
ret = createTACPkgRoot(pkg, flags);
- if (ret == TAC_ERROR_INVALID_PACKAGE) {
+ if (ret == NI_ERROR_INVALID_PACKAGE) {
fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != TAC_ERROR_NONE) {
+ break;
+ } else if (ret != NI_ERROR_NONE) {
fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkg.c_str());
- return -1;
+ break;
}
+ it = args.erase(it);
}
- } else if (pkgDllMode) {
- int ret = createNiDllUnderPkgRoot(args[0], args[1], flags);
- if (ret == NI_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", args[0].c_str());
- return -1;
- } else if (ret == NI_ERROR_ALREADY_EXIST) {
- // skip for already exist case
- return -1;
- } else if (ret != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to generate NI file [%s]\n", args[1].c_str());
- return -1;
+ }
+ //sh-3.2# dotnettool --ni-pkg-dll [pkgId] [pkgAssemblyPath] [pkgAssemblyPath] ...
+ else if (cmd == "--ni-pkg-dll") {
+ if (args.size() < 2) {
+ fprintf(stderr, "Package name or DLL path is missing\n");
+ } else {
+ std::string pkg = std::string(*it);
+ it = args.erase(it);
+ while (it != args.end()) {
+ std::string dll = std::string(*it);
+ int ret = createNiDllUnderPkgRoot(pkg, dll, flags);
+ if (ret == NI_ERROR_INVALID_PACKAGE) {
+ fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
+ break;
+ } else if (ret != NI_ERROR_NONE) {
+ fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
}
- } else if (rmPkgMode) {
- for (const std::string pkg : args) {
+ }
+ //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
+ else if (cmd == "--ni-dir") {
+ if (args.size() < 1) {
+ fprintf(stderr, "Directory path is missing\n");
+ }
+ while (it != args.end()) {
+ const std::string dir[] = {std::string(*it)};
+ int ret = createNiUnderDirs(dir, 1, flags);
+ if (ret != NI_ERROR_NONE) {
+ fprintf(stderr, "Failed to generate NI directory\n");
+ break;
+ }
+ it = args.erase(it);
+ }
+ }
+ //sh-3.2# dotnettool --ni-reset-system
+ else if (cmd == "--ni-reset-system") {
+ removeNiPlatform();
+ }
+ //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--ni-reset-pkg") {
+ if (args.size() < 1) {
+ fprintf(stderr, "Package name is missing\n");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
int ret = removeNiUnderPkgRoot(pkg);
if (ret == NI_ERROR_INVALID_PACKAGE) {
fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
+ break;
} else if (ret != NI_ERROR_NONE) {
fprintf(stderr, "Failed to remove dlls for given package [%s]\n", pkg.c_str());
- return -1;
+ break;
}
ret = resetTACPackage(pkg);
if (ret == TAC_ERROR_INVALID_PACKAGE) {
fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
+ break;
} else if (ret != TAC_ERROR_NONE) {
fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkg.c_str());
- return -1;
+ break;
}
+ it = args.erase(it);
}
- } else if (rmDirMode) {
- removeNiUnderDirs(args.data(), args.size());
- } else if (dllMode) {
- // donot return error code for generation failure.
- // we have to run crossgen for all input dlls.
- for (const std::string dll : args) {
- int ret = createNiDll(dll, flags);
- if (ret == NI_ERROR_ALREADY_EXIST) {
- // skip for already exist case
- } else if (ret != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
- }
+ }
+ //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
+ else if (cmd == "--ni-reset-dir") {
+ if (args.size() < 1) {
+ fprintf(stderr, "Directory path is missing\n");
}
- } else if (dirMode) {
- createNiUnderDirs(args.data(), args.size(), flags);
- } else if (disableTacMode) {
- for (const std::string pkg : args) {
- int ret = disableTACPackage(pkg);
+ while (it != args.end()) {
+ const std::string dir[] = {std::string(*it)};
+ removeNiUnderDirs(dir, 1);
+ it = args.erase(it);
+ }
+ }
+ //sh-3.2# dotnettool --ni-regen-all-app
+ else if (cmd == "--ni-regen-all-app") {
+ int ret = regenerateAppNI(flags);
+ if (ret != NI_ERROR_NONE) {
+ fprintf(stderr, "Failed to regenerate all app NI\n");
+ }
+ }
+ //sh-3.2# dotnettool --tac-regen-all
+ else if (cmd == "--tac-regen-all") {
+ int ret = regenerateTACNI(flags);
+ if (ret != NI_ERROR_NONE) {
+ fprintf(stderr, "Failed to regenerate all TAC\n");
+ }
+ }
+ //sh-3.2# dotnettool --tac-restore-db
+ else if (cmd == "--tac-restore-db") {
+ int ret = restoreTACDB();
+ if (ret != TAC_ERROR_NONE) {
+ fprintf(stderr, "Failed to restore TAC db\n");
+ }
+ }
+ //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--tac-enable-pkg") {
+ if (args.size() < 1) {
+ fprintf(stderr, "Package name is missing\n");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ int ret = enableTACPackage(pkg);
if (ret == TAC_ERROR_INVALID_PACKAGE) {
fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
+ break;
} else if (ret != TAC_ERROR_NONE) {
- fprintf(stderr, "Failed to disable tac [%s]\n", pkg.c_str());
- return -1;
+ fprintf(stderr, "Failed to enable tac [%s]\n", pkg.c_str());
+ break;
}
+ it = args.erase(it);
}
- } else if (enableTacMode) {
- for (const std::string pkg : args) {
- int ret = enableTACPackage(pkg);
+ }
+ //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--tac-disable-pkg") {
+ if (args.size() < 1) {
+ fprintf(stderr, "Package name is missing\n");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ int ret = disableTACPackage(pkg);
if (ret == TAC_ERROR_INVALID_PACKAGE) {
fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
+ break;
} else if (ret != TAC_ERROR_NONE) {
- fprintf(stderr, "Failed to enable tac [%s]\n", pkg.c_str());
- return -1;
+ fprintf(stderr, "Failed to disable tac [%s]\n", pkg.c_str());
+ break;
}
+ it = args.erase(it);
}
}
+ else {
+ fprintf(stderr, "Unknown option [%s]\n", cmd.c_str());
+ DisplayUsage();
+ }
+
+ gettimeofday(&tv, NULL);
+ endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
+ fprintf(stdout, "\nSpend time for dotnettool is [%d]ms\n", (int)(endtime - starttime));
+
return 0;
}
return 0;
}
+static bool isCoreLibPrepared(DWORD flags)
+{
+ if (flags & NI_FLAGS_ENABLER2R) {
+ return true;
+ }
+
+ std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
+ if (isFileExist(coreLibBackup)) {
+ return true;
+ } else {
+ fprintf(stderr, "The native image of System.Private.CoreLib does not exist\n"
+ "Run the command to create the native image\n"
+ "# dotnettool --ni-dll /usr/share/dotnet.tizen/netcoreapp/System.Private.CoreLib.dll\n\n");
+ return false;
+ }
+}
+
static void createCoreLibNI(DWORD flags)
{
std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll");
std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
if (!isFileExist(coreLibBackup)) {
-
if (!crossgen(coreLib, std::string(), flags)) {
if (rename(coreLib.c_str(), coreLibBackup.c_str())) {
fprintf(stderr, "Failed to rename System.Private.CoreLib.dll\n");
}
-void createNiPlatform(DWORD flags)
+ni_error_e createNiPlatform(DWORD flags)
{
+ createCoreLibNI(flags);
+
const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()};
- createNiUnderDirs(platformDirs, 2, flags);
+ return createNiUnderDirs(platformDirs, 2, flags);
}
ni_error_e createNiDll(const std::string& dllPath, DWORD flags)
{
- createCoreLibNI(flags);
- // System.Private.CoreLib.dll is generated in the createCoreLibNI function.
- // Skip if input dll is System.Private.CoreLib.dll
- if (dllPath.find("System.Private.CoreLib.dll") != std::string::npos) {
- return NI_ERROR_NONE;
+ if (!isCoreLibPrepared(flags)) {
+ return NI_ERROR_CORE_NI_FILE;
}
return crossgen(dllPath, std::string(), flags);
ni_error_e createTACPkgRoot(const std::string& pkgId, DWORD flags)
{
+ if (!isCoreLibPrepared(flags)) {
+ return NI_ERROR_CORE_NI_FILE;
+ }
+
std::string pkgRoot;
if (getRootPath(pkgId, pkgRoot) < 0) {
return NI_ERROR_INVALID_PACKAGE;
return NI_ERROR_NONE;
}
-void createNiUnderDirs(const std::string rootPaths[], int count, DWORD flags)
+ni_error_e createNiUnderDirs(const std::string rootPaths[], int count, DWORD flags)
{
- createCoreLibNI(flags);
+ if (!isCoreLibPrepared(flags)) {
+ return NI_ERROR_CORE_NI_FILE;
+ }
std::string appPaths;
for (int i = 0; i < count; i++) {
}
tpaAssemblies.clear();
+ return NI_ERROR_NONE;
}
ni_error_e createNiUnderPkgRoot(const std::string& pkgId, DWORD flags)
std::string paths[] = {binDir, libDir, tacDir};
flags |= NI_FLAGS_APPNI;
- createNiUnderDirs(paths, 3, flags);
-
- return NI_ERROR_NONE;
+ return createNiUnderDirs(paths, 3, flags);
}
ni_error_e createNiDllUnderPkgRoot(const std::string& pkgId, const std::string& dllPath, DWORD flags)
{
+ if (!isCoreLibPrepared(flags)) {
+ return NI_ERROR_CORE_NI_FILE;
+ }
+
std::string pkgRoot;
if (getRootPath(pkgId, pkgRoot) < 0) {
return NI_ERROR_INVALID_PACKAGE;
ni_error_e regenerateAppNI(DWORD flags)
{
+ if (!isCoreLibPrepared(flags)) {
+ return NI_ERROR_CORE_NI_FILE;
+ }
+
int ret = 0;
pkgmgrinfo_appinfo_metadata_filter_h handle;
ni_error_e regenerateTACNI(DWORD flags)
{
+ if (!isCoreLibPrepared(flags)) {
+ return NI_ERROR_CORE_NI_FILE;
+ }
+
const std::string tacDir[] = {__DOTNET_DIR};
removeNiUnderDirs(tacDir, 1);